@appcorp/fusion-storybook 0.2.40 → 0.2.44

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.
Files changed (100) hide show
  1. package/base-modules/admission/constants.d.ts +5 -17
  2. package/base-modules/admission/constants.js +12 -7
  3. package/base-modules/admission/context/use-admission-module.js +11 -48
  4. package/base-modules/admission/filter.js +23 -3
  5. package/base-modules/admission/form.js +49 -19
  6. package/base-modules/attendance/context.js +3 -37
  7. package/base-modules/attendance/filter.js +3 -1
  8. package/base-modules/attendance/form.js +26 -10
  9. package/base-modules/attendance/more-actions.js +34 -25
  10. package/base-modules/campus/context.js +7 -7
  11. package/base-modules/class/cache.js +0 -1
  12. package/base-modules/class/context.js +10 -48
  13. package/base-modules/class/more-actions.js +47 -24
  14. package/base-modules/course/context.js +3 -37
  15. package/base-modules/course/form.js +91 -292
  16. package/base-modules/discount-code/constants.d.ts +5 -0
  17. package/base-modules/discount-code/constants.js +5 -0
  18. package/base-modules/discount-code/context.d.ts +1 -0
  19. package/base-modules/discount-code/context.js +40 -39
  20. package/base-modules/discount-code/form.js +21 -15
  21. package/base-modules/discount-code/more-actions.js +1 -1
  22. package/base-modules/enrollment/context.js +3 -37
  23. package/base-modules/enrollment/form.js +38 -11
  24. package/base-modules/enrollment/more-actions.js +48 -25
  25. package/base-modules/expense/constants.js +1 -1
  26. package/base-modules/expense/context.js +5 -32
  27. package/base-modules/expense/filter.js +50 -3
  28. package/base-modules/expense/form.js +82 -6
  29. package/base-modules/family/context.js +7 -38
  30. package/base-modules/family-member/context.js +7 -39
  31. package/base-modules/fee-structure/context.js +1 -25
  32. package/base-modules/fee-structure/form.js +77 -89
  33. package/base-modules/fee-structure/more-actions.js +45 -22
  34. package/base-modules/rbac/context.d.ts +1 -0
  35. package/base-modules/rbac/context.js +24 -33
  36. package/base-modules/rbac/form.js +3 -1
  37. package/base-modules/school/context.js +1 -1
  38. package/base-modules/school/form.js +34 -14
  39. package/base-modules/section/context.d.ts +1 -0
  40. package/base-modules/section/context.js +40 -47
  41. package/base-modules/section/form.js +25 -80
  42. package/base-modules/section/more-actions.js +47 -24
  43. package/base-modules/section/view.js +9 -7
  44. package/base-modules/student-fee/context/use-student-fee-module.d.ts +1 -0
  45. package/base-modules/student-fee/context/use-student-fee-module.js +48 -32
  46. package/base-modules/student-fee/context.d.ts +1 -1
  47. package/base-modules/student-fee/context.js +1 -1
  48. package/base-modules/student-fee/filter.js +23 -3
  49. package/base-modules/student-fee/form.js +93 -174
  50. package/base-modules/student-fee/view.d.ts +7 -1
  51. package/base-modules/student-fee/view.js +17 -20
  52. package/base-modules/student-profile/constants.d.ts +0 -6
  53. package/base-modules/student-profile/constants.js +1 -3
  54. package/base-modules/student-profile/context/use-student-profile-module.d.ts +1 -0
  55. package/base-modules/student-profile/context/use-student-profile-module.js +62 -55
  56. package/base-modules/student-profile/context.d.ts +1 -1
  57. package/base-modules/student-profile/context.js +1 -1
  58. package/base-modules/student-profile/filter.js +24 -4
  59. package/base-modules/student-profile/form.js +35 -3
  60. package/base-modules/subject/context.d.ts +1 -0
  61. package/base-modules/subject/context.js +38 -47
  62. package/base-modules/subject/more-actions.js +47 -24
  63. package/base-modules/teacher/constants.d.ts +0 -6
  64. package/base-modules/teacher/constants.js +0 -2
  65. package/base-modules/teacher/context.d.ts +1 -0
  66. package/base-modules/teacher/context.js +58 -39
  67. package/base-modules/teacher/form.js +46 -11
  68. package/base-modules/teacher/more-actions.js +45 -22
  69. package/base-modules/user/context/use-user-module.d.ts +1 -0
  70. package/base-modules/user/context/use-user-module.js +36 -32
  71. package/base-modules/user/context.js +1 -1
  72. package/base-modules/user/filter.js +6 -4
  73. package/base-modules/user/form.js +29 -5
  74. package/base-modules/user/more-actions.js +9 -7
  75. package/base-modules/user/view.js +3 -1
  76. package/base-modules/workspace/form.js +18 -8
  77. package/base-modules/workspace-user/context.d.ts +2 -1
  78. package/base-modules/workspace-user/context.js +31 -29
  79. package/package.json +1 -1
  80. package/tsconfig.build.tsbuildinfo +1 -1
  81. package/base-modules/admission/cache.d.ts +0 -14
  82. package/base-modules/admission/cache.js +0 -31
  83. package/base-modules/attendance/cache.d.ts +0 -14
  84. package/base-modules/attendance/cache.js +0 -31
  85. package/base-modules/course/cache.d.ts +0 -14
  86. package/base-modules/course/cache.js +0 -31
  87. package/base-modules/enrollment/cache.d.ts +0 -14
  88. package/base-modules/enrollment/cache.js +0 -31
  89. package/base-modules/expense/cache.d.ts +0 -14
  90. package/base-modules/expense/cache.js +0 -31
  91. package/base-modules/family/cache.d.ts +0 -14
  92. package/base-modules/family/cache.js +0 -31
  93. package/base-modules/family-member/cache.d.ts +0 -14
  94. package/base-modules/family-member/cache.js +0 -31
  95. package/base-modules/rbac/cache.d.ts +0 -27
  96. package/base-modules/rbac/cache.js +0 -46
  97. package/base-modules/student-fee/cache.d.ts +0 -15
  98. package/base-modules/student-fee/cache.js +0 -21
  99. package/base-modules/workspace-user/cache.d.ts +0 -14
  100. 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 ADMISSION_STATUS_OPTIONS_CONST: readonly [{
18
- readonly label: "Pending";
19
- readonly value: ADMISSION_STATUS.PENDING;
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 ADMISSION_STATUS_OPTIONS_CONST = [
32
- { label: "Pending", value: ADMISSION_STATUS.PENDING },
33
- { label: "Approved", value: ADMISSION_STATUS.APPROVED },
34
- { label: "Rejected", value: ADMISSION_STATUS.REJECTED },
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, pageLimit } from "../constants";
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("actionDeleteConfirmation")))
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("actionHeaderFilters"),
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("actionHeaderAddAdmission"),
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("actionRowView"),
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("actionRowEdit"),
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("actionRowDelete"),
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("actionRowPrintPdf"),
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("actionRowAnalyzeWithAi"),
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("actionRowAddStudent"),
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
- }, [dispatch, isDefaultListState, listParams, workspace === null || workspace === void 0 ? void 0 : workspace.id, t, showToast]);
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 { EnhancedCombobox } from "@appcorp/shadcn/components/enhanced-combobox";
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
- return (_jsx("div", { className: "space-y-4", children: _jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedCombobox, { id: "filterAdmissionStatus", label: t("filterAdmissionStatusLabel"), info: t("filterByAdmissionStatus"), options: [...ADMISSION_STATUS_OPTIONS], value: filterAdmissionStatus !== null && filterAdmissionStatus !== void 0 ? filterAdmissionStatus : undefined, onValueChange: (value) => handleChange("filterAdmissionStatus", value) }), _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: [
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 { EnhancedCombobox } from "@appcorp/shadcn/components/enhanced-combobox";
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 { getCachedDiscountCodesSync } from "../discount-code/cache";
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 = getCachedDiscountCodesSync();
31
- const discountCodeOptions = (discountCodes.items || [])
32
- .filter((code) => code.enabled)
33
- .map((code) => {
34
- var _a;
35
- return ({
36
- label: `${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}`,
37
- value: code.code,
38
- description: code.description || undefined,
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(EnhancedCombobox, { emptyText: t("formNoGenderOptionsEmpty"), error: errors.gender, id: "gender", info: t("formGenderInfo"), label: t("formGenderLabel"), required: true, onValueChange: (value) => handleChange("gender", value), options: [
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
- if (!schoolId)
409
- return;
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
  // ==========================================================================
@@ -2,7 +2,9 @@
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { useAttendanceModule } from "./context";
4
4
  import { EnhancedRadio } from "@appcorp/shadcn/components/enhanced-radio";
5
+ import { useTranslations } from "next-intl";
5
6
  export const AttendanceFilter = ({ labelAll, labelEnabled, labelDisabled, }) => {
7
+ const t = useTranslations("attendance");
6
8
  const { state, handleChange } = useAttendanceModule();
7
9
  const { filterEnabled } = state;
8
10
  const filterEnabledValue = filterEnabled === undefined
@@ -10,7 +12,7 @@ export const AttendanceFilter = ({ labelAll, labelEnabled, labelDisabled, }) =>
10
12
  : filterEnabled
11
13
  ? "true"
12
14
  : "false";
13
- return (_jsx("div", { className: "space-y-4", children: _jsx("div", { className: "grid grid-cols-1 gap-4", children: _jsx(EnhancedRadio, { label: "Enabled", name: "filterEnabled", value: filterEnabledValue, options: [
15
+ return (_jsx("div", { className: "space-y-4", children: _jsx("div", { className: "grid grid-cols-1 gap-4", children: _jsx(EnhancedRadio, { label: t("filterOptionEnabled"), name: "filterEnabled", value: filterEnabledValue, options: [
14
16
  { label: labelAll, value: "undefined" },
15
17
  { label: labelEnabled, value: "true" },
16
18
  { label: labelDisabled, value: "false" },
@@ -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 { EnhancedCombobox } from "@appcorp/shadcn/components/enhanced-combobox";
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
- 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 }), _jsx(EnhancedCombobox, { error: errors.status, id: "status", info: t("formStatusInfo"), label: t("formOptionStatus"), onValueChange: (value) => handleChange("status", value), options: ATTENDANCE_STATUS_OPTIONS.map((opt) => ({
15
- label: t(`status${opt.value.charAt(0).toUpperCase() +
16
- opt.value
17
- .slice(1)
18
- .toLowerCase()
19
- .replace(/_([a-z])/g, (_, c) => c.toUpperCase())}`),
20
- value: opt.value,
21
- })), placeholder: t("formStatusPlaceholder"), required: true, searchPlaceholder: t("formSearchStatusPlaceholder"), emptyText: t("formNoStatusEmpty"), value: status }), _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) })] }));
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
  };