@appcorp/fusion-storybook 0.1.11 → 0.1.14

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.
@@ -195,10 +195,85 @@ export const useAdmissionModule = () => {
195
195
  siblings: context.state.siblings || "",
196
196
  state: context.state.state || "",
197
197
  });
198
- }, [context.state, (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.id]);
198
+ }, [
199
+ context.state.address,
200
+ context.state.admissionNotes,
201
+ context.state.status,
202
+ context.state.bForm,
203
+ context.state.city,
204
+ context.state.classForAdmission,
205
+ context.state.country,
206
+ context.state.discountCode,
207
+ context.state.dob,
208
+ context.state.emergencyContact,
209
+ context.state.enabled,
210
+ context.state.fatherCnic,
211
+ context.state.fatherFirstName,
212
+ context.state.fatherLastName,
213
+ context.state.fatherMobile,
214
+ context.state.fatherOccupation,
215
+ context.state.fatherOrganization,
216
+ context.state.firstName,
217
+ context.state.gender,
218
+ context.state.hafiz,
219
+ context.state.id,
220
+ context.state.lastName,
221
+ context.state.motherCnic,
222
+ context.state.motherFirstName,
223
+ context.state.motherLastName,
224
+ context.state.motherMobile,
225
+ context.state.notes,
226
+ context.state.orphan,
227
+ context.state.postalCode,
228
+ context.state.previousSchool,
229
+ context.state.registrationCode,
230
+ context.state.siblings,
231
+ context.state.state,
232
+ (_b = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _b === void 0 ? void 0 : _b.id,
233
+ ]);
199
234
  const byIdParams = useMemo(() => ({ id: context.state.id }), [context.state.id]);
200
235
  const deleteParams = useMemo(() => ({ id: context.state.id }), [context.state.id]);
201
236
  // ============================================================================
237
+ // UTILITIES
238
+ // ============================================================================
239
+ const showToast = useCallback((message, variant) => {
240
+ generateThemeToast({ description: message, variant });
241
+ }, []);
242
+ const setField = useCallback((key, value) => {
243
+ var _a, _b, _c;
244
+ let formatted = value === null
245
+ ? undefined
246
+ : value;
247
+ if ((key === "bForm" || key === "fatherCnic" || key === "motherCnic") &&
248
+ typeof value === "string" &&
249
+ value.length === 13) {
250
+ formatted = (_a = formatCnic(value)) !== null && _a !== void 0 ? _a : value;
251
+ }
252
+ if ((key === "fatherMobile" || key === "motherMobile") &&
253
+ typeof value === "string" &&
254
+ value.length >= 13) {
255
+ formatted = (_c = (_b = formatPhone(value, "PK")) === null || _b === void 0 ? void 0 : _b.international) !== null && _c !== void 0 ? _c : value;
256
+ }
257
+ context.dispatch({
258
+ type: ADMISSION_ACTION_TYPES.SET_INPUT_FIELD,
259
+ payload: { key, value: formatted || value },
260
+ });
261
+ }, [context]);
262
+ const resetFormAndCloseDrawer = useCallback(() => {
263
+ context.dispatch({
264
+ type: ADMISSION_ACTION_TYPES.SET_ERRORS,
265
+ payload: { errors: {} },
266
+ });
267
+ context.dispatch({
268
+ type: ADMISSION_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
269
+ payload: { disabled: false },
270
+ });
271
+ context.dispatch({
272
+ type: ADMISSION_ACTION_TYPES.SET_DRAWER,
273
+ payload: { drawer: null },
274
+ });
275
+ }, [context]);
276
+ // ============================================================================
202
277
  // API CALLBACKS
203
278
  // ============================================================================
204
279
  const listCallback = ({ data, error }) => {
@@ -317,46 +392,6 @@ export const useAdmissionModule = () => {
317
392
  },
318
393
  });
319
394
  // ============================================================================
