@appcorp/fusion-storybook 0.2.93 → 0.2.95

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 (32) hide show
  1. package/base-modules/admission/context/use-admission-module.js +17 -16
  2. package/base-modules/admission/validate.d.ts +2 -2
  3. package/base-modules/admission/validate.js +9 -2
  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 +26 -22
  9. package/base-modules/family-member/form.js +8 -1
  10. package/base-modules/family-member/validate.d.ts +2 -2
  11. package/base-modules/family-member/validate.js +3 -2
  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/context/use-student-fee-module.js +34 -28
  17. package/base-modules/student-fee/form.js +1 -1
  18. package/base-modules/student-profile/context/use-student-profile-module.js +33 -27
  19. package/base-modules/student-profile/form.js +8 -1
  20. package/base-modules/student-profile/validate.d.ts +2 -2
  21. package/base-modules/student-profile/validate.js +3 -4
  22. package/base-modules/teacher/context.js +1 -1
  23. package/base-modules/teacher/form.js +8 -1
  24. package/base-modules/teacher/validate.d.ts +2 -2
  25. package/base-modules/teacher/validate.js +11 -2
  26. package/base-modules/user/context/use-user-module.js +16 -12
  27. package/base-modules/user/validate.d.ts +1 -1
  28. package/base-modules/user/validate.js +2 -2
  29. package/package.json +1 -1
  30. package/tsconfig.build.tsbuildinfo +1 -1
  31. package/utils/to-e164-phone.d.ts +1 -0
  32. package/utils/to-e164-phone.js +11 -0
@@ -4,6 +4,7 @@
4
4
  * Zod validation schemas for account-school form data.
5
5
  */
6
6
  import { z } from "zod";
7
+ import { toE164Phone } from "../../utils/to-e164-phone";
7
8
  // ============================================================================
8
9
  // VALIDATION KEYS
9
10
  // ============================================================================
@@ -27,7 +28,11 @@ export const schoolFormValidation = z.object({
27
28
  state: z.string().nullable().optional(),
28
29
  country: z.string().nullable().optional(),
29
30
  postalCode: z.string().nullable().optional(),
30
- phone: z.string().nullable().optional(),
31
+ phone: z
32
+ .string()
33
+ .nullable()
34
+ .optional()
35
+ .transform((val) => { var _a; return (val ? (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val : val); }),
31
36
  email: z.string().email(VALIDATION_KEYS.email).nullable().optional(),
32
37
  website: z.string().url(VALIDATION_KEYS.website).nullable().optional(),
33
38
  logo: z.string().nullable().optional(),
@@ -29,45 +29,50 @@ export const useStudentFeeModule = () => {
29
29
  // ============================================================================
30
30
  // 1.4.1 STATE & CORE HOOKS
31
31
  // ============================================================================
32
- var _a;
32
+ var _a, _b, _c, _d;
33
33
  const context = useStudentFeeContext();
34
34
  const { dispatch } = context;
35
35
  const state = context.state;
36
36
  const t = useTranslations("studentFee");
37
37
  const { theme } = useTheme();
38
38
  const workspace = getCachedWorkspaceSync();
39
- const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
40
39
  const listFetchNowRef = useRef(null);
41
40
  const debouncedQuery = useDebounce(state.searchQuery, 800);
42
41
  // ============================================================================
43
42
  // 1.4.2 API PARAMETERS
44
43
  // ============================================================================
45
- const listParams = useMemo(() => (Object.assign(Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterEnabled !== undefined
46
- ? { filterEnabled: state.filterEnabled }
47
- : {})), (state.filterStatus ? { status: state.filterStatus } : {}))), [
44
+ const listParams = useMemo(() => {
45
+ var _a;
46
+ return (Object.assign(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
47
+ ? { filterEnabled: state.filterEnabled }
48
+ : {})), (state.filterStatus ? { status: state.filterStatus } : {})));
49
+ }, [
48
50
  state.currentPage,
49
51
  state.filterEnabled,
50
52
  state.filterStatus,
51
53
  state.pageLimit,
52
54
  debouncedQuery,
53
- schoolId,
55
+ (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id,
54
56
  ]);
55
- const updateParams = useMemo(() => ({
56
- amount: Number(state.amount),
57
- amountDue: Number(state.amountDue),
58
- amountPaid: Number(state.amountPaid),
59
- discountAmount: Number(state.discountAmount),
60
- discountCodeId: state.discountCodeId,
61
- dueDate: state.dueDate,
62
- enabled: state.enabled,
63
- familyId: state.familyId,
64
- feeStructureId: state.feeStructureId,
65
- id: state.id,
66
- remarks: state.remarks || null,
67
- schoolId,
68
- status: state.status,
69
- studentProfileId: state.studentProfileId,
70
- }), [state, schoolId]);
57
+ const updateParams = useMemo(() => {
58
+ var _a;
59
+ return ({
60
+ amount: Number(state.amount),
61
+ amountDue: Number(state.amountDue),
62
+ amountPaid: Number(state.amountPaid),
63
+ discountAmount: Number(state.discountAmount),
64
+ discountCodeId: state.discountCodeId,
65
+ dueDate: state.dueDate,
66
+ enabled: state.enabled,
67
+ familyId: state.familyId,
68
+ feeStructureId: state.feeStructureId,
69
+ id: state.id,
70
+ remarks: state.remarks || null,
71
+ schoolId: ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "",
72
+ status: state.status,
73
+ studentProfileId: state.studentProfileId,
74
+ });
75
+ }, [state, (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.id]);
71
76
  const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
72
77
  const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
73
78
  // ============================================================================
@@ -96,6 +101,7 @@ export const useStudentFeeModule = () => {
96
101
  });
97
102
  }, [dispatch]);
98
103
  const resetRecordFormState = useCallback(() => {
104
+ var _a;
99
105
  dispatch({
100
106
  type: STUDENT_FEE_ACTION_TYPES.SET_ERRORS,
101
107
  payload: { errors: {} },
@@ -126,13 +132,13 @@ export const useStudentFeeModule = () => {
126
132
  reliabilityScore: null,
127
133
  remarks: null,
128
134
  riskLevel: null,
129
- schoolId,
135
+ schoolId: ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "",
130
136
  status: PAYMENT_STATUS.PENDING,
131
137
  studentProfileId: "",
132
138
  },
133
139
  },
134
140
  });
135
- }, [dispatch, schoolId]);
141
+ }, [dispatch, (_c = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _c === void 0 ? void 0 : _c.id]);
136
142
  // ============================================================================
