@appcorp/fusion-storybook 0.2.40 → 0.2.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/base-modules/admission/constants.d.ts +5 -17
- package/base-modules/admission/constants.js +12 -7
- package/base-modules/admission/context/use-admission-module.js +11 -48
- package/base-modules/admission/filter.js +23 -3
- package/base-modules/admission/form.js +49 -19
- package/base-modules/attendance/context.js +3 -37
- package/base-modules/attendance/form.js +26 -10
- package/base-modules/attendance/more-actions.js +34 -25
- package/base-modules/campus/context.js +7 -7
- package/base-modules/class/cache.js +0 -1
- package/base-modules/class/context.js +10 -48
- package/base-modules/class/more-actions.js +0 -2
- package/base-modules/course/context.js +3 -37
- package/base-modules/course/form.js +91 -292
- package/base-modules/discount-code/constants.d.ts +5 -0
- package/base-modules/discount-code/constants.js +5 -0
- package/base-modules/discount-code/context.d.ts +1 -0
- package/base-modules/discount-code/context.js +40 -39
- package/base-modules/discount-code/form.js +21 -15
- package/base-modules/discount-code/more-actions.js +1 -1
- package/base-modules/enrollment/context.js +3 -37
- package/base-modules/enrollment/form.js +38 -11
- package/base-modules/enrollment/more-actions.js +0 -2
- package/base-modules/expense/constants.js +1 -1
- package/base-modules/expense/context.js +5 -32
- package/base-modules/expense/filter.js +50 -3
- package/base-modules/expense/form.js +82 -6
- package/base-modules/family/context.js +7 -38
- package/base-modules/family-member/context.js +7 -39
- package/base-modules/fee-structure/context.js +1 -25
- package/base-modules/fee-structure/form.js +77 -89
- package/base-modules/fee-structure/more-actions.js +0 -2
- package/base-modules/rbac/context.d.ts +1 -0
- package/base-modules/rbac/context.js +23 -32
- package/base-modules/school/context.js +1 -1
- package/base-modules/school/form.js +34 -14
- package/base-modules/section/context.d.ts +1 -0
- package/base-modules/section/context.js +40 -47
- package/base-modules/section/form.js +25 -80
- package/base-modules/section/more-actions.js +0 -2
- package/base-modules/section/view.js +9 -7
- package/base-modules/student-fee/context/use-student-fee-module.d.ts +1 -0
- package/base-modules/student-fee/context/use-student-fee-module.js +48 -32
- package/base-modules/student-fee/context.d.ts +1 -1
- package/base-modules/student-fee/context.js +1 -1
- package/base-modules/student-fee/filter.js +23 -3
- package/base-modules/student-fee/form.js +93 -174
- package/base-modules/student-fee/view.d.ts +7 -1
- package/base-modules/student-fee/view.js +17 -20
- package/base-modules/student-profile/constants.d.ts +0 -6
- package/base-modules/student-profile/constants.js +1 -3
- package/base-modules/student-profile/context/use-student-profile-module.d.ts +1 -0
- package/base-modules/student-profile/context/use-student-profile-module.js +62 -55
- package/base-modules/student-profile/context.d.ts +1 -1
- package/base-modules/student-profile/context.js +1 -1
- package/base-modules/student-profile/filter.js +23 -3
- package/base-modules/student-profile/form.js +35 -3
- package/base-modules/subject/context.d.ts +1 -0
- package/base-modules/subject/context.js +38 -47
- package/base-modules/subject/more-actions.js +0 -2
- package/base-modules/teacher/constants.d.ts +0 -6
- package/base-modules/teacher/constants.js +0 -2
- package/base-modules/teacher/context.d.ts +1 -0
- package/base-modules/teacher/context.js +58 -39
- package/base-modules/teacher/form.js +46 -11
- package/base-modules/teacher/more-actions.js +0 -2
- package/base-modules/user/context/use-user-module.d.ts +1 -0
- package/base-modules/user/context/use-user-module.js +36 -32
- package/base-modules/user/context.js +1 -1
- package/base-modules/user/filter.js +6 -4
- package/base-modules/user/form.js +29 -5
- package/base-modules/user/more-actions.js +9 -7
- package/base-modules/user/view.js +3 -1
- package/base-modules/workspace/form.js +18 -8
- package/base-modules/workspace-user/context.d.ts +2 -1
- package/base-modules/workspace-user/context.js +31 -29
- package/package.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/base-modules/admission/cache.d.ts +0 -14
- package/base-modules/admission/cache.js +0 -31
- package/base-modules/attendance/cache.d.ts +0 -14
- package/base-modules/attendance/cache.js +0 -31
- package/base-modules/course/cache.d.ts +0 -14
- package/base-modules/course/cache.js +0 -31
- package/base-modules/enrollment/cache.d.ts +0 -14
- package/base-modules/enrollment/cache.js +0 -31
- package/base-modules/expense/cache.d.ts +0 -14
- package/base-modules/expense/cache.js +0 -31
- package/base-modules/family/cache.d.ts +0 -14
- package/base-modules/family/cache.js +0 -31
- package/base-modules/family-member/cache.d.ts +0 -14
- package/base-modules/family-member/cache.js +0 -31
- package/base-modules/rbac/cache.d.ts +0 -27
- package/base-modules/rbac/cache.js +0 -46
- package/base-modules/student-fee/cache.d.ts +0 -15
- package/base-modules/student-fee/cache.js +0 -21
- package/base-modules/workspace-user/cache.d.ts +0 -14
- package/base-modules/workspace-user/cache.js +0 -31
|
@@ -7,26 +7,14 @@
|
|
|
7
7
|
* - Table Configuration
|
|
8
8
|
* - Status Options
|
|
9
9
|
*/
|
|
10
|
-
import { ADMISSION_STATUS } from "../../type";
|
|
10
|
+
import { ADMISSION_STATUS, GENDER } from "../../type";
|
|
11
11
|
export declare const pageLimit: number;
|
|
12
12
|
export declare const ADMISSION_API_ROUTES: Record<string, string>;
|
|
13
13
|
export declare const ADMISSION_STATUS_OPTIONS: {
|
|
14
14
|
label: string;
|
|
15
15
|
value: ADMISSION_STATUS;
|
|
16
16
|
}[];
|
|
17
|
-
export declare const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
readonly label: "Approved";
|
|
22
|
-
readonly value: ADMISSION_STATUS.APPROVED;
|
|
23
|
-
}, {
|
|
24
|
-
readonly label: "Rejected";
|
|
25
|
-
readonly value: ADMISSION_STATUS.REJECTED;
|
|
26
|
-
}, {
|
|
27
|
-
readonly label: "Enrolled";
|
|
28
|
-
readonly value: ADMISSION_STATUS.ENROLLED;
|
|
29
|
-
}, {
|
|
30
|
-
readonly label: "Cancelled";
|
|
31
|
-
readonly value: ADMISSION_STATUS.CANCELLED;
|
|
32
|
-
}];
|
|
17
|
+
export declare const GENDER_OPTIONS: {
|
|
18
|
+
label: string;
|
|
19
|
+
value: GENDER;
|
|
20
|
+
}[];
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* - Table Configuration
|
|
8
8
|
* - Status Options
|
|
9
9
|
*/
|
|
10
|
-
import { ADMISSION_STATUS } from "../../type";
|
|
10
|
+
import { ADMISSION_STATUS, GENDER } from "../../type";
|
|
11
11
|
// ============================================================================
|
|
12
12
|
// PAGE CONFIGURATION
|
|
13
13
|
// ============================================================================
|
|
@@ -28,10 +28,15 @@ export const ADMISSION_STATUS_OPTIONS = [
|
|
|
28
28
|
{ label: "Enrolled", value: ADMISSION_STATUS.ENROLLED },
|
|
29
29
|
{ label: "Cancelled", value: ADMISSION_STATUS.CANCELLED },
|
|
30
30
|
];
|
|
31
|
-
export const
|
|
32
|
-
{ label: "
|
|
33
|
-
{ label: "
|
|
34
|
-
{ label: "
|
|
35
|
-
{ label: "Enrolled", value: ADMISSION_STATUS.ENROLLED },
|
|
36
|
-
{ label: "Cancelled", value: ADMISSION_STATUS.CANCELLED },
|
|
31
|
+
export const GENDER_OPTIONS = [
|
|
32
|
+
{ label: "Male", value: GENDER.MALE },
|
|
33
|
+
{ label: "Female", value: GENDER.FEMALE },
|
|
34
|
+
{ label: "Other", value: GENDER.OTHER },
|
|
37
35
|
];
|
|
36
|
+
// export const ADMISSION_STATUS_OPTIONS_CONST = [
|
|
37
|
+
// { label: "Pending", value: ADMISSION_STATUS.PENDING },
|
|
38
|
+
// { label: "Approved", value: ADMISSION_STATUS.APPROVED },
|
|
39
|
+
// { label: "Rejected", value: ADMISSION_STATUS.REJECTED },
|
|
40
|
+
// { label: "Enrolled", value: ADMISSION_STATUS.ENROLLED },
|
|
41
|
+
// { label: "Cancelled", value: ADMISSION_STATUS.CANCELLED },
|
|
42
|
+
// ] as const;
|
|
@@ -7,16 +7,12 @@ import { useModuleEntityV2, } from "@react-pakistan/util-functions/hooks/use-mod
|
|
|
7
7
|
import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
|
|
8
8
|
import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
|
|
9
9
|
import { ADMISSION_STATUS, GENDER, } from "../../../type";
|
|
10
|
-
import { ADMISSION_API_ROUTES
|
|
10
|
+
import { ADMISSION_API_ROUTES } from "../constants";
|
|
11
11
|
import { admissionFormValidation } from "../validate";
|
|
12
|
-
import { getCachedAdmissions, invalidateAdmissionsCache } from "../cache";
|
|
13
12
|
import { getCachedWorkspaceSync } from "../../workspace/cache";
|
|
14
13
|
import { generateAdmissionReceiptPDF, } from "../../../utils/admission-pdf";
|
|
15
14
|
import { formatNumber } from "@react-pakistan/util-functions/general/format-number";
|
|
16
15
|
import { formatPhoneDisplay } from "@react-pakistan/util-functions/general/format-phone-display";
|
|
17
|
-
import { invalidateFamiliesCache } from "../../family/cache";
|
|
18
|
-
import { invalidateFamilyMembersCache } from "../../family-member/cache";
|
|
19
|
-
import { invalidateStudentProfilesCache } from "../../student-profile/cache";
|
|
20
16
|
import { Filter, Plus } from "lucide-react";
|
|
21
17
|
import { ADMISSION_DRAWER, ADMISSION_ACTION_TYPES, useAdmissionContext, } from "../context";
|
|
22
18
|
export const useAdmissionModule = () => {
|
|
@@ -130,12 +126,6 @@ export const useAdmissionModule = () => {
|
|
|
130
126
|
]);
|
|
131
127
|
const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
|
|
132
128
|
const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
|
|
133
|
-
const isDefaultListState = state.currentPage === 1 &&
|
|
134
|
-
state.pageLimit === pageLimit &&
|
|
135
|
-
!debouncedQuery &&
|
|
136
|
-
state.filterAdmissionStatus === undefined &&
|
|
137
|
-
state.filterStartDate === undefined &&
|
|
138
|
-
state.filterEndDate === undefined;
|
|
139
129
|
// ============================================================================
|
|
140
130
|
// 1.4.3 UTILITIES
|
|
141
131
|
// ============================================================================
|
|
@@ -198,7 +188,6 @@ export const useAdmissionModule = () => {
|
|
|
198
188
|
return;
|
|
199
189
|
}
|
|
200
190
|
if (data) {
|
|
201
|
-
invalidateAdmissionsCache();
|
|
202
191
|
showToast(t("messagesSaveSuccess"), TOAST_VARIANT.SUCCESS);
|
|
203
192
|
resetFormAndCloseDrawer();
|
|
204
193
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
@@ -275,7 +264,6 @@ export const useAdmissionModule = () => {
|
|
|
275
264
|
return;
|
|
276
265
|
}
|
|
277
266
|
if (data) {
|
|
278
|
-
invalidateAdmissionsCache();
|
|
279
267
|
showToast(t("messagesDeleteSuccess"), TOAST_VARIANT.SUCCESS);
|
|
280
268
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
281
269
|
}
|
|
@@ -298,7 +286,6 @@ export const useAdmissionModule = () => {
|
|
|
298
286
|
updateParams,
|
|
299
287
|
headers: {
|
|
300
288
|
"Content-Type": "application/json",
|
|
301
|
-
// "x-api-token": process.env.NEXT_PUBLIC_API_KEY!,
|
|
302
289
|
},
|
|
303
290
|
});
|
|
304
291
|
// ============================================================================
|
|
@@ -339,7 +326,7 @@ export const useAdmissionModule = () => {
|
|
|
339
326
|
});
|
|
340
327
|
}, [dispatch, byIdFetchNow]);
|
|
341
328
|
const handleDelete = useCallback((row) => {
|
|
342
|
-
if (!confirm(t("
|
|
329
|
+
if (!confirm(t("messagesDeleteConfirmation")))
|
|
343
330
|
return;
|
|
344
331
|
deleteFetchNow === null || deleteFetchNow === void 0 ? void 0 : deleteFetchNow(undefined, {
|
|
345
332
|
body: JSON.stringify({ id: row === null || row === void 0 ? void 0 : row.id }),
|
|
@@ -484,10 +471,6 @@ export const useAdmissionModule = () => {
|
|
|
484
471
|
body: JSON.stringify({ admissionId: tableRow === null || tableRow === void 0 ? void 0 : tableRow.id }),
|
|
485
472
|
});
|
|
486
473
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
487
|
-
invalidateAdmissionsCache();
|
|
488
|
-
invalidateFamiliesCache();
|
|
489
|
-
invalidateFamilyMembersCache();
|
|
490
|
-
invalidateStudentProfilesCache();
|
|
491
474
|
if (data) {
|
|
492
475
|
showToast(t("messagesAdmitSuccess"), TOAST_VARIANT.SUCCESS);
|
|
493
476
|
}
|
|
@@ -548,7 +531,6 @@ export const useAdmissionModule = () => {
|
|
|
548
531
|
payload: { form: { aiAnalysis: result.aiAnalysis } },
|
|
549
532
|
});
|
|
550
533
|
}
|
|
551
|
-
invalidateAdmissionsCache();
|
|
552
534
|
(_b = listFetchNowRef.current) === null || _b === void 0 ? void 0 : _b.call(listFetchNowRef);
|
|
553
535
|
generateThemeToast({
|
|
554
536
|
description: `${t("messagesAnalyzeSuccess")} ${(_c = result === null || result === void 0 ? void 0 : result.score) !== null && _c !== void 0 ? _c : "N/A"} — ${(_d = result === null || result === void 0 ? void 0 : result.status) !== null && _d !== void 0 ? _d : ""}`,
|
|
@@ -642,14 +624,14 @@ export const useAdmissionModule = () => {
|
|
|
642
624
|
{
|
|
643
625
|
enabled: true,
|
|
644
626
|
handleOnClick: handleFilters,
|
|
645
|
-
label: t("
|
|
627
|
+
label: t("actionsButtonFilters"),
|
|
646
628
|
order: 1,
|
|
647
629
|
icon: Filter,
|
|
648
630
|
},
|
|
649
631
|
{
|
|
650
632
|
enabled: true,
|
|
651
633
|
handleOnClick: handleCreate,
|
|
652
|
-
label: t("
|
|
634
|
+
label: t("actionsButtonAddAdmission"),
|
|
653
635
|
order: 2,
|
|
654
636
|
icon: Plus,
|
|
655
637
|
},
|
|
@@ -658,39 +640,39 @@ export const useAdmissionModule = () => {
|
|
|
658
640
|
{
|
|
659
641
|
enabled: true,
|
|
660
642
|
handleOnClick: handleView,
|
|
661
|
-
label: t("
|
|
643
|
+
label: t("actionsButtonView"),
|
|
662
644
|
order: 1,
|
|
663
645
|
},
|
|
664
646
|
{
|
|
665
647
|
enabled: (row) => (row === null || row === void 0 ? void 0 : row.status) === ADMISSION_STATUS.PENDING,
|
|
666
648
|
handleOnClick: handleEdit,
|
|
667
|
-
label: t("
|
|
649
|
+
label: t("actionsButtonEdit"),
|
|
668
650
|
order: 2,
|
|
669
651
|
},
|
|
670
652
|
{
|
|
671
653
|
enabled: (row) => (row === null || row === void 0 ? void 0 : row.status) === ADMISSION_STATUS.PENDING,
|
|
672
654
|
handleOnClick: handleDelete,
|
|
673
|
-
label: t("
|
|
655
|
+
label: t("actionsButtonDelete"),
|
|
674
656
|
order: 3,
|
|
675
657
|
variant: "destructive",
|
|
676
658
|
},
|
|
677
659
|
{
|
|
678
660
|
enabled: true,
|
|
679
661
|
handleOnClick: handlePrint,
|
|
680
|
-
label: t("
|
|
662
|
+
label: t("actionsButtonPrintPdf"),
|
|
681
663
|
order: 4,
|
|
682
664
|
},
|
|
683
665
|
{
|
|
684
666
|
enabled: (row) => hasGeminiSecrets &&
|
|
685
667
|
(row === null || row === void 0 ? void 0 : row.status) === ADMISSION_STATUS.PENDING,
|
|
686
668
|
handleOnClick: handleAnalyze,
|
|
687
|
-
label: t("
|
|
669
|
+
label: t("actionsButtonAnalyzeWithAi"),
|
|
688
670
|
order: 5,
|
|
689
671
|
},
|
|
690
672
|
{
|
|
691
673
|
enabled: (row) => (row === null || row === void 0 ? void 0 : row.status) !== ADMISSION_STATUS.APPROVED,
|
|
692
674
|
handleOnClick: handleAddStudent,
|
|
693
|
-
label: t("
|
|
675
|
+
label: t("actionsButtonAddStudent"),
|
|
694
676
|
order: 6,
|
|
695
677
|
},
|
|
696
678
|
], [
|
|
@@ -713,31 +695,12 @@ export const useAdmissionModule = () => {
|
|
|
713
695
|
// ============================================================================
|
|
714
696
|
// 1.4.9 EFFECTS
|
|
715
697
|
// ============================================================================
|
|
716
|
-
// Initial load + re-fetch on page/search/filter change via cache
|
|
717
698
|
useEffect(() => {
|
|
718
699
|
var _a;
|
|
719
700
|
if (!(workspace === null || workspace === void 0 ? void 0 : workspace.id))
|
|
720
701
|
return;
|
|
721
|
-
if (isDefaultListState) {
|
|
722
|
-
(async () => {
|
|
723
|
-
try {
|
|
724
|
-
const { count, items } = await getCachedAdmissions({
|
|
725
|
-
params: listParams,
|
|
726
|
-
});
|
|
727
|
-
dispatch({
|
|
728
|
-
type: ADMISSION_ACTION_TYPES.SET_ITEMS,
|
|
729
|
-
payload: { items: items || [], count: count || 0 },
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
catch (_a) {
|
|
733
|
-
showToast(t("messagesFetchFailed"), TOAST_VARIANT.ERROR);
|
|
734
|
-
}
|
|
735
|
-
})();
|
|
736
|
-
return;
|
|
737
|
-
}
|
|
738
702
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
739
|
-
}, [
|
|
740
|
-
// Sync ref to always point at latest listFetchNow (avoids stale closure in callbacks)
|
|
703
|
+
}, [listParams, workspace === null || workspace === void 0 ? void 0 : workspace.id]);
|
|
741
704
|
useEffect(() => {
|
|
742
705
|
listFetchNowRef.current = listFetchNow;
|
|
743
706
|
}, [listFetchNow]);
|
|
@@ -6,21 +6,41 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
* Filter UI for admission records. Uses the module state pattern:
|
|
7
7
|
* `const { state, handleChange, handleSetStartDate, handleSetEndDate } = useAdmissionModule()`
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import { useEnhancedCombobox } from "@appcorp/shadcn/hooks/use-enhanced-combobox";
|
|
10
10
|
import { EnhancedRadio } from "@appcorp/shadcn/components/enhanced-radio";
|
|
11
11
|
import { useTranslations } from "next-intl";
|
|
12
|
-
import { ADMISSION_STATUS_OPTIONS } from "./constants";
|
|
12
|
+
import { ADMISSION_STATUS_OPTIONS, ADMISSION_API_ROUTES } from "./constants";
|
|
13
13
|
import { useAdmissionModule } from "./context";
|
|
14
14
|
export const AdmissionFilter = () => {
|
|
15
15
|
const { state, handleChange, handleSetStartDate, handleSetEndDate } = useAdmissionModule();
|
|
16
16
|
const { filterEnabled, filterAdmissionStatus, filterStartDate, filterEndDate, } = state;
|
|
17
17
|
const t = useTranslations("admission");
|
|
18
|
+
const admissionStatusLabelMap = {
|
|
19
|
+
PENDING: t("formOptionPending"),
|
|
20
|
+
APPROVED: t("formOptionApproved"),
|
|
21
|
+
REJECTED: t("formOptionRejected"),
|
|
22
|
+
ENROLLED: t("formOptionEnrolled"),
|
|
23
|
+
CANCELLED: t("formOptionCancelled"),
|
|
24
|
+
};
|
|
18
25
|
const filterEnabledValue = filterEnabled === undefined
|
|
19
26
|
? "undefined"
|
|
20
27
|
: filterEnabled
|
|
21
28
|
? "true"
|
|
22
29
|
: "false";
|
|
23
|
-
|
|
30
|
+
const { enhancedComboboxElement: filterAdmissionStatusCombo } = useEnhancedCombobox({
|
|
31
|
+
id: "filterAdmissionStatus",
|
|
32
|
+
label: t("filterAdmissionStatusLabel"),
|
|
33
|
+
info: t("filterByAdmissionStatus"),
|
|
34
|
+
options: ADMISSION_STATUS_OPTIONS.map((opt) => ({
|
|
35
|
+
id: opt.value,
|
|
36
|
+
name: admissionStatusLabelMap[opt.value] || opt.label,
|
|
37
|
+
})),
|
|
38
|
+
value: filterAdmissionStatus || "",
|
|
39
|
+
onValueChange: (value) => handleChange("filterAdmissionStatus", value),
|
|
40
|
+
searchEndpoint: ADMISSION_API_ROUTES.UNIT,
|
|
41
|
+
placeholder: "",
|
|
42
|
+
});
|
|
43
|
+
return (_jsx("div", { className: "space-y-4", children: _jsxs("div", { className: "grid grid-cols-1 gap-4", children: [filterAdmissionStatusCombo, _jsxs("div", { children: [_jsx("label", { htmlFor: "startDate", className: "text-foreground mb-1 block text-sm font-medium", children: t("filterStartDateLabel") }), _jsx("input", { id: "startDate", type: "date", value: filterStartDate || "", onChange: (e) => handleSetStartDate(e.target.value), className: "border-input bg-background text-foreground focus:ring-ring w-full rounded-md border px-3 py-2 focus:border-transparent focus:ring-2 focus:outline-none" })] }), _jsxs("div", { children: [_jsx("label", { htmlFor: "endDate", className: "text-foreground mb-1 block text-sm font-medium", children: t("filterEndDateLabel") }), _jsx("input", { id: "endDate", type: "date", value: filterEndDate || "", onChange: (e) => handleSetEndDate(e.target.value), className: "border-input bg-background text-foreground focus:ring-ring w-full rounded-md border px-3 py-2 focus:border-transparent focus:ring-2 focus:outline-none" })] }), _jsx(EnhancedRadio, { label: t("filterOptionEnabled"), name: "filterEnabled", value: filterEnabledValue, options: [
|
|
24
44
|
{ label: t("filterOptionAll"), value: "undefined" },
|
|
25
45
|
{ label: t("filterOptionEnabled"), value: "true" },
|
|
26
46
|
{ label: t("filterOptionDisabled"), value: "false" },
|
|
@@ -12,31 +12,65 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
12
12
|
import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
|
|
13
13
|
import { EnhancedTextarea } from "@appcorp/shadcn/components/enhanced-textarea";
|
|
14
14
|
import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
|
|
15
|
-
import {
|
|
15
|
+
import { useEnhancedCombobox } from "@appcorp/shadcn/hooks/use-enhanced-combobox";
|
|
16
16
|
import { useAdmissionModule, ADMISSION_ACTION_TYPES } from "./context";
|
|
17
17
|
import { Separator } from "@appcorp/shadcn/components/ui/separator";
|
|
18
|
-
import { GENDER } from "../../type";
|
|
19
18
|
import { useEffect } from "react";
|
|
20
19
|
import { getCachedWorkspaceSync } from "../workspace/cache";
|
|
21
|
-
import { getDialCode, VALUE_DELIMITER } from "@react-pakistan/util-functions";
|
|
20
|
+
import { API_METHODS, getDialCode, VALUE_DELIMITER, } from "@react-pakistan/util-functions";
|
|
22
21
|
import { v4 as uuidv4 } from "uuid";
|
|
23
|
-
import {
|
|
22
|
+
import { ADMISSION_API_ROUTES, GENDER_OPTIONS } from "./constants";
|
|
24
23
|
import { useTranslations } from "next-intl";
|
|
24
|
+
import { useFetch } from "@react-pakistan/util-functions/hooks/use-fetch";
|
|
25
25
|
export const AdmissionForm = () => {
|
|
26
26
|
const { state, handleChange, dispatch } = useAdmissionModule();
|
|
27
27
|
const { address, admissionNotes, studentIdNumber, city, classForAdmission, country, discountCode, dob, emergencyContact, errors, fatherIdNumber, fatherFirstName, fatherLastName, fatherMobile, fatherOccupation, fatherOrganization, firstName, gender, id, lastName, motherIdNumber, motherFirstName, motherLastName, motherMobile, notes, previousSchool, registrationCode, siblings, state: provinceState, } = state;
|
|
28
28
|
const t = useTranslations("admission");
|
|
29
|
+
const genderLabelMap = {
|
|
30
|
+
MALE: t("formOptionMale"),
|
|
31
|
+
FEMALE: t("formOptionFemale"),
|
|
32
|
+
OTHER: t("formOptionOther"),
|
|
33
|
+
};
|
|
29
34
|
const workspace = getCachedWorkspaceSync();
|
|
30
|
-
const discountCodes =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
const { data: discountCodes } = useFetch("/api/v1/discount-code", {
|
|
36
|
+
params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
|
|
37
|
+
method: API_METHODS.GET,
|
|
38
|
+
});
|
|
39
|
+
const { enhancedComboboxElement: genderCombo } = useEnhancedCombobox({
|
|
40
|
+
emptyText: t("formNoGenderOptionsEmpty"),
|
|
41
|
+
id: "gender",
|
|
42
|
+
info: t("formGenderInfo"),
|
|
43
|
+
label: t("formGenderLabel"),
|
|
44
|
+
required: true,
|
|
45
|
+
onValueChange: (value) => handleChange("gender", value),
|
|
46
|
+
options: GENDER_OPTIONS.map((g) => ({
|
|
47
|
+
id: g.value,
|
|
48
|
+
name: genderLabelMap[g.value] || g.label,
|
|
49
|
+
})),
|
|
50
|
+
placeholder: t("formGenderPlaceholder"),
|
|
51
|
+
searchEndpoint: ADMISSION_API_ROUTES.UNIT,
|
|
52
|
+
searchPlaceholder: t("formSearchGenderPlaceholder"),
|
|
53
|
+
value: gender,
|
|
54
|
+
});
|
|
55
|
+
const { enhancedComboboxElement: discountCodeCombo } = useEnhancedCombobox({
|
|
56
|
+
emptyText: t("formNoDiscountCodesEmpty"),
|
|
57
|
+
id: "discountCode",
|
|
58
|
+
info: t("formDiscountCodeInfo"),
|
|
59
|
+
label: t("formDiscountCodeLabel"),
|
|
60
|
+
onValueChange: (value) => handleChange("discountCode", value),
|
|
61
|
+
options: ((discountCodes === null || discountCodes === void 0 ? void 0 : discountCodes.items) || [])
|
|
62
|
+
.filter((code) => code.enabled)
|
|
63
|
+
.map((code) => {
|
|
64
|
+
var _a;
|
|
65
|
+
return ({
|
|
66
|
+
id: code.code,
|
|
67
|
+
name: `${code.code} - ${code.discountValue}${code.discountType === "PERCENTAGE" ? "%" : (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.currency}`,
|
|
68
|
+
});
|
|
69
|
+
}),
|
|
70
|
+
placeholder: t("formDiscountCodePlaceholder"),
|
|
71
|
+
searchEndpoint: ADMISSION_API_ROUTES.UNIT,
|
|
72
|
+
searchPlaceholder: t("formSearchDiscountCodesPlaceholder"),
|
|
73
|
+
value: discountCode || "",
|
|
40
74
|
});
|
|
41
75
|
useEffect(() => {
|
|
42
76
|
var _a, _b, _c, _d, _e, _f;
|
|
@@ -79,9 +113,5 @@ export const AdmissionForm = () => {
|
|
|
79
113
|
}
|
|
80
114
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
81
115
|
}, [id, dispatch]);
|
|
82
|
-
return (_jsxs("div", { className: "grid grid-cols-1 gap-2 space-y-2", children: [_jsx("h4", { className: "m-0 p-0", children: t("formSectionStudentInformation") }), _jsxs("div", { className: "grid grid-cols-5 gap-4", children: [_jsx(EnhancedInput, { error: errors.firstName, id: "firstName", info: t("formFirstNameInfo"), label: t("formFirstNameLabel"), onChange: (e) => handleChange("firstName", e.target.value), placeholder: t("formFirstNamePlaceholder"), required: true, type: "text", value: firstName || "" }), _jsx(EnhancedInput, { error: errors.lastName, id: "lastName", info: t("formLastNameInfo"), label: t("formLastNameLabel"), onChange: (e) => handleChange("lastName", e.target.value), placeholder: t("formLastNamePlaceholder"), required: true, type: "text", value: lastName || "" }), _jsx(EnhancedInput, { error: errors.studentIdNumber, id: "studentIdNumber", info: t("formStudentIdNumberInfo"), label: t("formStudentIdNumberLabel"), onChange: (e) => handleChange("studentIdNumber", e.target.value), placeholder: t("formStudentIdNumberPlaceholder"), required: true, type: "text", value: studentIdNumber || "" }), _jsx(
|
|
83
|
-
{ label: t("formOptionMale"), value: GENDER.MALE },
|
|
84
|
-
{ label: t("formOptionFemale"), value: GENDER.FEMALE },
|
|
85
|
-
{ label: t("formOptionOther"), value: GENDER.OTHER },
|
|
86
|
-
], placeholder: t("formGenderPlaceholder"), searchPlaceholder: t("formSearchGenderPlaceholder"), value: gender }), _jsx(EnhancedInput, { error: errors.dob, id: "dob", info: t("formDobInfo"), label: t("formDobLabel"), onChange: (e) => handleChange("dob", e.target.value), placeholder: t("formDobPlaceholder"), required: true, type: "date", value: dob || "" }), _jsx(EnhancedInput, { error: errors.registrationCode, id: "registrationCode", info: t("formRegistrationCodeInfo"), label: t("formRegistrationCodeLabel"), onChange: (e) => handleChange("registrationCode", e.target.value), placeholder: t("formRegistrationCodePlaceholder"), required: true, type: "text", value: registrationCode || "", disabled: true }), _jsx(EnhancedCombobox, { emptyText: t("formNoDiscountCodesEmpty"), error: errors.discountCode, id: "discountCode", info: t("formDiscountCodeInfo"), label: t("formDiscountCodeLabel"), onValueChange: (value) => handleChange("discountCode", value), options: discountCodeOptions, placeholder: t("formDiscountCodePlaceholder"), searchPlaceholder: t("formSearchDiscountCodesPlaceholder"), value: discountCode || "" }), _jsx(EnhancedCheckbox, { label: t("formCheckboxHafizLabel"), id: "hafiz", info: t("formHafizInfo"), onCheckedChange: (checked) => handleChange("hafiz", checked) }), _jsx(EnhancedCheckbox, { label: t("formCheckboxOrphanLabel"), id: "orphan", info: t("formOrphanInfo"), onCheckedChange: (checked) => handleChange("orphan", checked) })] }), _jsx(Separator, {}), _jsx("h4", { className: "m-0 p-0", children: t("formSectionFatherInformation") }), _jsxs("div", { className: "grid grid-cols-6 gap-4", children: [_jsx(EnhancedInput, { error: errors.fatherFirstName, id: "fatherFirstName", info: t("formFatherFirstNameInfo"), label: t("formFirstNameLabel"), onChange: (e) => handleChange("fatherFirstName", e.target.value), placeholder: t("formFirstNamePlaceholder"), required: true, type: "text", value: fatherFirstName || "" }), _jsx(EnhancedInput, { error: errors.fatherLastName, id: "fatherLastName", info: t("formFatherLastNameInfo"), label: t("formLastNameLabel"), onChange: (e) => handleChange("fatherLastName", e.target.value), placeholder: t("formLastNamePlaceholder"), required: true, type: "text", value: fatherLastName || "" }), _jsx(EnhancedInput, { error: errors.fatherIdNumber, id: "fatherIdNumber", info: t("formFatherIdNumberInfo"), label: t("formIdNumberLabel"), onChange: (e) => handleChange("fatherIdNumber", e.target.value), placeholder: t("formIDNumberPlaceholder"), required: true, type: "text", value: fatherIdNumber || "" }), _jsx(EnhancedInput, { error: errors.fatherMobile, id: "fatherMobile", info: t("formFatherMobileInfo"), label: t("formMobileLabel"), onChange: (e) => handleChange("fatherMobile", e.target.value), placeholder: "+923001234567", required: true, type: "text", value: fatherMobile || "" }), _jsx(EnhancedInput, { error: errors.fatherOccupation, id: "fatherOccupation", info: t("formFatherOccupationInfo"), label: t("formOccupationLabel"), onChange: (e) => handleChange("fatherOccupation", e.target.value), placeholder: t("formOccupationPlaceholder"), required: false, type: "text", value: fatherOccupation || "" }), _jsx(EnhancedInput, { error: errors.fatherOrganization, id: "fatherOrganization", info: t("formFatherOrganizationInfo"), label: t("formOrganizationLabel"), onChange: (e) => handleChange("fatherOrganization", e.target.value), placeholder: t("formOrganizationPlaceholder"), required: false, type: "text", value: fatherOrganization || "" }), _jsx(EnhancedCheckbox, { label: t("formEmergencyContactLabel"), id: "emergencyContactFather", info: t("formFatherEmergencyContactInfo"), checked: emergencyContact === "Father", onCheckedChange: (checked) => handleChange("emergencyContact", checked ? "Father" : "") })] }), _jsx(Separator, {}), _jsx("h4", { className: "m-0 p-0", children: t("formSectionMotherInformation") }), _jsxs("div", { className: "grid grid-cols-6 gap-4", children: [_jsx(EnhancedInput, { error: errors.motherFirstName, id: "motherFirstName", info: t("formMotherFirstNameInfo"), label: t("formFirstNameLabel"), onChange: (e) => handleChange("motherFirstName", e.target.value), placeholder: t("formFirstNamePlaceholder"), required: true, type: "text", value: motherFirstName || "" }), _jsx(EnhancedInput, { error: errors.motherLastName, id: "motherLastName", info: t("formMotherLastNameInfo"), label: t("formLastNameLabel"), onChange: (e) => handleChange("motherLastName", e.target.value), placeholder: t("formLastNamePlaceholder"), required: true, type: "text", value: motherLastName || "" }), _jsx(EnhancedInput, { error: errors.motherIdNumber, id: "motherIdNumber", info: t("formMotherIdNumberInfo"), label: t("formIdNumberLabel"), onChange: (e) => handleChange("motherIdNumber", e.target.value), placeholder: t("formIDNumberPlaceholder"), required: true, type: "text", value: motherIdNumber || "" }), _jsx(EnhancedInput, { error: errors.motherMobile, id: "motherMobile", info: t("formMotherMobileInfo"), label: t("formMobileLabel"), onChange: (e) => handleChange("motherMobile", e.target.value), placeholder: "+923001234567", required: true, type: "text", value: motherMobile || "" }), _jsx(EnhancedCheckbox, { label: t("formEmergencyContactLabel"), id: "emergencyContactMother", info: t("formMotherEmergencyContactInfo"), checked: emergencyContact === "Mother", onCheckedChange: (checked) => handleChange("emergencyContact", checked ? "Mother" : "") })] }), _jsx(Separator, {}), _jsx("h4", { className: "m-0 p-0", children: t("formSectionHomeInformation") }), _jsxs("div", { className: "grid grid-cols-6 gap-4", children: [_jsx(EnhancedTextarea, { error: errors.address, id: "homeAddress", info: t("formHomeAddressInfo"), label: t("formHomeAddressLabel"), onChange: (e) => handleChange("address", e.target.value), placeholder: t("formHomeAddressPlaceholder"), required: true, rows: 2, value: address || "" }), _jsx(EnhancedInput, { error: errors.city, id: "city", info: t("formCityInfo"), label: t("formCityLabel"), onChange: (e) => handleChange("city", e.target.value), placeholder: t("formCityPlaceholder"), required: true, type: "text", value: city || "" }), _jsx(EnhancedInput, { error: errors.state, id: "state", info: t("formStateInfo"), label: t("formStateLabel"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("formStatePlaceholder"), required: true, type: "text", value: provinceState || "" }), _jsx(EnhancedInput, { error: errors.country, id: "country", info: t("formCountryInfo"), label: t("formCountryLabel"), onChange: (e) => handleChange("country", e.target.value), placeholder: t("formCountryPlaceholder"), required: true, type: "text", value: country || "" })] }), _jsx(Separator, {}), _jsx("h4", { className: "m-0 p-0", children: t("formSectionAdmissionInformation") }), _jsxs("div", { className: "grid grid-cols-6 gap-4", children: [_jsx(EnhancedInput, { error: errors.classForAdmission, id: "classForAdmission", info: t("formClassForAdmissionInfo"), label: t("formClassForAdmissionLabel"), onChange: (e) => handleChange("classForAdmission", e.target.value), placeholder: t("formClassForAdmissionPlaceholder"), required: true, type: "text", value: classForAdmission || "" }), _jsx(EnhancedInput, { error: errors.previousSchool, id: "previousSchool", info: t("formPreviousSchoolInfo"), label: t("formPreviousSchoolLabel"), onChange: (e) => handleChange("previousSchool", e.target.value), placeholder: t("formPreviousSchoolPlaceholder"), type: "text", value: previousSchool || "" }), _jsx(EnhancedTextarea, { error: errors.siblings, id: "siblings", info: t("formSiblingsInfo"), label: t("formSiblingsLabel"), onChange: (e) => handleChange("siblings", e.target.value), placeholder: t("formSiblingsPlaceholder"), rows: 3, value: siblings || "" })] }), _jsx(Separator, {}), _jsx("h4", { className: "m-0 p-0", children: t("formSectionOfficeUse") }), _jsxs("div", { className: "grid grid-cols-4 gap-4", children: [_jsx(EnhancedTextarea, { error: errors.notes, id: "notes", info: t("formNotesInfo"), label: t("formNotesLabel"), onChange: (e) => handleChange("notes", e.target.value), placeholder: t("formNotesPlaceholder"), rows: 3, value: notes || "" }), _jsx(EnhancedTextarea, { error: errors.admissionNotes, id: "admissionNotes", info: t("formAdmissionNotesInfo"), label: t("formAdmissionNotesLabel"), onChange: (e) => handleChange("admissionNotes", e.target.value), placeholder: t("formAdmissionNotesPlaceholder"), rows: 3, value: admissionNotes || "" })] })] }));
|
|
116
|
+
return (_jsxs("div", { className: "grid grid-cols-1 gap-2 space-y-2", children: [_jsx("h4", { className: "m-0 p-0", children: t("formSectionStudentInformation") }), _jsxs("div", { className: "grid grid-cols-5 gap-4", children: [_jsx(EnhancedInput, { error: errors.firstName, id: "firstName", info: t("formFirstNameInfo"), label: t("formFirstNameLabel"), onChange: (e) => handleChange("firstName", e.target.value), placeholder: t("formFirstNamePlaceholder"), required: true, type: "text", value: firstName || "" }), _jsx(EnhancedInput, { error: errors.lastName, id: "lastName", info: t("formLastNameInfo"), label: t("formLastNameLabel"), onChange: (e) => handleChange("lastName", e.target.value), placeholder: t("formLastNamePlaceholder"), required: true, type: "text", value: lastName || "" }), _jsx(EnhancedInput, { error: errors.studentIdNumber, id: "studentIdNumber", info: t("formStudentIdNumberInfo"), label: t("formStudentIdNumberLabel"), onChange: (e) => handleChange("studentIdNumber", e.target.value), placeholder: t("formStudentIdNumberPlaceholder"), required: true, type: "text", value: studentIdNumber || "" }), genderCombo, _jsx(EnhancedInput, { error: errors.dob, id: "dob", info: t("formDobInfo"), label: t("formDobLabel"), onChange: (e) => handleChange("dob", e.target.value), placeholder: t("formDobPlaceholder"), required: true, type: "date", value: dob || "" }), _jsx(EnhancedInput, { error: errors.registrationCode, id: "registrationCode", info: t("formRegistrationCodeInfo"), label: t("formRegistrationCodeLabel"), onChange: (e) => handleChange("registrationCode", e.target.value), placeholder: t("formRegistrationCodePlaceholder"), required: true, type: "text", value: registrationCode || "", disabled: true }), discountCodeCombo, _jsx(EnhancedCheckbox, { label: t("formCheckboxHafizLabel"), id: "hafiz", info: t("formHafizInfo"), onCheckedChange: (checked) => handleChange("hafiz", checked) }), _jsx(EnhancedCheckbox, { label: t("formCheckboxOrphanLabel"), id: "orphan", info: t("formOrphanInfo"), onCheckedChange: (checked) => handleChange("orphan", checked) })] }), _jsx(Separator, {}), _jsx("h4", { className: "m-0 p-0", children: t("formSectionFatherInformation") }), _jsxs("div", { className: "grid grid-cols-6 gap-4", children: [_jsx(EnhancedInput, { error: errors.fatherFirstName, id: "fatherFirstName", info: t("formFatherFirstNameInfo"), label: t("formFirstNameLabel"), onChange: (e) => handleChange("fatherFirstName", e.target.value), placeholder: t("formFirstNamePlaceholder"), required: true, type: "text", value: fatherFirstName || "" }), _jsx(EnhancedInput, { error: errors.fatherLastName, id: "fatherLastName", info: t("formFatherLastNameInfo"), label: t("formLastNameLabel"), onChange: (e) => handleChange("fatherLastName", e.target.value), placeholder: t("formLastNamePlaceholder"), required: true, type: "text", value: fatherLastName || "" }), _jsx(EnhancedInput, { error: errors.fatherIdNumber, id: "fatherIdNumber", info: t("formFatherIdNumberInfo"), label: t("formIdNumberLabel"), onChange: (e) => handleChange("fatherIdNumber", e.target.value), placeholder: t("formIDNumberPlaceholder"), required: true, type: "text", value: fatherIdNumber || "" }), _jsx(EnhancedInput, { error: errors.fatherMobile, id: "fatherMobile", info: t("formFatherMobileInfo"), label: t("formMobileLabel"), onChange: (e) => handleChange("fatherMobile", e.target.value), placeholder: "+923001234567", required: true, type: "text", value: fatherMobile || "" }), _jsx(EnhancedInput, { error: errors.fatherOccupation, id: "fatherOccupation", info: t("formFatherOccupationInfo"), label: t("formOccupationLabel"), onChange: (e) => handleChange("fatherOccupation", e.target.value), placeholder: t("formOccupationPlaceholder"), required: false, type: "text", value: fatherOccupation || "" }), _jsx(EnhancedInput, { error: errors.fatherOrganization, id: "fatherOrganization", info: t("formFatherOrganizationInfo"), label: t("formOrganizationLabel"), onChange: (e) => handleChange("fatherOrganization", e.target.value), placeholder: t("formOrganizationPlaceholder"), required: false, type: "text", value: fatherOrganization || "" }), _jsx(EnhancedCheckbox, { label: t("formEmergencyContactLabel"), id: "emergencyContactFather", info: t("formFatherEmergencyContactInfo"), checked: emergencyContact === "Father", onCheckedChange: (checked) => handleChange("emergencyContact", checked ? "Father" : "") })] }), _jsx(Separator, {}), _jsx("h4", { className: "m-0 p-0", children: t("formSectionMotherInformation") }), _jsxs("div", { className: "grid grid-cols-6 gap-4", children: [_jsx(EnhancedInput, { error: errors.motherFirstName, id: "motherFirstName", info: t("formMotherFirstNameInfo"), label: t("formFirstNameLabel"), onChange: (e) => handleChange("motherFirstName", e.target.value), placeholder: t("formFirstNamePlaceholder"), required: true, type: "text", value: motherFirstName || "" }), _jsx(EnhancedInput, { error: errors.motherLastName, id: "motherLastName", info: t("formMotherLastNameInfo"), label: t("formLastNameLabel"), onChange: (e) => handleChange("motherLastName", e.target.value), placeholder: t("formLastNamePlaceholder"), required: true, type: "text", value: motherLastName || "" }), _jsx(EnhancedInput, { error: errors.motherIdNumber, id: "motherIdNumber", info: t("formMotherIdNumberInfo"), label: t("formIdNumberLabel"), onChange: (e) => handleChange("motherIdNumber", e.target.value), placeholder: t("formIDNumberPlaceholder"), required: true, type: "text", value: motherIdNumber || "" }), _jsx(EnhancedInput, { error: errors.motherMobile, id: "motherMobile", info: t("formMotherMobileInfo"), label: t("formMobileLabel"), onChange: (e) => handleChange("motherMobile", e.target.value), placeholder: "+923001234567", required: true, type: "text", value: motherMobile || "" }), _jsx(EnhancedCheckbox, { label: t("formEmergencyContactLabel"), id: "emergencyContactMother", info: t("formMotherEmergencyContactInfo"), checked: emergencyContact === "Mother", onCheckedChange: (checked) => handleChange("emergencyContact", checked ? "Mother" : "") })] }), _jsx(Separator, {}), _jsx("h4", { className: "m-0 p-0", children: t("formSectionHomeInformation") }), _jsxs("div", { className: "grid grid-cols-6 gap-4", children: [_jsx(EnhancedTextarea, { error: errors.address, id: "homeAddress", info: t("formHomeAddressInfo"), label: t("formHomeAddressLabel"), onChange: (e) => handleChange("address", e.target.value), placeholder: t("formHomeAddressPlaceholder"), required: true, rows: 2, value: address || "" }), _jsx(EnhancedInput, { error: errors.city, id: "city", info: t("formCityInfo"), label: t("formCityLabel"), onChange: (e) => handleChange("city", e.target.value), placeholder: t("formCityPlaceholder"), required: true, type: "text", value: city || "" }), _jsx(EnhancedInput, { error: errors.state, id: "state", info: t("formStateInfo"), label: t("formStateLabel"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("formStatePlaceholder"), required: true, type: "text", value: provinceState || "" }), _jsx(EnhancedInput, { error: errors.country, id: "country", info: t("formCountryInfo"), label: t("formCountryLabel"), onChange: (e) => handleChange("country", e.target.value), placeholder: t("formCountryPlaceholder"), required: true, type: "text", value: country || "" })] }), _jsx(Separator, {}), _jsx("h4", { className: "m-0 p-0", children: t("formSectionAdmissionInformation") }), _jsxs("div", { className: "grid grid-cols-6 gap-4", children: [_jsx(EnhancedInput, { error: errors.classForAdmission, id: "classForAdmission", info: t("formClassForAdmissionInfo"), label: t("formClassForAdmissionLabel"), onChange: (e) => handleChange("classForAdmission", e.target.value), placeholder: t("formClassForAdmissionPlaceholder"), required: true, type: "text", value: classForAdmission || "" }), _jsx(EnhancedInput, { error: errors.previousSchool, id: "previousSchool", info: t("formPreviousSchoolInfo"), label: t("formPreviousSchoolLabel"), onChange: (e) => handleChange("previousSchool", e.target.value), placeholder: t("formPreviousSchoolPlaceholder"), type: "text", value: previousSchool || "" }), _jsx(EnhancedTextarea, { error: errors.siblings, id: "siblings", info: t("formSiblingsInfo"), label: t("formSiblingsLabel"), onChange: (e) => handleChange("siblings", e.target.value), placeholder: t("formSiblingsPlaceholder"), rows: 3, value: siblings || "" })] }), _jsx(Separator, {}), _jsx("h4", { className: "m-0 p-0", children: t("formSectionOfficeUse") }), _jsxs("div", { className: "grid grid-cols-4 gap-4", children: [_jsx(EnhancedTextarea, { error: errors.notes, id: "notes", info: t("formNotesInfo"), label: t("formNotesLabel"), onChange: (e) => handleChange("notes", e.target.value), placeholder: t("formNotesPlaceholder"), rows: 3, value: notes || "" }), _jsx(EnhancedTextarea, { error: errors.admissionNotes, id: "admissionNotes", info: t("formAdmissionNotesInfo"), label: t("formAdmissionNotesLabel"), onChange: (e) => handleChange("admissionNotes", e.target.value), placeholder: t("formAdmissionNotesPlaceholder"), rows: 3, value: admissionNotes || "" })] })] }));
|
|
87
117
|
};
|
|
@@ -25,7 +25,6 @@ import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
|
|
|
25
25
|
import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
|
|
26
26
|
import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
|
|
27
27
|
import { ATTENDANCE_API_ROUTES, pageLimit } from "./constants";
|
|
28
|
-
import { getCachedAttendances, invalidateAttendancesCache } from "./cache";
|
|
29
28
|
import { attendanceFormValidation } from "./validate";
|
|
30
29
|
import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
|
|
31
30
|
import { ATTENDANCE_STATUS, } from "../../type";
|
|
@@ -168,7 +167,6 @@ export const useAttendanceModule = () => {
|
|
|
168
167
|
showToast(isCreatedOrUpdated(data)
|
|
169
168
|
? t("messagesAttendanceCreated")
|
|
170
169
|
: t("messagesAttendanceUpdated"), TOAST_VARIANT.SUCCESS);
|
|
171
|
-
invalidateAttendancesCache();
|
|
172
170
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
173
171
|
resetFormAndCloseDrawer();
|
|
174
172
|
}
|
|
@@ -193,7 +191,6 @@ export const useAttendanceModule = () => {
|
|
|
193
191
|
}
|
|
194
192
|
if (data) {
|
|
195
193
|
showToast(t("messagesAttendanceDeleted"), TOAST_VARIANT.SUCCESS);
|
|
196
|
-
invalidateAttendancesCache();
|
|
197
194
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
198
195
|
}
|
|
199
196
|
}, [showToast, t]);
|
|
@@ -397,44 +394,13 @@ export const useAttendanceModule = () => {
|
|
|
397
394
|
// ==========================================================================
|
|
398
395
|
// 1.4.9 EFFECTS
|
|
399
396
|
// ==========================================================================
|
|
400
|
-
// Keep the latest fetch function in a ref so the fetch effect can call it
|
|
401
|
-
// without depending on listFetchNow's unstable identity.
|
|
402
397
|
useEffect(() => {
|
|
403
398
|
listFetchNowRef.current = listFetchNow;
|
|
404
|
-
});
|
|
405
|
-
// Initial load via cache; re-fetch directly from API on page/pageLimit/filter/search changes.
|
|
399
|
+
}, [listFetchNow]);
|
|
406
400
|
useEffect(() => {
|
|
407
401
|
var _a;
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
const currentPage = Number(listParams.currentPage) || 1;
|
|
411
|
-
const currentPageLimit = Number(listParams.pageLimit) || pageLimit;
|
|
412
|
-
const isDefaultLoad = currentPage === 1 &&
|
|
413
|
-
currentPageLimit === pageLimit &&
|
|
414
|
-
!listParams.searchQuery &&
|
|
415
|
-
listParams.filterEnabled === undefined;
|
|
416
|
-
if (isDefaultLoad) {
|
|
417
|
-
(async () => {
|
|
418
|
-
try {
|
|
419
|
-
const { count, items } = await getCachedAttendances({
|
|
420
|
-
params: listParams,
|
|
421
|
-
});
|
|
422
|
-
dispatch({
|
|
423
|
-
type: ATTENDANCE_ACTION_TYPES.SET_ITEMS,
|
|
424
|
-
payload: { items: items || [], count: count || 0 },
|
|
425
|
-
});
|
|
426
|
-
}
|
|
427
|
-
catch (_a) {
|
|
428
|
-
showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
|
|
429
|
-
}
|
|
430
|
-
})();
|
|
431
|
-
}
|
|
432
|
-
else {
|
|
433
|
-
// Bypass cache for pagination, pageLimit, filter and search changes.
|
|
434
|
-
// Use ref to avoid the infinite-loop caused by listFetchNow's unstable identity.
|
|
435
|
-
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
436
|
-
}
|
|
437
|
-
}, [listParams, dispatch, showToast, schoolId, t]);
|
|
402
|
+
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
403
|
+
}, [listParams]);
|
|
438
404
|
// ==========================================================================
|
|
439
405
|
// 1.4.10 RETURN
|
|
440
406
|
// ==========================================================================
|
|
@@ -1,22 +1,38 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
|
|
4
|
-
import {
|
|
4
|
+
import { useEnhancedCombobox } from "@appcorp/shadcn/hooks/use-enhanced-combobox";
|
|
5
5
|
import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
|
|
6
6
|
import { EnhancedTextarea } from "@appcorp/shadcn/components/enhanced-textarea";
|
|
7
7
|
import { useAttendanceModule } from "./context";
|
|
8
|
-
import { ATTENDANCE_STATUS_OPTIONS } from "./constants";
|
|
8
|
+
import { ATTENDANCE_STATUS_OPTIONS, ATTENDANCE_API_ROUTES } from "./constants";
|
|
9
9
|
import { useTranslations } from "next-intl";
|
|
10
10
|
export const AttendanceForm = () => {
|
|
11
11
|
const { state, handleChange } = useAttendanceModule();
|
|
12
12
|
const { date, enabled, errors, remarks, status } = state;
|
|
13
13
|
const t = useTranslations("attendance");
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
const attendanceStatusLabelMap = {
|
|
15
|
+
PRESENT: t("formOptionPresent"),
|
|
16
|
+
ABSENT: t("formOptionAbsent"),
|
|
17
|
+
LATE: t("formOptionLate"),
|
|
18
|
+
EXCUSED: t("formOptionExcused"),
|
|
19
|
+
HALF_DAY: t("formOptionHalfDay"),
|
|
20
|
+
};
|
|
21
|
+
const { enhancedComboboxElement: statusCombo } = useEnhancedCombobox({
|
|
22
|
+
id: "status",
|
|
23
|
+
info: t("formStatusInfo"),
|
|
24
|
+
label: t("formOptionStatus"),
|
|
25
|
+
onValueChange: (value) => handleChange("status", value),
|
|
26
|
+
options: ATTENDANCE_STATUS_OPTIONS.map((opt) => ({
|
|
27
|
+
id: opt.value,
|
|
28
|
+
name: attendanceStatusLabelMap[opt.value] || opt.label,
|
|
29
|
+
})),
|
|
30
|
+
placeholder: t("formStatusPlaceholder"),
|
|
31
|
+
required: true,
|
|
32
|
+
searchEndpoint: ATTENDANCE_API_ROUTES.UNIT,
|
|
33
|
+
searchPlaceholder: t("formSearchStatusPlaceholder"),
|
|
34
|
+
emptyText: t("formNoStatusEmpty"),
|
|
35
|
+
value: status,
|
|
36
|
+
});
|
|
37
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsx(EnhancedInput, { error: errors.date, id: "date", info: t("formDateInfo"), label: t("formDateLabel"), onChange: (e) => handleChange("date", e.target.value), placeholder: t("formDatePlaceholder"), required: true, type: "date", value: date }), statusCombo, _jsx(EnhancedTextarea, { error: errors.remarks, id: "remarks", info: t("formRemarksInfo"), label: t("formRemarksLabel"), onChange: (e) => handleChange("remarks", e.target.value), placeholder: t("formRemarksPlaceholder"), rows: 3, value: remarks !== null && remarks !== void 0 ? remarks : "" }), _jsx(EnhancedCheckbox, { defaultChecked: enabled, label: t("formActiveAttendanceRecordLabel"), onCheckedChange: (checked) => handleChange("enabled", checked) })] }));
|
|
22
38
|
};
|
|
@@ -1,38 +1,47 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { useEnhancedCombobox } from "@appcorp/shadcn/hooks/use-enhanced-combobox";
|
|
4
4
|
import { EnhancedRadio } from "@appcorp/shadcn/components/enhanced-radio";
|
|
5
5
|
import { EnhancedTextarea } from "@appcorp/shadcn/components/enhanced-textarea";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { getCachedStudentProfilesSync } from "../student-profile/cache";
|
|
9
|
-
import { useMemo, useState } from "react";
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import { ATTENDANCE_API_ROUTES } from "./constants";
|
|
10
8
|
export const AttendanceMoreActions = ({ labelAttendanceStatus, labelCourse, labelCourseInfo, labelCoursePlaceholder, labelNoCourseFound, labelRemarks, labelRemarksInfo, labelRemarksPlaceholder, labelSearchCourses, labelStatusAbsent, labelStatusExcused, labelStatusHalfDay, labelStatusLate, labelStatusPresent, }) => {
|
|
11
|
-
const enrollment = getCachedEnrollmentsSync().items;
|
|
12
|
-
const studentProfiles = getCachedStudentProfilesSync().items;
|
|
13
|
-
const courses = getCachedCoursesSync().items;
|
|
9
|
+
// const enrollment = getCachedEnrollmentsSync().items;
|
|
10
|
+
// const studentProfiles = getCachedStudentProfilesSync().items;
|
|
11
|
+
// const courses = getCachedCoursesSync().items;
|
|
14
12
|
const [courseId, setCourseId] = useState("");
|
|
15
13
|
const [remarks, setRemarks] = useState({});
|
|
16
14
|
const [attendance, setAttendance] = useState({});
|
|
17
15
|
const [errors] = useState({});
|
|
16
|
+
const { enhancedComboboxElement: courseIdCombo } = useEnhancedCombobox({
|
|
17
|
+
emptyText: labelNoCourseFound,
|
|
18
|
+
id: "courseId",
|
|
19
|
+
info: labelCourseInfo,
|
|
20
|
+
label: labelCourse,
|
|
21
|
+
onValueChange: (value) => setCourseId(value),
|
|
22
|
+
options: [{ id: "", code: "" }].map((c) => ({
|
|
23
|
+
id: c.id,
|
|
24
|
+
name: c.code.trim(),
|
|
25
|
+
})),
|
|
26
|
+
placeholder: labelCoursePlaceholder,
|
|
27
|
+
required: true,
|
|
28
|
+
searchEndpoint: ATTENDANCE_API_ROUTES.UNIT,
|
|
29
|
+
searchPlaceholder: labelSearchCourses,
|
|
30
|
+
value: courseId || "",
|
|
31
|
+
});
|
|
18
32
|
// Find the section for the selected course, then get students enrolled in that section
|
|
19
|
-
const studentsInCourse = useMemo(() => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
studentsInCourse.length > 0 &&
|
|
32
|
-
studentsInCourse.map((s) => {
|
|
33
|
-
var _a, _b, _c, _d;
|
|
34
|
-
const student = studentProfiles.find((sp) => sp.id === s);
|
|
35
|
-
return (_jsxs("div", { children: [_jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsxs("div", { className: "flex flex-col items-center justify-center", children: [_jsxs("p", { children: [(_a = student === null || student === void 0 ? void 0 : student.familyMember) === null || _a === void 0 ? void 0 : _a.firstName, " ", (_b = student === null || student === void 0 ? void 0 : student.familyMember) === null || _b === void 0 ? void 0 : _b.lastName] }), _jsx("img", { src: (_c = student === null || student === void 0 ? void 0 : student.familyMember) === null || _c === void 0 ? void 0 : _c.avatar, alt: (_d = student === null || student === void 0 ? void 0 : student.familyMember) === null || _d === void 0 ? void 0 : _d.firstName, width: 100, height: 100, className: "rounded-full" })] }), _jsx("div", { children: _jsx(EnhancedRadio, { label: labelAttendanceStatus, name: "attendanceStatus", value: attendance[s] || "PRESENT", options: [
|
|
33
|
+
// const studentsInCourse = useMemo(() => {
|
|
34
|
+
// const courseObj = courses.find((c) => c.id === courseId);
|
|
35
|
+
// if (!courseObj) return [];
|
|
36
|
+
// return enrollment
|
|
37
|
+
// .filter((e) => e.sectionId === courseObj.sectionId)
|
|
38
|
+
// .map((e) => e.studentProfileId);
|
|
39
|
+
// }, [enrollment, courseId, courses]);
|
|
40
|
+
return (_jsxs("div", { className: "space-y-4", children: [courseIdCombo, courseId &&
|
|
41
|
+
[].length > 0 &&
|
|
42
|
+
[].map((s) => {
|
|
43
|
+
// const student = studentProfiles.find((sp) => sp.id === s);
|
|
44
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsxs("div", { className: "flex flex-col items-center justify-center", children: [_jsx("p", { children: " " }), _jsx("img", { src: "student?.familyMember?.avatar", alt: "student?.familyMember?.firstName", width: 100, height: 100, className: "rounded-full" })] }), _jsx("div", { children: _jsx(EnhancedRadio, { label: labelAttendanceStatus, name: "attendanceStatus", value: attendance[s] || "PRESENT", options: [
|
|
36
45
|
{ label: labelStatusPresent, value: "PRESENT" },
|
|
37
46
|
{ label: labelStatusAbsent, value: "ABSENT" },
|
|
38
47
|
{ label: labelStatusLate, value: "LATE" },
|