320
- // UTILITIES
321
- // ============================================================================
322
- const showToast = useCallback((message, variant) => {
323
- generateThemeToast({ description: message, variant });
324
- }, []);
325
- const resetFormAndCloseDrawer = useCallback(() => {
326
- context.dispatch({
327
- type: ADMISSION_ACTION_TYPES.SET_ERRORS,
328
- payload: { errors: {} },
329
- });
330
- context.dispatch({
331
- type: ADMISSION_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
332
- payload: { disabled: false },
333
- });
334
- context.dispatch({
335
- type: ADMISSION_ACTION_TYPES.SET_DRAWER,
336
- payload: { drawer: null },
337
- });
338
- }, [context]);
339
- const setField = useCallback((key, value) => {
340
- var _a, _b, _c;
341
- let formatted = value === null
342
- ? undefined
343
- : value;
344
- if ((key === "bForm" || key === "fatherCnic" || key === "motherCnic") &&
345
- typeof value === "string" &&
346
- value.length === 13) {
347
- formatted = (_a = formatCnic(value)) !== null && _a !== void 0 ? _a : value;
348
- }
349
- if ((key === "fatherMobile" || key === "motherMobile") &&
350
- typeof value === "string" &&
351
- value.length >= 13) {
352
- formatted = (_c = (_b = formatPhone(value, "PK")) === null || _b === void 0 ? void 0 : _b.international) !== null && _c !== void 0 ? _c : value;
353
- }
354
- context.dispatch({
355
- type: ADMISSION_ACTION_TYPES.SET_INPUT_FIELD,
356
- payload: { key, value: formatted || value },
357
- });
358
- }, [context]);
359
- // ============================================================================
360
395
  // HANDLERS
361
396
  // ============================================================================
362
397
  const handleChange = useCallback((field, value) => {
@@ -724,7 +759,7 @@ export const useAdmissionModule = () => {
724
759
  showToast(t("messagesFetchFailed"), TOAST_VARIANT.ERROR);
725
760
  }
726
761
  })();
727
- }, [listParams, workspace === null || workspace === void 0 ? void 0 : workspace.id, t, showToast, context]);
762
+ }, [listParams, workspace === null || workspace === void 0 ? void 0 : workspace.id, t, showToast, context.dispatch]);
728
763
  // ============================================================================
729
764
  // RETURN
730
765
  // ============================================================================