137
143
  // 1.4.4 API CALLBACKS
138
144
  // ============================================================================
@@ -591,11 +597,11 @@ export const useStudentFeeModule = () => {
591
597
  listFetchNowRef.current = listFetchNow;
592
598
  }, [listFetchNow]);
593
599
  useEffect(() => {
594
- var _a;
595
- if (!schoolId)
600
+ var _a, _b;
601
+ if (!((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id))
596
602
  return;
597
- (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
598
- }, [dispatch, listParams, schoolId, showToast, t]);
603
+ (_b = listFetchNowRef.current) === null || _b === void 0 ? void 0 : _b.call(listFetchNowRef);
604
+ }, [dispatch, listParams, (_d = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _d === void 0 ? void 0 : _d.id, showToast, t]);
599
605
  // ============================================================================
600
606
  // 1.4.10 RETURN
601
607
  // ============================================================================
@@ -23,7 +23,7 @@ import { getTranslatedError } from "../../utils/get-translated-error";
23
23
  export const StudentFeeForm = () => {
24
24
  var _a, _b, _c, _d, _e;
25
25
  const { state, handleChange } = useStudentFeeModule();
26
- const { amount, amountDue, amountPaid, discountAmount, discountCodeId, dueDate, enabled, errors, familyId, feeStructureId, remarks, status, studentProfileId, } = state;
26
+ const { amount, amountDue, amountPaid, discountAmount, discountCodeId, dueDate, enabled, errors, feeStructureId, remarks, status, studentProfileId, } = state;
27
27
  const workspace = getCachedWorkspaceSync();
28
28
  const currency = (_b = (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.currency) !== null && _b !== void 0 ? _b : "";
29
29
  const t = useTranslations("studentFee");
@@ -6,50 +6,55 @@ import { useModuleEntityV2, } from "@react-pakistan/util-functions/hooks/use-mod
6
6
  import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
7
7
  import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
8
8
  import { STUDENT_STATUS } from "../../../type";
9
- import { formatNumber } from "@react-pakistan/util-functions/general/format-number";
10
9
  import { formatPhoneDisplay } from "@react-pakistan/util-functions/general/format-phone-display";
10
+ import { toE164Phone } from "../../../utils/to-e164-phone";
11
11
  import { STUDENT_PROFILE_API_ROUTES } from "../../../constants";
12
12
  import { studentProfileFormValidation } from "../validate";
13
13
  import { getCachedWorkspaceSync } from "../../workspace/cache";
14
14
  import { useStudentProfileContext, STUDENT_PROFILE_ACTION_TYPES, STUDENT_PROFILE_DRAWER, } from "./module-base";
15
15
  export const useStudentProfileModule = () => {
16
- var _a;
16
+ var _a, _b, _c;
17
17
  const context = useStudentProfileContext();
18
18
  const { dispatch } = context;
19
19
  const state = context.state;
20
20
  const t = useTranslations("studentProfile");
21
21
  const { theme } = useTheme();
22
22
  const workspace = getCachedWorkspaceSync();
23
- const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
24
23
  const listFetchNowRef = useRef(null);
25
24
  const debouncedQuery = useDebounce(state.searchQuery, 800);
26
- const listParams = useMemo(() => (Object.assign(Object.assign(Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterEnabled !== undefined
27
- ? { filterEnabled: String(state.filterEnabled) }
28
- : {})), (state.filterGender ? { filterGender: state.filterGender } : {})), (state.filterStatus ? { filterStatus: state.filterStatus } : {}))), [
25
+ const listParams = useMemo(() => {
26
+ var _a;
27
+ return (Object.assign(Object.assign(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
28
+ ? { filterEnabled: String(state.filterEnabled) }
29
+ : {})), (state.filterGender ? { filterGender: state.filterGender } : {})), (state.filterStatus ? { filterStatus: state.filterStatus } : {})));
30
+ }, [
29
31
  state.currentPage,
30
32
  state.filterEnabled,
31
33
  state.filterGender,
32
34
  state.filterStatus,
33
35
  state.pageLimit,
34
36
  debouncedQuery,
35
- schoolId,
37
+ (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id,
36
38
  ]);
37
- const updateParams = useMemo(() => ({
38
- avatar: state.avatar,
39
- bloodGroup: state.bloodGroup,
40
- dateOfBirth: state.dateOfBirth,
41
- email: state.email,
42
- emergencyPhone: formatNumber(state.emergencyPhone),
43
- enabled: state.enabled,
44
- familyMemberId: state.familyMemberId,
45
- firstName: state.firstName,
46
- gender: state.gender,
47
- id: state.id,
48
- lastName: state.lastName,
49
- phone: formatNumber(state.phone),
50
- status: state.status,
51
- studentCode: state.studentCode,
52
- }), [
39
+ const updateParams = useMemo(() => {
40
+ var _a, _b;
41
+ return ({
42
+ avatar: state.avatar,
43
+ bloodGroup: state.bloodGroup,
44
+ dateOfBirth: state.dateOfBirth,
45
+ email: state.email,
46
+ emergencyPhone: toE164Phone(state.emergencyPhone, (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.country),
47
+ enabled: state.enabled,
48
+ familyMemberId: state.familyMemberId,
49
+ firstName: state.firstName,
50
+ gender: state.gender,
51
+ id: state.id,
52
+ lastName: state.lastName,
53
+ phone: toE164Phone(state.phone, (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.country),
54
+ status: state.status,
55
+ studentCode: state.studentCode,
56
+ });
57
+ }, [
53
58
  state.avatar,
54
59
  state.bloodGroup,
55
60
  state.dateOfBirth,
@@ -64,6 +69,7 @@ export const useStudentProfileModule = () => {
64
69
  state.phone,
65
70
  state.status,
66
71
  state.studentCode,
72
+ (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.country,
67
73
  ]);
68
74
  const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
69
75
  const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
@@ -478,11 +484,11 @@ export const useStudentProfileModule = () => {
478
484
  listFetchNowRef.current = listFetchNow;
479
485
  }, [listFetchNow]);
480
486
  useEffect(() => {
481
- var _a;
482
- if (!schoolId)
487
+ var _a, _b;
488
+ if (!((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id))
483
489
  return;
484
- (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
485
- }, [dispatch, listParams, schoolId, showToast, t]);
490
+ (_b = listFetchNowRef.current) === null || _b === void 0 ? void 0 : _b.call(listFetchNowRef);
491
+ }, [dispatch, listParams, (_c = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _c === void 0 ? void 0 : _c.id, showToast, t]);
486
492
  return Object.assign(Object.assign({}, context), { applyFilters,
487
493
  byIdLoading,
488
494
  clearFilters,
@@ -8,6 +8,7 @@ import { useTranslations } from "next-intl";
8
8
  import { useStudentProfileModule } from "./context";
9
9
  import { STATUS_OPTIONS, GENDER_OPTIONS } from "./constants";
10
10
  import { STUDENT_PROFILE_API_ROUTES } from "../../constants";
11
+ import { formatPhone } from "@react-pakistan/util-functions/general/format-phone";
11
12
  import { getTranslatedError } from "../../utils/get-translated-error";
12
13
  export const StudentProfileForm = () => {
13
14
  const t = useTranslations("studentProfile");
@@ -63,5 +64,11 @@ export const StudentProfileForm = () => {
63
64
  });
64
65
  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", 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 }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "dateOfBirth", t }), id: "dateOfBirth", info: t("formDateOfBirthInfo"), label: t("formDateOfBirthLabel"), onChange: (e) => handleChange("dateOfBirth", e.target.value), onClick: (e) => { var _a, _b; return (_b = (_a = e.currentTarget).showPicker) === null || _b === void 0 ? void 0 : _b.call(_a); }, type: "date", value: dateOfBirth
65
66
  ? new Date(dateOfBirth).toISOString().split("formTLabel")[0]
66
- : "" }), genderCombo] })] }), _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", 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: "emergencyPhone", t }), id: "emergencyPhone", info: t("formEmergencyPhoneInfo"), label: t("formEmergencyPhoneLabel"), onChange: (e) => handleChange("emergencyPhone", e.target.value), placeholder: t("formEmergencyPhonePlaceholder"), type: "tel", value: emergencyPhone || "" })] }), _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 || "" }), _jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_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("formStateProvinceLabel"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("formStatePlaceholder"), value: stateValue || "" }), _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: "postalCode", t }), id: "postalCode", info: t("formPostalCodeInfo"), label: t("formPostalCodeLabel"), onChange: (e) => handleChange("postalCode", e.target.value), placeholder: t("formPostalCodePlaceholder"), value: postalCode || "" })] })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionAcademicInformation") }), _jsxs("div", { className: "grid grid-cols-1 gap-4", children: [statusCombo, _jsx(EnhancedTextarea, { error: getTranslatedError({ errors, key: "remarks", t }), id: "remarks", info: t("formRemarksInfo"), label: t("formRemarksLabel"), onChange: (e) => handleChange("remarks", e.target.value), placeholder: t("formRemarksPlaceholder"), rows: 4, value: remarks || "" })] }), _jsx(EnhancedCheckbox, { checked: enabled, info: t("formEnabledInfo"), label: t("formEnabledLabel"), onCheckedChange: (checked) => handleChange("enabled", checked) })] })] }));
67
+ : "" }), genderCombo] })] }), _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", children: [_jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "phone", t }), id: "phone", info: t("formPhoneInfo"), label: t("formPhoneLabel"), onChange: (e) => {
68
+ var _a;
69
+ return handleChange("phone", ((_a = formatPhone(e.target.value)) === null || _a === void 0 ? void 0 : _a.international) || e.target.value);
70
+ }, placeholder: t("formPhonePlaceholder"), type: "tel", value: phone || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "emergencyPhone", t }), id: "emergencyPhone", info: t("formEmergencyPhoneInfo"), label: t("formEmergencyPhoneLabel"), onChange: (e) => {
71
+ var _a;
72
+ return handleChange("emergencyPhone", ((_a = formatPhone(e.target.value)) === null || _a === void 0 ? void 0 : _a.international) || e.target.value);
73
+ }, placeholder: t("formEmergencyPhonePlaceholder"), type: "tel", value: emergencyPhone || "" })] }), _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 || "" }), _jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_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("formStateProvinceLabel"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("formStatePlaceholder"), value: stateValue || "" }), _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: "postalCode", t }), id: "postalCode", info: t("formPostalCodeInfo"), label: t("formPostalCodeLabel"), onChange: (e) => handleChange("postalCode", e.target.value), placeholder: t("formPostalCodePlaceholder"), value: postalCode || "" })] })] }), _jsxs("div", { className: "space-y-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: t("formSectionAcademicInformation") }), _jsxs("div", { className: "grid grid-cols-1 gap-4", children: [statusCombo, _jsx(EnhancedTextarea, { error: getTranslatedError({ errors, key: "remarks", t }), id: "remarks", info: t("formRemarksInfo"), label: t("formRemarksLabel"), onChange: (e) => handleChange("remarks", e.target.value), placeholder: t("formRemarksPlaceholder"), rows: 4, value: remarks || "" })] }), _jsx(EnhancedCheckbox, { checked: enabled, info: t("formEnabledInfo"), label: t("formEnabledLabel"), onCheckedChange: (checked) => handleChange("enabled", checked) })] })] }));
67
74
  };
@@ -13,8 +13,8 @@ export declare const VALIDATION_KEYS: {
13
13
  export declare const studentProfileFormValidation: z.ZodObject<{
14
14
  firstName: z.ZodString;
15
15
  lastName: z.ZodString;
16
- phone: z.ZodOptional<z.ZodString>;
17
- emergencyPhone: z.ZodOptional<z.ZodString>;
16
+ phone: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string | undefined, string | undefined>>;
17
+ emergencyPhone: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string | undefined, string | undefined>>;
18
18
  status: z.ZodString;
19
19
  dateOfBirth: z.ZodOptional<z.ZodString>;
20
20
  enrollmentDate: z.ZodOptional<z.ZodString>;
@@ -4,6 +4,7 @@
4
4
  * Zod validation schemas for student profile form data.
5
5
  */
6
6
  import { z } from "zod";
7
+ import { toE164Phone } from "../../utils/to-e164-phone";
7
8
  export const VALIDATION_KEYS = {
8
9
  firstNameRequired: "validationStudentProfileFirstNameRequired",
9
10
  lastNameRequired: "validationStudentProfileLastNameRequired",
@@ -16,13 +17,11 @@ export const studentProfileFormValidation = z.object({
16
17
  phone: z
17
18
  .string()
18
19
  .optional()
19
- .refine((val) => !val ||
20
- /^([+]?[\s0-9]+)?(\d{3}|[(]?[0-9]+[)]?)?([-]?[\s]?[0-9])+$/.test(val), VALIDATION_KEYS.phoneInvalid),
20
+ .transform((val) => { var _a; return (val ? (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val : val); }),
21
21
  emergencyPhone: z
22
22
  .string()
23
23
  .optional()
24
- .refine((val) => !val ||
25
- /^([+]?[\s0-9]+)?(\d{3}|[(]?[0-9]+[)]?)?([-]?[\s]?[0-9])+$/.test(val), VALIDATION_KEYS.phoneInvalid),
24
+ .transform((val) => { var _a; return (val ? (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val : val); }),
26
25
  status: z.string().min(1, VALIDATION_KEYS.statusRequired),
27
26
  dateOfBirth: z.string().optional(),
28
27
  enrollmentDate: z.string().optional(),
@@ -456,7 +456,7 @@ export const useTeacherModule = () => {
456
456
  finally {
457
457
  uploadInProgressRef.current = false;
458
458
  }
459
- }, [dispatch, showToast, state.id, workspace === null || workspace === void 0 ? void 0 : workspace.id]);
459
+ }, [dispatch, showToast, state.id, t, workspace === null || workspace === void 0 ? void 0 : workspace.id]);
460
460
  const applyFilters = useCallback(() => {
461
461
  dispatch({
462
462
  type: TEACHER_ACTION_TYPES.SET_CURRENT_PAGE,
@@ -9,6 +9,7 @@ import { useTranslations } from "next-intl";
9
9
  import { useTeacherModule } from "./context";
10
10
  import { GENDER_OPTIONS } from "./constants";
11
11
  import { TEACHER_API_ROUTES } from "../../constants";
12
+ import { formatPhone } from "@react-pakistan/util-functions/general/format-phone";
12
13
  import { getTranslatedError } from "../../utils/get-translated-error";
13
14
  export const TeacherForm = () => {
14
15
  const t = useTranslations("teacher");
@@ -45,7 +46,13 @@ export const TeacherForm = () => {
45
46
  ? new Date(joiningDate).toISOString().split("T")[0]
46
47
  : "" }), genderCombo, _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "dateOfBirth", t }), id: "dateOfBirth", info: t("formDateOfBirthInfo"), label: t("formDateOfBirthLabel"), onChange: (e) => handleChange("dateOfBirth", e.target.value), onClick: (e) => { var _a, _b; return (_b = (_a = e.currentTarget).showPicker) === null || _b === void 0 ? void 0 : _b.call(_a); }, type: "date", value: dateOfBirth
47
48
  ? new Date(dateOfBirth).toISOString().split("T")[0]
48
- : "" }), _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: "emergencyPhone", t }), id: "emergencyPhone", info: t("formEmergencyPhoneInfo"), label: t("formEmergencyPhoneLabel"), onChange: (e) => handleChange("emergencyPhone", e.target.value), placeholder: t("formEmergencyPhonePlaceholder"), type: "tel", value: emergencyPhone || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "qualification", t }), id: "qualification", info: t("formQualificationInfo"), label: t("formQualificationLabel"), onChange: (e) => handleChange("qualification", e.target.value), placeholder: t("formQualificationPlaceholder"), value: qualification || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "specialization", t }), id: "specialization", info: t("formSpecializationInfo"), label: t("formSpecializationLabel"), onChange: (e) => handleChange("specialization", e.target.value), placeholder: t("formSpecializationPlaceholder"), value: specialization || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "experience", t }), id: "experience", info: t("formExperienceInfo"), label: t("formExperienceLabel"), onChange: (e) => handleChange("experience", parseInt(e.target.value) || null), placeholder: t("formExperiencePlaceholder"), type: "number", value: (experience === null || experience === void 0 ? void 0 : experience.toString()) || "" }), _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("formStateProvinceInfo"), label: t("formStateProvinceLabel"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("formStatePlaceholder"), value: stateValue || "" }), _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: "postalCode", t }), id: "postalCode", info: t("formPostalCodeInfo"), label: t("formPostalCodeLabel"), onChange: (e) => handleChange("postalCode", e.target.value), placeholder: t("formPostalCodePlaceholder"), value: postalCode || "" }), _jsx(EnhancedDropzone, { accept: ["image/*"], error: getTranslatedError({ errors, key: "avatar", t }), id: "avatar", info: t("formAvatarInfo"), label: t("formAvatarLabel"), maxFiles: 1, maxSize: 100 * 1024, onChange: (files) => {
49
+ : "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "phone", t }), id: "phone", info: t("formPhoneInfo"), label: t("formPhoneLabel"), onChange: (e) => {
50
+ var _a;
51
+ return handleChange("phone", ((_a = formatPhone(e.target.value)) === null || _a === void 0 ? void 0 : _a.international) || e.target.value);
52
+ }, placeholder: t("formPhonePlaceholder"), type: "tel", value: phone || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "emergencyPhone", t }), id: "emergencyPhone", info: t("formEmergencyPhoneInfo"), label: t("formEmergencyPhoneLabel"), onChange: (e) => {
53
+ var _a;
54
+ return handleChange("emergencyPhone", ((_a = formatPhone(e.target.value)) === null || _a === void 0 ? void 0 : _a.international) || e.target.value);
55
+ }, placeholder: t("formEmergencyPhonePlaceholder"), type: "tel", value: emergencyPhone || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "qualification", t }), id: "qualification", info: t("formQualificationInfo"), label: t("formQualificationLabel"), onChange: (e) => handleChange("qualification", e.target.value), placeholder: t("formQualificationPlaceholder"), value: qualification || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "specialization", t }), id: "specialization", info: t("formSpecializationInfo"), label: t("formSpecializationLabel"), onChange: (e) => handleChange("specialization", e.target.value), placeholder: t("formSpecializationPlaceholder"), value: specialization || "" }), _jsx(EnhancedInput, { error: getTranslatedError({ errors, key: "experience", t }), id: "experience", info: t("formExperienceInfo"), label: t("formExperienceLabel"), onChange: (e) => handleChange("experience", parseInt(e.target.value) || null), placeholder: t("formExperiencePlaceholder"), type: "number", value: (experience === null || experience === void 0 ? void 0 : experience.toString()) || "" }), _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("formStateProvinceInfo"), label: t("formStateProvinceLabel"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("formStatePlaceholder"), value: stateValue || "" }), _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: "postalCode", t }), id: "postalCode", info: t("formPostalCodeInfo"), label: t("formPostalCodeLabel"), onChange: (e) => handleChange("postalCode", e.target.value), placeholder: t("formPostalCodePlaceholder"), value: postalCode || "" }), _jsx(EnhancedDropzone, { accept: ["image/*"], error: getTranslatedError({ errors, key: "avatar", t }), id: "avatar", info: t("formAvatarInfo"), label: t("formAvatarLabel"), maxFiles: 1, maxSize: 100 * 1024, onChange: (files) => {
49
56
  if (files.length > 0) {
50
57
  handleAvatarUpload === null || handleAvatarUpload === void 0 ? void 0 : handleAvatarUpload(files[0]);
51
58
  }
@@ -15,7 +15,7 @@ export declare const teacherFormValidation: z.ZodObject<{
15
15
  city: z.ZodNullable<z.ZodOptional<z.ZodString>>;
16
16
  country: z.ZodNullable<z.ZodOptional<z.ZodString>>;
17
17
  dateOfBirth: z.ZodNullable<z.ZodOptional<z.ZodString>>;
18
- emergencyPhone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
18
+ emergencyPhone: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null | undefined, string | null | undefined>>;
19
19
  campusId: z.ZodNullable<z.ZodOptional<z.ZodString>>;
20
20
  experience: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
21
21
  firstName: z.ZodString;
@@ -27,7 +27,7 @@ export declare const teacherFormValidation: z.ZodObject<{
27
27
  }>>>>;
28
28
  joiningDate: z.ZodOptional<z.ZodString>;
29
29
  lastName: z.ZodString;
30
- phone: z.ZodOptional<z.ZodNullable<z.ZodString>>;
30
+ phone: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | null | undefined, string | null | undefined>>;
31
31
  postalCode: z.ZodNullable<z.ZodOptional<z.ZodString>>;
32
32
  qualification: z.ZodNullable<z.ZodOptional<z.ZodString>>;
33
33
  specialization: z.ZodNullable<z.ZodOptional<z.ZodString>>;
@@ -4,6 +4,7 @@
4
4
  * Zod validation schemas for teacher form data with i18n-ready error keys.
5
5
  */
6
6
  import { z } from "zod";
7
+ import { toE164Phone } from "../../utils/to-e164-phone";
7
8
  // ============================================================================
8
9
  // VALIDATION KEYS
9
10
  // ============================================================================
@@ -21,7 +22,11 @@ export const teacherFormValidation = z.object({
21
22
  city: z.string().optional().nullable(),
22
23
  country: z.string().optional().nullable(),
23
24
  dateOfBirth: z.string().optional().nullable(),
24
- emergencyPhone: z.string().nullable().optional(),
25
+ emergencyPhone: z
26
+ .string()
27
+ .nullable()
28
+ .optional()
29
+ .transform((val) => { var _a; return (val ? (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val : val); }),
25
30
  campusId: z.string().optional().nullable(),
26
31
  experience: z.number().optional().nullable(),
27
32
  firstName: z.string().min(1, VALIDATION_KEYS.firstName),
@@ -32,7 +37,11 @@ export const teacherFormValidation = z.object({
32
37
  .nullable()),
33
38
  joiningDate: z.string().optional(),
34
39
  lastName: z.string().min(1, VALIDATION_KEYS.lastName),
35
- phone: z.string().nullable().optional(),
40
+ phone: z
41
+ .string()
42
+ .nullable()
43
+ .optional()
44
+ .transform((val) => { var _a; return (val ? (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val : val); }),
36
45
  postalCode: z.string().optional().nullable(),
37
46
  qualification: z.string().optional().nullable(),
38
47
  specialization: z.string().optional().nullable(),
@@ -12,10 +12,11 @@ import { getCachedWorkspaceSync } from "../../workspace/cache";
12
12
  import { blobToWebP } from "webp-converter-browser";
13
13
  import { supabasePublicStorageUrl } from "../../../constants";
14
14
  import { toastNetworkError } from "../../../utils/toast-network-error";
15
- import { formatNumber } from "@react-pakistan/util-functions/general/format-number";
16
15
  import { formatPhoneDisplay } from "@react-pakistan/util-functions/general/format-phone-display";
16
+ import { toE164Phone } from "../../../utils/to-e164-phone";
17
17
  import { useUserContext, USER_ACTION_TYPES, USER_DRAWER } from "../context";
18
18
  export const useUserModule = () => {
19
+ var _a;
19
20
  // ============================================================================
20
21
  // 1.4.1 STATE & CORE HOOKS
21
22
  // ============================================================================
@@ -39,17 +40,20 @@ export const useUserModule = () => {
39
40
  debouncedQuery,
40
41
  workspace === null || workspace === void 0 ? void 0 : workspace.id,
41
42
  ]);
42
- const updateParams = useMemo(() => ({
43
- avatar: state.avatar,
44
- email: (state.email || "").trim(),
45
- enabled: state.enabled,
46
- id: state.id,
47
- name: (state.name || "").trim(),
48
- password: state.password,
49
- phone: formatNumber(state.phone),
50
- userRole: state.userRole,
51
- workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id,
52
- }), [state, workspace === null || workspace === void 0 ? void 0 : workspace.id]);
43
+ const updateParams = useMemo(() => {
44
+ var _a;
45
+ return ({
46
+ avatar: state.avatar,
47
+ email: (state.email || "").trim(),
48
+ enabled: state.enabled,
49
+ id: state.id,
50
+ name: (state.name || "").trim(),
51
+ password: state.password,
52
+ phone: toE164Phone(state.phone, (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.country),
53
+ userRole: state.userRole,
54
+ workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id,
55
+ });
56
+ }, [state, workspace === null || workspace === void 0 ? void 0 : workspace.id, (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.country]);
53
57
  const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
54
58
  const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
55
59
  // ============================================================================
@@ -16,7 +16,7 @@ export declare const userFormValidation: z.ZodObject<{
16
16
  name: z.ZodString;
17
17
  email: z.ZodEmail;
18
18
  password: z.ZodOptional<z.ZodString>;
19
- phone: z.ZodOptional<z.ZodString>;
19
+ phone: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string | undefined, string | undefined>>;
20
20
  avatar: z.ZodOptional<z.ZodString>;
21
21
  enabled: z.ZodOptional<z.ZodBoolean>;
22
22
  userRole: z.ZodEnum<typeof USER_ROLE> & z.ZodType<USER_ROLE.SUPER_ADMIN | USER_ROLE.TEACHER | USER_ROLE.STUDENT | USER_ROLE.PARENT | USER_ROLE.STAFF, USER_ROLE, z.core.$ZodTypeInternals<USER_ROLE.SUPER_ADMIN | USER_ROLE.TEACHER | USER_ROLE.STUDENT | USER_ROLE.PARENT | USER_ROLE.STAFF, USER_ROLE>>;
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { z } from "zod";
7
7
  import { USER_ROLE } from "../../type";
8
+ import { toE164Phone } from "../../utils/to-e164-phone";
8
9
  // ============================================================================
9
10
  // VALIDATION KEYS
10
11
  // ============================================================================
@@ -25,8 +26,7 @@ export const userFormValidation = z.object({
25
26
  phone: z
26
27
  .string()
27
28
  .optional()
28
- .refine((val) => !val ||
29
- /^([+]?[\s0-9]+)?(\d{3}|[(]?[0-9]+[)]?)?([-]?[\s]?[0-9])+$/.test(val), VALIDATION_KEYS.phoneInvalid),
29
+ .transform((val) => { var _a; return (val ? (_a = toE164Phone(val)) !== null && _a !== void 0 ? _a : val : val); }),
30
30
  avatar: z.string().optional(),
31
31
  enabled: z.boolean().optional(),
32
32
  userRole: z
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appcorp/fusion-storybook",
3
- "version": "0.2.93",
3
+ "version": "0.2.95",
4
4
  "scripts": {
5
5
  "build-storybook": "storybook build",
6
6
  "build:next": "next build",