@appcorp/fusion-storybook 0.2.91 → 0.2.94

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 (33) hide show
  1. package/base-modules/admission/context/use-admission-module.js +21 -19
  2. package/base-modules/admission/validate.d.ts +5 -5
  3. package/base-modules/admission/validate.js +13 -5
  4. package/base-modules/campus/context.js +40 -21
  5. package/base-modules/campus/form.js +5 -1
  6. package/base-modules/campus/validate.d.ts +1 -1
  7. package/base-modules/campus/validate.js +3 -1
  8. package/base-modules/family-member/context.js +28 -23
  9. package/base-modules/family-member/form.js +8 -1
  10. package/base-modules/family-member/validate.d.ts +3 -3
  11. package/base-modules/family-member/validate.js +5 -3
  12. package/base-modules/school/context.js +24 -19
  13. package/base-modules/school/form.js +5 -1
  14. package/base-modules/school/validate.d.ts +1 -1
  15. package/base-modules/school/validate.js +6 -1
  16. package/base-modules/student-fee/form.js +1 -1
  17. package/base-modules/student-profile/context/use-student-profile-module.js +33 -27
  18. package/base-modules/student-profile/form.js +8 -1
  19. package/base-modules/student-profile/validate.d.ts +2 -2
  20. package/base-modules/student-profile/validate.js +3 -4
  21. package/base-modules/teacher/context.js +1 -1
  22. package/base-modules/teacher/form.js +8 -1
  23. package/base-modules/teacher/validate.d.ts +2 -2
  24. package/base-modules/teacher/validate.js +11 -2
  25. package/base-modules/user/context/use-user-module.js +16 -12
  26. package/base-modules/user/validate.d.ts +1 -1
  27. package/base-modules/user/validate.js +2 -2
  28. package/package.json +1 -1
  29. package/tsconfig.build.tsbuildinfo +1 -1
  30. package/utils/id-number.d.ts +1 -0
  31. package/utils/id-number.js +10 -0
  32. package/utils/to-e164-phone.d.ts +1 -0
  33. package/utils/to-e164-phone.js +11 -0
@@ -11,12 +11,13 @@ import { ADMISSION_API_ROUTES } from "../../../constants";
11
11
  import { admissionFormValidation } from "../validate";
12
12
  import { getCachedWorkspaceSync } from "../../workspace/cache";
13
13
  import { generateAdmissionReceiptPDF, } from "../../../utils/admission-pdf";
14
- import { formatNumber } from "@react-pakistan/util-functions/general/format-number";
14
+ import { normalizeIdNumber } from "../../../utils/id-number";
15
+ import { toE164Phone } from "../../../utils/to-e164-phone";
15
16
  import { formatPhoneDisplay } from "@react-pakistan/util-functions/general/format-phone-display";
16
17
  import { Filter, Plus } from "lucide-react";
17
18
  import { ADMISSION_DRAWER, ADMISSION_ACTION_TYPES, useAdmissionContext, } from "../context";