@@ -82,37 +82,56 @@ const createAdmissionConfig = ({ cancelLabel, dispatch, drawer, drawerTitle, lab
82
82
  // ============================================================================
83
83
  // STABLE PAGE COMPONENT (created once, outside render)
84
84
  // ============================================================================
85
- const GenericAdmissionPage = createGenericModulePage({
86
- cancelLabel: "",
87
- drawerTitle: "",
88
- filterContent: _jsx(AdmissionFilter, {}),
89
- formContent: _jsx(AdmissionForm, {}),
90
- moduleName: "admission",
91
- moreActionsContent: _jsx(AdmissionMoreActions, {}),
92
- onClearFilters: () => { },
93
- saveLabel: "",
94
- searchPlaceholder: "",
95
- size: "small",
96
- tableColumns: [],
97
- tableDescription: "",
98
- tableTitle: "",
99
- viewContent: _jsx(AdmissionView, {}),
100
- });
85
+ const GenericAdmissionPage = createGenericModulePage();
101
86
  // ============================================================================
102
87
  // INNER PAGE (requires AdmissionProvider context)
103
88
  // ============================================================================
104
89
  const AdmissionPageInner = (props) => {
105
90
  const context = useAdmissionModule();
106
- // Memoize config creation
107
- const admissionConfig = useMemo(() => createAdmissionConfig(Object.assign({ dispatch: context.dispatch, drawer: context.state.drawer }, props)), [context.dispatch, context.state.drawer, props]);
108
- // Memoize permission check to avoid recalculation on every render
109
- const hasPermission = useMemo(() => resolveRbacPermissions({
91
+ // Memoize config creation - destructure props to avoid object reference changes
92
+ const admissionConfig = useMemo(() => createAdmissionConfig({
93
+ dispatch: context.dispatch,
94
+ drawer: context.state.drawer,
95
+ cancelLabel: props.cancelLabel,
96
+ drawerTitle: props.drawerTitle,
97
+ labelActions: props.labelActions,
98
+ labelClass: props.labelClass,
99
+ labelEnabled: props.labelEnabled,
100
+ labelFirstName: props.labelFirstName,
101
+ labelId: props.labelId,
102
+ labelLastName: props.labelLastName,
103
+ labelRegistrationCode: props.labelRegistrationCode,
104
+ labelStatus: props.labelStatus,
105
+ saveLabel: props.saveLabel,
106
+ searchPlaceholder: props.searchPlaceholder,
107
+ tableDescription: props.tableDescription,
108
+ tableTitle: props.tableTitle,
109
+ }), [
110
+ context.dispatch,
111
+ context.state.drawer,
112
+ props.cancelLabel,
113
+ props.drawerTitle,
114
+ props.labelActions,
115
+ props.labelClass,
116
+ props.labelEnabled,
117
+ props.labelFirstName,
118
+ props.labelId,
119
+ props.labelLastName,
120
+ props.labelRegistrationCode,
121
+ props.labelStatus,
122
+ props.saveLabel,
123
+ props.searchPlaceholder,
124
+ props.tableDescription,
125
+ props.tableTitle,
126
+ ]);
127
+ const hasPermission = resolveRbacPermissions({
110
128
  userRole: props.userRole,
111
129
  moduleName: "Admission",
112
- }), [props.userRole]);
130
+ });
113
131
  if (!hasPermission) {
114
132
  return _jsx(RbacNoAccess, { moduleName: "Admission" });
115
133
  }
116
- return (_jsx("div", { className: "p-4", children: _jsx(GenericAdmissionPage, { config: admissionConfig, overrideConfig: admissionConfig, context: context, tableBodyCols: tableBodyCols }) }));
134
+ console.log("Rendering AdmissionPageInner with config:", admissionConfig);
135
+ return (_jsx("div", { className: "p-4", children: _jsx(GenericAdmissionPage, { overrideConfig: admissionConfig, context: context, tableBodyCols: tableBodyCols }) }));
117
136
  };
118
137
  export const AdmissionPage = (props) => (_jsx(AdmissionProvider, { children: _jsx(AdmissionPageInner, Object.assign({}, props)) }));
@@ -84,22 +84,7 @@ const createDiscountCodeConfig = (t, drawer, dispatch) => {
84
84
  // ============================================================================
85
85
  // STABLE PAGE COMPONENT (created once, outside render)
86
86
  // ============================================================================
87
- const GenericDiscountCodePage = createGenericModulePage({
88
- moduleName: "discountCode",
89
- tableColumns: [],
90
- cancelLabel: "",
91
- drawerTitle: "",
92
- filterContent: _jsx(DiscountCodeFilter, {}),
93
- formContent: _jsx(DiscountCodeForm, {}),
94
- moreActionsContent: _jsx(DiscountCodeMoreActions, {}),
95
- saveLabel: "",
96
- searchPlaceholder: "",
97
- tableDescription: "",
98
- tableTitle: "",
99
- viewContent: _jsx(DiscountCodeView, {}),
100
- size: "small",
101
- onClearFilters: () => { },
102
- });
87
+ const GenericDiscountCodePage = createGenericModulePage();
103
88
  // ============================================================================
104
89
  // INNER PAGE (requires DiscountCodeProvider context)
105
90
  // ============================================================================
@@ -115,6 +100,6 @@ const DiscountCodePageInner = ({ userRole }) => {
115
100
  if (!hasPermission) {
116
101
  return _jsx(RbacNoAccess, { moduleName: "DiscountCode" });
117
102
  }
118
- return (_jsx("div", { className: "p-4", children: _jsx(GenericDiscountCodePage, { config: discountCodeConfig, context: context, tableBodyCols: tableBodyCols }) }));
103
+ return (_jsx("div", { className: "p-4", children: _jsx(GenericDiscountCodePage, { overrideConfig: discountCodeConfig, context: context, tableBodyCols: tableBodyCols }) }));
119
104
  };
120
105
  export const DiscountCodePage = ({ userRole }) => (_jsx(DiscountCodeProvider, { children: _jsx(DiscountCodePageInner, { userRole: userRole }) }));
@@ -83,22 +83,7 @@ const createFamilyConfig = (t, dispatch) => {
83
83
  // ============================================================================
84
84
  // STABLE PAGE COMPONENT (created once, outside render)
85
85
  // ============================================================================
86
- const GenericFamilyPage = createGenericModulePage({
87
- moduleName: "family",
88
- tableColumns: [],
89
- cancelLabel: "",
90
- drawerTitle: "",
91
- filterContent: _jsx(FamilyFilter, {}),
92
- formContent: _jsx(FamilyForm, {}),
93
- moreActionsContent: _jsx(FamilyMoreActions, {}),
94
- saveLabel: "",
95
- searchPlaceholder: "",
96
- tableDescription: "",
97
- tableTitle: "",
98
- viewContent: _jsx(FamilyView, {}),
99
- size: "small",
100
- onClearFilters: () => { },
101
- });
86
+ const GenericFamilyPage = createGenericModulePage();
102
87
  // ============================================================================
103
88
  // INNER PAGE (requires FamilyProvider context)
104
89
  // ============================================================================
@@ -115,6 +100,6 @@ const FamilyPageInner = ({ userRole }) => {
115
100
  if (!hasPermission) {
116
101
  return _jsx(RbacNoAccess, { moduleName: "People Management" });
117
102
  }
118
- return (_jsx("div", { className: "p-4", children: _jsx(GenericFamilyPage, { config: familyConfig, context: context, tableBodyCols: tableBodyCols }) }));
103
+ return (_jsx("div", { className: "p-4", children: _jsx(GenericFamilyPage, { overrideConfig: familyConfig, context: context, tableBodyCols: tableBodyCols }) }));
119
104
  };
120
105
  export const FamilyPage = ({ userRole }) => (_jsx(FamilyProvider, { children: _jsx(FamilyPageInner, { userRole: userRole }) }));
@@ -85,22 +85,7 @@ const createFamilyMemberConfig = (t, drawer, dispatch) => {
85
85
  // ============================================================================
86
86
  // STABLE PAGE COMPONENT (created once, outside render)
87
87
  // ============================================================================
88
- const GenericFamilyMemberPage = createGenericModulePage({
89
- moduleName: "familyMember",
90
- tableColumns: [],
91
- cancelLabel: "",
92
- drawerTitle: "",
93
- filterContent: _jsx(FamilyMemberFilter, {}),
94
- formContent: _jsx(FamilyMemberForm, {}),
95
- moreActionsContent: _jsx(FamilyMemberMoreActions, {}),
96
- saveLabel: "",
97
- searchPlaceholder: "",
98
- tableDescription: "",
99
- tableTitle: "",
100
- viewContent: _jsx(FamilyMemberView, {}),
101
- size: "small",
102
- onClearFilters: () => { },
103
- });
88
+ const GenericFamilyMemberPage = createGenericModulePage();
104
89
  // ============================================================================
105
90
  // INNER PAGE (requires FamilyMemberProvider context)
106
91
  // ============================================================================
@@ -117,6 +102,6 @@ const FamilyMemberPageInner = ({ userRole }) => {
117
102
  if (!hasPermission) {
118
103
  return _jsx(RbacNoAccess, { moduleName: "People Management" });
119
104
  }
120
- return (_jsx("div", { className: "p-4", children: _jsx(GenericFamilyMemberPage, { config: familyMemberConfig, context: context, tableBodyCols: tableBodyCols }) }));
105
+ return (_jsx("div", { className: "p-4", children: _jsx(GenericFamilyMemberPage, { overrideConfig: familyMemberConfig, context: context, tableBodyCols: tableBodyCols }) }));
121
106
  };
122
107
  export const FamilyMemberPage = ({ userRole }) => (_jsx(FamilyMemberProvider, { children: _jsx(FamilyMemberPageInner, { userRole: userRole }) }));
@@ -33,19 +33,17 @@ const tableBodyCols = [
33
33
  { componentType: COMPONENT_TYPE.ACTIONS },
34
34
  ];
35
35
  // ============================================================================
36
- // GENERIC PAGE COMPONENT
36
+ // COMPONENT FACTORY (creates JSX elements when config is created, not during render)
37
37
  // ============================================================================
38
- const StudentProfilePageInner = () => {
39
- // const { user } = useAuthStateContext();
40
- // const userRole = user?.user_metadata?.role as USER_ROLE;
41
- const userRole = USER_ROLE.SCHOOL_ADMIN; // Default for storybook
42
- const t = useTranslations("studentProfile");
43
- const context = useStudentProfileModule();
44
- // Config only changes when the locale changes or the drawer changes (size).
45
- // Keeping this stable is critical: createGenericModulePage closes over config
46
- // and produces a new React component type. If that type changes during render,
47
- // React unmounts → remounts → effects fire → dispatch → infinite loop.
48
- const studentProfileConfig = useMemo(() => ({
38
+ const createComponentInstances = () => ({
39
+ filter: _jsx(StudentProfileFilter, {}),
40
+ form: _jsx(StudentProfileForm, {}),
41
+ moreActions: _jsx(StudentProfileMoreActions, {}),
42
+ view: _jsx(StudentProfileView, {}),
43
+ });
44
+ const createStudentProfileConfig = ({ drawer, dispatch, t, }) => {
45
+ const components = createComponentInstances();
46
+ return {
49
47
  moduleName: "studentProfile",
50
48
  tableColumns: [
51
49
  { label: t("id"), width: "5%" },
@@ -58,29 +56,45 @@ const StudentProfilePageInner = () => {
58
56
  ],
59
57
  cancelLabel: t("cancel"),
60
58
  drawerTitle: t("studentProfile"),
61
- filterContent: _jsx(StudentProfileFilter, {}),
62
- formContent: _jsx(StudentProfileForm, {}),
63
- moreActionsContent: _jsx(StudentProfileMoreActions, {}),
59
+ filterContent: components.filter,
60
+ formContent: components.form,
61
+ moreActionsContent: components.moreActions,
64
62
  saveLabel: t("save"),
65
63
  searchPlaceholder: t("searchStudentProfiles"),
66
64
  tableDescription: t("manageStudentProfilesAndTheirInformation"),
67
65
  tableTitle: t("studentProfile"),
68
- viewContent: _jsx(StudentProfileView, {}),
69
- size: context.state.drawer === STUDENT_PROFILE_DRAWER.FORM_DRAWER
70
- ? "full"
71
- : "small",
66
+ viewContent: components.view,
67
+ size: drawer === STUDENT_PROFILE_DRAWER.FORM_DRAWER ? "full" : "small",
72
68
  onClearFilters: () => {
73
- context.dispatch({ type: STUDENT_PROFILE_ACTION_TYPES.RESET_FORM });
69
+ dispatch({ type: STUDENT_PROFILE_ACTION_TYPES.RESET_FORM });
74
70
  },
75
- }), [t, context.state.drawer]);
76
- const GenericStudentProfilePage = useMemo(() => createGenericModulePage(studentProfileConfig), [studentProfileConfig]);
77
- const hasPermission = resolveRbacPermissions({
71
+ };
72
+ };
73
+ // ============================================================================
74
+ // STABLE PAGE COMPONENT (created once, outside render)
75
+ // ============================================================================
76
+ const GenericStudentProfilePage = createGenericModulePage();
77
+ // ============================================================================
78
+ // INNER PAGE (requires StudentProfileProvider context)
79
+ // ============================================================================
80
+ const StudentProfilePageInner = () => {
81
+ const userRole = USER_ROLE.SCHOOL_ADMIN; // Default for storybook
82
+ const t = useTranslations("studentProfile");
83
+ const context = useStudentProfileModule();
84
+ // Memoize config creation
85
+ const studentProfileConfig = useMemo(() => createStudentProfileConfig({
86
+ dispatch: context.dispatch,
87
+ drawer: context.state.drawer,
88
+ t,
89
+ }), [context.dispatch, context.state.drawer, t]);
90
+ // Memoize permission check to avoid recalculation on every render
91
+ const hasPermission = useMemo(() => resolveRbacPermissions({
78
92
  userRole,
79
93
  moduleName: "People Management",
80
- });
94
+ }), [userRole]);
81
95
  if (!hasPermission) {
82
96
  return _jsx(RbacNoAccess, { moduleName: "People Management" });
83
97
  }
84
- return (_jsx("div", { className: "p-4", children: _jsx(GenericStudentProfilePage, { config: studentProfileConfig, context: context, tableBodyCols: tableBodyCols }) }));
98
+ return (_jsx("div", { className: "p-4", children: _jsx(GenericStudentProfilePage, { overrideConfig: studentProfileConfig, context: context, tableBodyCols: tableBodyCols }) }));
85
99
  };
86
100
  export const StudentProfilePage = () => (_jsx(StudentProfileProvider, { children: _jsx(StudentProfilePageInner, {}) }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appcorp/fusion-storybook",
3
- "version": "0.1.11",
3
+ "version": "0.1.14",
4
4
  "scripts": {
5
5
  "build-storybook": "storybook build",
6
6
  "build:next": "next build",
@@ -56,7 +56,7 @@
56
56
  "@radix-ui/react-separator": "^1.1.8",
57
57
  "@radix-ui/react-slot": "^1.2.4",
58
58
  "@radix-ui/react-toast": "^1.2.15",
59
- "@react-pakistan/util-functions": "^1.25.64",
59
+ "@react-pakistan/util-functions": "^1.25.66",
60
60
  "@storybook/addon-a11y": "^10.3.4",
61
61
  "@storybook/addon-docs": "^10.3.4",
62
62
  "@storybook/addon-onboarding": "^10.3.4",