18
19
  export const useAdmissionModule = () => {
19
- var _a, _b, _c, _d, _e, _f;
20
+ var _a, _b, _c, _d, _e, _f, _g;
20
21
  // ============================================================================
21
22
  // 1.4.1 STATE & CORE HOOKS
22
23
  // ============================================================================
@@ -51,7 +52,7 @@ export const useAdmissionModule = () => {
51
52
  (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id,
52
53
  ]);
53
54
  const updateParams = useMemo(() => {
54
- var _a, _b, _c, _d;
55
+ var _a, _b, _c, _d, _e, _f;
55
56
  return ({
56
57
  address: state.address || "",
57
58
  admissionNotes: state.admissionNotes || "",
@@ -67,32 +68,30 @@ export const useAdmissionModule = () => {
67
68
  fatherIdNumber: state.fatherIdNumber || "",
68
69
  fatherFirstName: state.fatherFirstName || "",
69
70
  fatherLastName: state.fatherLastName || "",
70
- fatherMobile: formatNumber(state.fatherMobile),
71
+ fatherMobile: toE164Phone(state.fatherMobile, (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.country),
71
72
  fatherOccupation: state.fatherOccupation || "",
72
73
  fatherOrganization: state.fatherOrganization || "",
73
74
  firstName: state.firstName || "",
74
75
  gender: state.gender || null,
75
- hafiz: (_b = state.hafiz) !== null && _b !== void 0 ? _b : false,
76
+ hafiz: (_c = state.hafiz) !== null && _c !== void 0 ? _c : false,
76
77
  id: state.id || "",
77
78
  lastName: state.lastName || "",
78
79
  motherIdNumber: state.motherIdNumber || "",
79
80
  motherFirstName: state.motherFirstName || "",
80
81
  motherLastName: state.motherLastName || "",
81
- motherMobile: formatNumber(state.motherMobile),
82
+ motherMobile: toE164Phone(state.motherMobile, (_d = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _d === void 0 ? void 0 : _d.country),
82
83
  notes: state.notes || "",
83
- orphan: (_c = state.orphan) !== null && _c !== void 0 ? _c : false,
84
+ orphan: (_e = state.orphan) !== null && _e !== void 0 ? _e : false,
84
85
  postalCode: state.postalCode || "",
85
86
  previousSchool: state.previousSchool || "",
86
87
  registrationCode: state.registrationCode || "",
87
- schoolId: ((_d = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _d === void 0 ? void 0 : _d.id) || "",
88
+ schoolId: ((_f = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _f === void 0 ? void 0 : _f.id) || "",
88
89
  siblings: state.siblings || "",
89
90
  state: state.state || "",
90
91
  });
91
92
  }, [
92
93
  state.address,
93
94
  state.admissionNotes,
94
- state.status,
95
- state.studentIdNumber,
96
95
  state.city,
97
96
  state.classForAdmission,
98
97
  state.country,
@@ -100,8 +99,8 @@ export const useAdmissionModule = () => {
100
99
  state.dob,
101
100
  state.emergencyContact,
102
101
  state.enabled,
103
- state.fatherIdNumber,
104
102
  state.fatherFirstName,
103
+ state.fatherIdNumber,
105
104
  state.fatherLastName,
106
105
  state.fatherMobile,
107
106
  state.fatherOccupation,
@@ -111,8 +110,8 @@ export const useAdmissionModule = () => {
111
110
  state.hafiz,
112
111
  state.id,
113
112
  state.lastName,
114
- state.motherIdNumber,
115
113
  state.motherFirstName,
114
+ state.motherIdNumber,
116
115
  state.motherLastName,
117
116
  state.motherMobile,
118
117
  state.notes,
@@ -122,7 +121,10 @@ export const useAdmissionModule = () => {
122
121
  state.registrationCode,
123
122
  state.siblings,
124
123
  state.state,
125
- (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.id,
124
+ state.status,
125
+ state.studentIdNumber,
126
+ (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.country,
127
+ (_c = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _c === void 0 ? void 0 : _c.id,
126
128
  ]);
127
129
  const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
128
130
  const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
@@ -536,7 +538,7 @@ export const useAdmissionModule = () => {
536
538
  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 : ""}`,
537
539
  variant: TOAST_VARIANT.SUCCESS,
538
540
  });
539
- }, [(_c = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _c === void 0 ? void 0 : _c.id, t, showToast, byIdFetchNow, dispatch]);
541
+ }, [(_d = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _d === void 0 ? void 0 : _d.id, t, showToast, byIdFetchNow, dispatch]);
540
542
  const handleSubmit = useCallback(() => {
541
543
  dispatch({
542
544
  type: ADMISSION_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
@@ -556,7 +558,7 @@ export const useAdmissionModule = () => {
556
558
  siblings: updateParams.siblings,
557
559
  },
558
560
  fatherDetails: {
559
- fatherIdNumber: updateParams.fatherIdNumber,
561
+ fatherIdNumber: normalizeIdNumber(updateParams.fatherIdNumber),
560
562
  fatherFirstName: updateParams.fatherFirstName,
561
563
  fatherLastName: updateParams.fatherLastName,
562
564
  fatherMobile: updateParams.fatherMobile,
@@ -565,7 +567,7 @@ export const useAdmissionModule = () => {
565
567
  emergencyContact: updateParams.emergencyContact === "Father",
566
568
  },
567
569
  motherDetails: {
568
- motherIdNumber: updateParams.motherIdNumber || "",
570
+ motherIdNumber: normalizeIdNumber(updateParams.motherIdNumber || ""),
569
571
  motherFirstName: updateParams.motherFirstName || "N/A",
570
572
  motherLastName: updateParams.motherLastName || "N/A",
571
573
  motherMobile: updateParams.motherMobile,
@@ -583,7 +585,7 @@ export const useAdmissionModule = () => {
583
585
  admissionNotes: updateParams.admissionNotes,
584
586
  },
585
587
  studentDetails: {
586
- studentIdNumber: updateParams.studentIdNumber,
588
+ studentIdNumber: normalizeIdNumber(updateParams.studentIdNumber),
587
589
  discountCode: updateParams.discountCode,
588
590
  dob: updateParams.dob,
589
591
  firstName: updateParams.firstName,
@@ -614,12 +616,12 @@ export const useAdmissionModule = () => {
614
616
  t,
615
617
  showToast,
616
618
  updateFetchNow,
617
- (_d = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _d === void 0 ? void 0 : _d.id,
619
+ (_e = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _e === void 0 ? void 0 : _e.id,
618
620
  ]);
619
621
  // ============================================================================
620
622
  // 1.4.8 HEADER & ROW ACTIONS
621
623
  // ============================================================================
622
- const hasGeminiSecrets = Boolean(((_e = workspace === null || workspace === void 0 ? void 0 : workspace.secrets) === null || _e === void 0 ? void 0 : _e.GEMINI_API_KEY) && ((_f = workspace === null || workspace === void 0 ? void 0 : workspace.secrets) === null || _f === void 0 ? void 0 : _f.GEMINI_MODEL));
624
+ const hasGeminiSecrets = Boolean(((_f = workspace === null || workspace === void 0 ? void 0 : workspace.secrets) === null || _f === void 0 ? void 0 : _f.GEMINI_API_KEY) && ((_g = workspace === null || workspace === void 0 ? void 0 : workspace.secrets) === null || _g === void 0 ? void 0 : _g.GEMINI_MODEL));
623
625
  const headerActions = useMemo(() => [
624
626
  {
625
627
  enabled: true,
@@ -9,7 +9,7 @@ export declare const admissionFormValidation: z.ZodObject<{
9
9
  registrationCode: z.ZodString;
10
10
  firstName: z.ZodString;
11
11
  lastName: z.ZodString;
12
- studentIdNumber: z.ZodString;
12
+ studentIdNumber: z.ZodPipe<z.ZodString, z.ZodTransform<string | null | undefined, string>>;
13
13
  dob: z.ZodString;
14
14
  gender: z.ZodEnum<typeof GENDER>;
15
15
  discountCode: z.ZodOptional<z.ZodString>;
@@ -17,14 +17,14 @@ export declare const admissionFormValidation: z.ZodObject<{
17
17
  orphan: z.ZodOptional<z.ZodBoolean>;
18
18
  fatherFirstName: z.ZodString;
19
19
  fatherLastName: z.ZodString;
20
- fatherIdNumber: z.ZodString;
21
- fatherMobile: z.ZodString;
20
+ fatherIdNumber: z.ZodPipe<z.ZodString, z.ZodTransform<string | null | undefined, string>>;
21
+ fatherMobile: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
22
22
  fatherOccupation: z.ZodOptional<z.ZodString>;
23
23
  fatherOrganization: z.ZodOptional<z.ZodString>;
24
24
  motherFirstName: z.ZodString;
25
25
  motherLastName: z.ZodString;
26
- motherIdNumber: z.ZodString;
27
- motherMobile: z.ZodString;
26
+ motherIdNumber: z.ZodPipe<z.ZodString, z.ZodTransform<string | null | undefined, string>>;
27
+ motherMobile: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
28
28
  address: z.ZodString;
29
29
  city: z.ZodString;
30
30
  state: z.ZodString;
@@ -5,12 +5,14 @@
5
5
  */
6
6
  import { z } from "zod";
7
7
  import { GENDER } from "../../type";
8
+ import { normalizeIdNumber } from "../../utils/id-number";
9
+ import { toE164Phone } from "../../utils/to-e164-phone";
8
10
  export const admissionFormValidation = z.object({
9
11
  // Student Information
10
12
  registrationCode: z.string().min(1, "Registration code is required"),
11
13
  firstName: z.string().min(1, "First name is required"),
12
14
  lastName: z.string().min(1, "Last name is required"),
13
- studentIdNumber: z.string().min(1, "Student ID number is required"),
15
+ studentIdNumber: z.string().min(1, "Student ID number is required").transform(normalizeIdNumber),
14
16
  dob: z
15
17
  .string()
16
18
  .min(1, "Date of birth is required")
@@ -33,15 +35,21 @@ export const admissionFormValidation = z.object({
33
35
  // Father Information
34
36
  fatherFirstName: z.string().min(1, "Father's first name is required"),
35
37
  fatherLastName: z.string().min(1, "Father's last name is required"),
36
- fatherIdNumber: z.string().min(1, "Father's ID number is required"),
37
- fatherMobile: z.string().min(1, "Father's mobile number is required"),
38
+ fatherIdNumber: z.string().min(1, "Father's ID number is required").transform(normalizeIdNumber),
39
+ fatherMobile: z
40
+ .string()
41
+ .min(1, "Father's mobile number is required")
42
+ .transform((val) => { var _a; return (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val; }),
38
43
  fatherOccupation: z.string().optional(),
39
44
  fatherOrganization: z.string().optional(),
40
45
  // Mother Information
41
46
  motherFirstName: z.string().min(1, "Mother's first name is required"),
42
47
  motherLastName: z.string().min(1, "Mother's last name is required"),
43
- motherIdNumber: z.string().min(1, "Mother's ID number is required"),
44
- motherMobile: z.string().min(1, "Mother's mobile number is required"),
48
+ motherIdNumber: z.string().min(1, "Mother's ID number is required").transform(normalizeIdNumber),
49
+ motherMobile: z
50
+ .string()
51
+ .min(1, "Mother's mobile number is required")
52
+ .transform((val) => { var _a; return (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val; }),
45
53
  // Home Information
46
54
  address: z.string().min(1, "Home address is required"),
47
55
  city: z.string().min(1, "City is required"),
@@ -21,8 +21,8 @@ import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
21
21
  import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
22
22
  import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
23
23
  import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
24
- import { formatNumber } from "@react-pakistan/util-functions/general/format-number";
25
24
  import { formatPhoneDisplay } from "@react-pakistan/util-functions/general/format-phone-display";
25
+ import { toE164Phone } from "../../utils/to-e164-phone";
26
26
  import { pageLimit } from "./constants";
27
27
  import { CAMPUS_API_ROUTES } from "../../constants";
28
28
  import { campusFormValidation } from "./validate";
@@ -75,7 +75,7 @@ export const { actionTypes: CAMPUS_ACTION_TYPES, config: campusModuleConfig, ini
75
75
  // 1.4 ENHANCED CAMPUS HOOK WITH API INTEGRATION
76
76
  // ============================================================================
77
77
  export const useCampusModule = () => {
78
- var _a;
78
+ var _a, _b, _c, _d;
79
79
  // ============================================================================
80
80
  // 1.4.1 STATE & CORE HOOKS
81
81
  // ============================================================================
@@ -85,33 +85,51 @@ export const useCampusModule = () => {
85
85
  const t = useTranslations("campus");
86
86
  const { theme } = useTheme();
87
87
  const workspace = getCachedWorkspaceSync();
88
- const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
89
88
  const debouncedQuery = useDebounce(state.searchQuery, 800);
90
89
  const listFetchNowRef = useRef(null);
91
90
  // ============================================================================
92
91
  // 1.4.2 API PARAMETERS
93
92
  // ============================================================================
94
- const listParams = useMemo(() => (Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterEnabled !== undefined
95
- ? { filterEnabled: String(state.filterEnabled) }
96
- : {}))), [
93
+ const listParams = useMemo(() => {
94
+ var _a;
95
+ return (Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId: ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "" }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterEnabled !== undefined
96
+ ? { filterEnabled: String(state.filterEnabled) }
97
+ : {})));
98
+ }, [
97
99
  state.currentPage,
98
100
  state.filterEnabled,
99
101
  state.pageLimit,
100
102
  debouncedQuery,
101
- schoolId,
103
+ (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id,
104
+ ]);
105
+ const updateParams = useMemo(() => {
106
+ var _a, _b;
107
+ return ({
108
+ address: state.address,
109
+ city: state.city,
110
+ code: state.code,
111
+ country: state.country,
112
+ enabled: state.enabled,
113
+ id: state.id,
114
+ name: state.name,
115
+ phone: toE164Phone(state.phone, (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.country),
116
+ schoolId: state.schoolId || ((_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.id) || "",
117
+ state: state.state,
118
+ });
119
+ }, [
120
+ state.address,
121
+ state.city,
122
+ state.code,
123
+ state.country,
124
+ state.enabled,
125
+ state.id,
126
+ state.name,
127
+ state.phone,
128
+ state.schoolId,
129
+ state.state,
130
+ (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.country,
131
+ (_c = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _c === void 0 ? void 0 : _c.id,
102
132
  ]);
103
- const updateParams = useMemo(() => ({
104
- address: state.address,
105
- city: state.city,
106
- code: state.code,
107
- country: state.country,
108
- enabled: state.enabled,
109
- id: state.id,
110
- name: state.name,
111
- phone: formatNumber(state.phone),
112
- schoolId: state.schoolId || schoolId,
113
- state: state.state,
114
- }), [state, schoolId]);
115
133
  const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
116
134
  const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
117
135
  // ============================================================================
@@ -140,6 +158,7 @@ export const useCampusModule = () => {
140
158
  });
141
159
  }, [dispatch]);
142
160
  const resetRecordFormState = useCallback(() => {
161
+ var _a;
143
162
  dispatch({
144
163
  type: CAMPUS_ACTION_TYPES.SET_ERRORS,
145
164
  payload: { errors: {} },
@@ -161,12 +180,12 @@ export const useCampusModule = () => {
161
180
  id: "",
162
181
  name: "",
163
182
  phone: null,
164
- schoolId,
183
+ schoolId: ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "",
165
184
  state: null,
166
185
  },
167
186
  },
168
187
  });
169
- }, [dispatch, schoolId]);
188
+ }, [dispatch, (_d = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _d === void 0 ? void 0 : _d.id]);
170
189
  // ============================================================================
171
190
  // 1.4.4 API CALLBACKS
172
191
  // ============================================================================
@@ -9,10 +9,14 @@ import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
9
9
  import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
10
10
  import { useCampusModule } from "./context";
11
11
  import { useTranslations } from "next-intl";
12
+ import { formatPhone } from "@react-pakistan/util-functions/general/format-phone";
12
13
  import { getTranslatedError } from "../../utils/get-translated-error";
13
14
  export const CampusForm = () => {
14
15
  const { state, handleChange } = useCampusModule();
15
16
  const { address, city, code, country, enabled, errors, name, phone, state: campusState, } = state;
16
17
  const t = useTranslations("campus");
17
- return (_jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "name", t }), id: "name", info: t("formCampusNameInfo"), label: t("formCampusNameLabel"), onChange: (e) => handleChange("name", e.target.value), placeholder: t("formCampusNamePlaceholder"), required: true, value: name }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "code", t }), id: "code", info: t("formCampusCodeInfo"), label: t("formCampusCodeLabel"), onChange: (e) => handleChange("code", e.target.value), placeholder: t("formCampusCodePlaceholder"), required: true, value: code }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "address", t }), id: "address", info: t("formAddressInfo"), label: t("formAddressLabel"), onChange: (e) => handleChange("address", e.target.value), placeholder: t("formAddressPlaceholder"), value: address || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "city", t }), id: "city", info: t("formCityInfo"), label: t("formCityLabel"), onChange: (e) => handleChange("city", e.target.value), placeholder: t("formCityPlaceholder"), value: city || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "state", t }), id: "state", info: t("formStateInfo"), label: t("formStateLabel"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("formStatePlaceholder"), value: campusState || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "country", t }), id: "country", info: t("formCountryInfo"), label: t("formCountryLabel"), onChange: (e) => handleChange("country", e.target.value), placeholder: t("formCountryPlaceholder"), value: country || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "phone", t }), id: "phone", info: t("formPhoneInfo"), label: t("formPhoneLabel"), onChange: (e) => handleChange("phone", e.target.value), placeholder: t("formPhonePlaceholder"), value: phone || "" }), _jsx(EnhancedCheckbox, { info: t("formActiveCampusInfo"), label: t("formActiveCampusLabel"), defaultChecked: enabled, onCheckedChange: (checked) => handleChange("enabled", checked) })] }));
18
+ return (_jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "name", t }), id: "name", info: t("formCampusNameInfo"), label: t("formCampusNameLabel"), onChange: (e) => handleChange("name", e.target.value), placeholder: t("formCampusNamePlaceholder"), required: true, value: name }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "code", t }), id: "code", info: t("formCampusCodeInfo"), label: t("formCampusCodeLabel"), onChange: (e) => handleChange("code", e.target.value), placeholder: t("formCampusCodePlaceholder"), required: true, value: code }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "address", t }), id: "address", info: t("formAddressInfo"), label: t("formAddressLabel"), onChange: (e) => handleChange("address", e.target.value), placeholder: t("formAddressPlaceholder"), value: address || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "city", t }), id: "city", info: t("formCityInfo"), label: t("formCityLabel"), onChange: (e) => handleChange("city", e.target.value), placeholder: t("formCityPlaceholder"), value: city || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "state", t }), id: "state", info: t("formStateInfo"), label: t("formStateLabel"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("formStatePlaceholder"), value: campusState || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "country", t }), id: "country", info: t("formCountryInfo"), label: t("formCountryLabel"), onChange: (e) => handleChange("country", e.target.value), placeholder: t("formCountryPlaceholder"), value: country || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "phone", t }), id: "phone", info: t("formPhoneInfo"), label: t("formPhoneLabel"), onChange: (e) => {
19
+ var _a;
20
+ return handleChange("phone", ((_a = formatPhone(e.target.value)) === null || _a === void 0 ? void 0 : _a.international) || e.target.value);
21
+ }, placeholder: t("formPhonePlaceholder"), value: phone || "" }), _jsx(EnhancedCheckbox, { info: t("formActiveCampusInfo"), label: t("formActiveCampusLabel"), defaultChecked: enabled, onCheckedChange: (checked) => handleChange("enabled", checked) })] }));
18
22
  };
@@ -19,6 +19,6 @@ export declare const campusFormValidation: z.ZodObject<{
19
19
  city: z.ZodNullable<z.ZodOptional<z.ZodString>>;
20
20
  state: z.ZodNullable<z.ZodOptional<z.ZodString>>;
21
21
  country: z.ZodNullable<z.ZodOptional<z.ZodString>>;
22
- phone: z.ZodNullable<z.ZodOptional<z.ZodString>>;
22
+ phone: z.ZodPipe<z.ZodNullable<z.ZodOptional<z.ZodString>>, z.ZodTransform<string | null | undefined, string | null | undefined>>;
23
23
  enabled: z.ZodOptional<z.ZodBoolean>;
24
24
  }, z.core.$strip>;
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { toE164Phone } from "../../utils/to-e164-phone";
2
3
  export const VALIDATION_KEYS = {
3
4
  nameRequired: "validationCampusNameRequired",
4
5
  nameMaxLength: "validationCampusNameMaxLength",
@@ -47,6 +48,7 @@ export const campusFormValidation = z.object({
47
48
  .string()
48
49
  .max(30, VALIDATION_KEYS.phoneMaxLength)
49
50
  .optional()
50
- .nullable(),
51
+ .nullable()
52
+ .transform((val) => { var _a; return (val ? (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val : val); }),
51
53
  enabled: z.boolean().optional(),
52
54
  });
@@ -26,11 +26,12 @@ import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
26
26
  import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
27
27
  import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
28
28
  import { pageLimit } from "./constants";
29
+ import { normalizeIdNumber } from "../../utils/id-number";
29
30
  import { FAMILY_MEMBER_API_ROUTES } from "../../constants";
30
31
  import { familyMemberFormValidation } from "./validate";
31
32
  import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
32
- import { formatNumber } from "@react-pakistan/util-functions/general/format-number";
33
33
  import { formatPhoneDisplay } from "@react-pakistan/util-functions/general/format-phone-display";
34
+ import { toE164Phone } from "../../utils/to-e164-phone";
34
35
  import { useTranslations } from "next-intl";
35
36
  import { getCachedWorkspaceSync } from "../workspace/cache";
36
37
  import { Eye, Filter, MoreHorizontal, Pencil, Plus } from "lucide-react";
@@ -95,7 +96,7 @@ export const useFamilyMemberModule = () => {
95
96
  // ============================================================================
96
97
  // 1.4.1 STATE & CORE HOOKS
97
98
  // ============================================================================
98
- var _a, _b;
99
+ var _a, _b, _c;
99
100
  const context = useFamilyMemberContext();
100
101
  const { dispatch } = context;
101
102
  const state = context.state;
@@ -120,25 +121,28 @@ export const useFamilyMemberModule = () => {
120
121
  debouncedQuery,
121
122
  (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id,
122
123
  ]);
123
- const updateParams = useMemo(() => ({
124
- id: state.id,
125
- familyId: state.familyId,
126
- role: state.role,
127
- firstName: state.firstName,
128
- lastName: state.lastName,
129
- dateOfBirth: state.dateOfBirth,
130
- gender: state.gender,
131
- bloodGroup: state.bloodGroup,
132
- phone: formatNumber(state.phone),
133
- email: state.email,
134
- relationship: state.relationship,
135
- occupation: state.occupation,
136
- emergencyPhone: formatNumber(state.emergencyPhone),
137
- idNumber: state.idNumber,
138
- avatar: state.avatar,
139
- isPrimary: state.isPrimary,
140
- enabled: state.enabled,
141
- }), [
124
+ const updateParams = useMemo(() => {
125
+ var _a, _b;
126
+ return ({
127
+ id: state.id,
128
+ familyId: state.familyId,
129
+ role: state.role,
130
+ firstName: state.firstName,
131
+ lastName: state.lastName,
132
+ dateOfBirth: state.dateOfBirth,
133
+ gender: state.gender,
134
+ bloodGroup: state.bloodGroup,
135
+ phone: toE164Phone(state.phone, (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.country),
136
+ email: state.email,
137
+ relationship: state.relationship,
138
+ occupation: state.occupation,
139
+ emergencyPhone: toE164Phone(state.emergencyPhone, (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.country),
140
+ idNumber: state.idNumber,
141
+ avatar: state.avatar,
142
+ isPrimary: state.isPrimary,
143
+ enabled: state.enabled,
144
+ });
145
+ }, [
142
146
  state.avatar,
143
147
  state.bloodGroup,
144
148
  state.dateOfBirth,
@@ -156,6 +160,7 @@ export const useFamilyMemberModule = () => {
156
160
  state.phone,
157
161
  state.relationship,
158
162
  state.role,
163
+ (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.country,
159
164
  ]);
160
165
  const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
161
166
  const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
@@ -407,7 +412,7 @@ export const useFamilyMemberModule = () => {
407
412
  schema: familyMemberFormValidation,
408
413
  successCallback: () => {
409
414
  updateFetchNow(undefined, {
410
- body: JSON.stringify(updateParams),
415
+ body: JSON.stringify(Object.assign(Object.assign({}, updateParams), { idNumber: normalizeIdNumber(updateParams.idNumber) })),
411
416
  });
412
417
  },
413
418
  errorCallback: (errors) => {
@@ -476,7 +481,7 @@ export const useFamilyMemberModule = () => {
476
481
  if (!((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id))
477
482
  return;
478
483
  (_b = listFetchNowRef.current) === null || _b === void 0 ? void 0 : _b.call(listFetchNowRef);
479
- }, [listParams, (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.id]);
484
+ }, [listParams, (_c = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _c === void 0 ? void 0 : _c.id]);
480
485
  // ============================================================================
481
486
  // 1.4.10 RETURN
482
487
  // ============================================================================
@@ -9,10 +9,17 @@ import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
9
9
  import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
10
10
  import { useFamilyMemberModule } from "./context";
11
11
  import { useTranslations } from "next-intl";
12
+ import { formatPhone } from "@react-pakistan/util-functions/general/format-phone";
12
13
  import { getTranslatedError } from "../../utils/get-translated-error";
13
14
  export const FamilyMemberForm = () => {
14
15
  const { handleChange, state } = useFamilyMemberModule();
15
16
  const { bloodGroup, dateOfBirth, email, emergencyPhone, enabled, errors, firstName, gender, idNumber, isPrimary, lastName, occupation, phone, relationship, role, } = state;
16
17
  const t = useTranslations("familyMember");
17
- return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionPersonalInformation") }), _jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "firstName", t }), id: "firstName", info: t("formFirstNameInfo"), label: t("formFirstNameLabel"), onChange: (e) => handleChange("firstName", e.target.value), placeholder: t("formFirstNamePlaceholder"), required: true, value: firstName }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "lastName", t }), id: "lastName", info: t("formLastNameInfo"), label: t("formLastNameLabel"), onChange: (e) => handleChange("lastName", e.target.value), placeholder: t("formLastNamePlaceholder"), required: true, value: lastName })] }), _jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "role", t }), id: "role", info: t("formRoleInfo"), label: t("formRoleLabel"), onChange: (e) => handleChange("role", e.target.value), placeholder: t("formRolePlaceholder"), required: true, value: role }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "dateOfBirth", t }), id: "dateOfBirth", info: t("formDateOfBirthInfo"), label: t("formDateOfBirthLabel"), onChange: (e) => handleChange("dateOfBirth", e.target.value), placeholder: "YYYY-MM-DD", type: "date", value: dateOfBirth })] }), _jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "gender", t }), id: "gender", info: t("formGenderInfo"), label: t("formGenderLabel"), onChange: (e) => handleChange("gender", e.target.value), placeholder: t("formGenderPlaceholder"), value: gender }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "bloodGroup", t }), id: "bloodGroup", info: t("formBloodGroupInfo"), label: t("formBloodGroupLabel"), onChange: (e) => handleChange("bloodGroup", e.target.value), placeholder: t("formBloodGroupPlaceholder"), value: bloodGroup })] }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "idNumber", t }), id: "idNumber", info: t("formIdNumberInfo"), label: t("formIdNumberLabel"), onChange: (e) => handleChange("idNumber", e.target.value), placeholder: t("formIdNumberPlaceholder"), value: idNumber })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionContactInformation") }), _jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "phone", t }), id: "phone", info: t("formPhoneInfo"), label: t("formPhoneLabel"), onChange: (e) => handleChange("phone", e.target.value), placeholder: t("formPhonePlaceholder"), type: "tel", value: phone }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "email", t }), id: "email", info: t("formEmailInfo"), label: t("formEmailLabel"), onChange: (e) => handleChange("email", e.target.value), placeholder: t("formEmailPlaceholder"), type: "email", value: email })] }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "emergencyPhone", t }), id: "emergencyPhone", info: t("formEmergencyPhoneInfo"), label: t("formEmergencyPhoneLabel"), onChange: (e) => handleChange("emergencyPhone", e.target.value), placeholder: t("formEmergencyPhonePlaceholder"), type: "tel", value: emergencyPhone })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionAdditionalInformation") }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "relationship", t }), id: "relationship", info: t("formRelationshipInfo"), label: t("formRelationshipLabel"), onChange: (e) => handleChange("relationship", e.target.value), placeholder: t("formRelationshipPlaceholder"), value: relationship }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "occupation", t }), id: "occupation", info: t("formOccupationInfo"), label: t("formOccupationLabel"), onChange: (e) => handleChange("occupation", e.target.value), placeholder: t("formOccupationPlaceholder"), value: occupation })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionStatus") }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx(EnhancedCheckbox, { checked: isPrimary, id: "isPrimary", label: t("formPrimaryContactLabel"), onCheckedChange: (checked) => handleChange("isPrimary", checked === true) }), _jsx(EnhancedCheckbox, { checked: enabled, id: "enabled", label: t("badgeActive"), onCheckedChange: (checked) => handleChange("enabled", checked === true) })] })] })] }));
18
+ return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionPersonalInformation") }), _jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "firstName", t }), id: "firstName", info: t("formFirstNameInfo"), label: t("formFirstNameLabel"), onChange: (e) => handleChange("firstName", e.target.value), placeholder: t("formFirstNamePlaceholder"), required: true, value: firstName }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "lastName", t }), id: "lastName", info: t("formLastNameInfo"), label: t("formLastNameLabel"), onChange: (e) => handleChange("lastName", e.target.value), placeholder: t("formLastNamePlaceholder"), required: true, value: lastName })] }), _jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "role", t }), id: "role", info: t("formRoleInfo"), label: t("formRoleLabel"), onChange: (e) => handleChange("role", e.target.value), placeholder: t("formRolePlaceholder"), required: true, value: role }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "dateOfBirth", t }), id: "dateOfBirth", info: t("formDateOfBirthInfo"), label: t("formDateOfBirthLabel"), onChange: (e) => handleChange("dateOfBirth", e.target.value), placeholder: "YYYY-MM-DD", type: "date", value: dateOfBirth })] }), _jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "gender", t }), id: "gender", info: t("formGenderInfo"), label: t("formGenderLabel"), onChange: (e) => handleChange("gender", e.target.value), placeholder: t("formGenderPlaceholder"), value: gender }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "bloodGroup", t }), id: "bloodGroup", info: t("formBloodGroupInfo"), label: t("formBloodGroupLabel"), onChange: (e) => handleChange("bloodGroup", e.target.value), placeholder: t("formBloodGroupPlaceholder"), value: bloodGroup })] }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "idNumber", t }), id: "idNumber", info: t("formIdNumberInfo"), label: t("formIdNumberLabel"), onChange: (e) => handleChange("idNumber", e.target.value), placeholder: t("formIdNumberPlaceholder"), value: idNumber })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionContactInformation") }), _jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "phone", t }), id: "phone", info: t("formPhoneInfo"), label: t("formPhoneLabel"), onChange: (e) => {
19
+ var _a;
20
+ return handleChange("phone", ((_a = formatPhone(e.target.value)) === null || _a === void 0 ? void 0 : _a.international) || e.target.value);
21
+ }, placeholder: t("formPhonePlaceholder"), type: "tel", value: phone }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "email", t }), id: "email", info: t("formEmailInfo"), label: t("formEmailLabel"), onChange: (e) => handleChange("email", e.target.value), placeholder: t("formEmailPlaceholder"), type: "email", value: email })] }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "emergencyPhone", t }), id: "emergencyPhone", info: t("formEmergencyPhoneInfo"), label: t("formEmergencyPhoneLabel"), onChange: (e) => {
22
+ var _a;
23
+ return handleChange("emergencyPhone", ((_a = formatPhone(e.target.value)) === null || _a === void 0 ? void 0 : _a.international) || e.target.value);
24
+ }, placeholder: t("formEmergencyPhonePlaceholder"), type: "tel", value: emergencyPhone })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionAdditionalInformation") }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "relationship", t }), id: "relationship", info: t("formRelationshipInfo"), label: t("formRelationshipLabel"), onChange: (e) => handleChange("relationship", e.target.value), placeholder: t("formRelationshipPlaceholder"), value: relationship }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "occupation", t }), id: "occupation", info: t("formOccupationInfo"), label: t("formOccupationLabel"), onChange: (e) => handleChange("occupation", e.target.value), placeholder: t("formOccupationPlaceholder"), value: occupation })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionStatus") }), _jsxs("div", { className: "flex items-center gap-4", children: [_jsx(EnhancedCheckbox, { checked: isPrimary, id: "isPrimary", label: t("formPrimaryContactLabel"), onCheckedChange: (checked) => handleChange("isPrimary", checked === true) }), _jsx(EnhancedCheckbox, { checked: enabled, id: "enabled", label: t("badgeActive"), onCheckedChange: (checked) => handleChange("enabled", checked === true) })] })] })] }));
18
25
  };
@@ -20,12 +20,12 @@ export declare const familyMemberFormValidation: z.ZodObject<{
20
20
  dateOfBirth: z.ZodOptional<z.ZodString>;
21
21
  gender: z.ZodOptional<z.ZodString>;
22
22
  bloodGroup: z.ZodOptional<z.ZodString>;
23
- phone: z.ZodOptional<z.ZodString>;
23
+ phone: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string | undefined, string | undefined>>;
24
24
  email: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
25
25
  relationship: z.ZodOptional<z.ZodString>;
26
26
  occupation: z.ZodOptional<z.ZodString>;
27
- emergencyPhone: z.ZodOptional<z.ZodString>;
28
- idNumber: z.ZodOptional<z.ZodString>;
27
+ emergencyPhone: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string | undefined, string | undefined>>;
28
+ idNumber: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string | null | undefined, string | undefined>>;
29
29
  avatar: z.ZodOptional<z.ZodString>;
30
30
  isPrimary: z.ZodOptional<z.ZodBoolean>;
31
31
  enabled: z.ZodOptional<z.ZodBoolean>;
@@ -4,6 +4,8 @@
4
4
  * Zod validation schemas for family-member form data.
5
5
  */
6
6
  import { z } from "zod";
7
+ import { normalizeIdNumber } from "../../utils/id-number";
8
+ import { toE164Phone } from "../../utils/to-e164-phone";
7
9
  // ============================================================================
8
10
  // VALIDATION KEYS (used as Zod error messages, translated via getTranslatedError)
9
11
  // ============================================================================
@@ -26,7 +28,7 @@ export const familyMemberFormValidation = z.object({
26
28
  dateOfBirth: z.string().optional(),
27
29
  gender: z.string().optional(),
28
30
  bloodGroup: z.string().optional(),
29
- phone: z.string().optional(),
31
+ phone: z.string().optional().transform((val) => { var _a; return (val ? (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val : val); }),
30
32
  email: z
31
33
  .string()
32
34
  .email(VALIDATION_KEYS.emailInvalid)
@@ -34,8 +36,8 @@ export const familyMemberFormValidation = z.object({
34
36
  .or(z.literal("")),
35
37
  relationship: z.string().optional(),
36
38
  occupation: z.string().optional(),
37
- emergencyPhone: z.string().optional(),
38
- idNumber: z.string().optional(),
39
+ emergencyPhone: z.string().optional().transform((val) => { var _a; return (val ? (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val : val); }),
40
+ idNumber: z.string().optional().transform((val) => (val ? normalizeIdNumber(val) : val)),
39
41
  avatar: z.string().optional(),
40
42
  isPrimary: z.boolean().optional(),
41
43
  enabled: z.boolean().optional(),