@appcorp/fusion-storybook 0.1.21 → 0.1.23

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 (62) hide show
  1. package/base-modules/teacher/cache.d.ts +14 -0
  2. package/base-modules/teacher/cache.js +31 -0
  3. package/base-modules/teacher/constants.d.ts +23 -0
  4. package/base-modules/teacher/constants.js +27 -0
  5. package/base-modules/teacher/context.d.ts +245 -0
  6. package/base-modules/teacher/context.js +461 -0
  7. package/base-modules/teacher/filter.d.ts +1 -0
  8. package/base-modules/teacher/filter.js +29 -0
  9. package/base-modules/teacher/form.d.ts +1 -0
  10. package/base-modules/teacher/form.js +30 -0
  11. package/base-modules/teacher/more-actions.d.ts +1 -0
  12. package/base-modules/teacher/more-actions.js +50 -0
  13. package/base-modules/teacher/page.d.ts +32 -0
  14. package/base-modules/teacher/page.js +141 -0
  15. package/base-modules/teacher/validate.d.ts +26 -0
  16. package/base-modules/teacher/validate.js +37 -0
  17. package/base-modules/teacher/view.d.ts +1 -0
  18. package/base-modules/teacher/view.js +27 -0
  19. package/base-modules/user/cache.d.ts +14 -0
  20. package/base-modules/user/cache.js +31 -0
  21. package/base-modules/user/constants.d.ts +9 -0
  22. package/base-modules/user/constants.js +19 -0
  23. package/base-modules/user/context.d.ts +218 -0
  24. package/base-modules/user/context.js +585 -0
  25. package/base-modules/user/drawer.d.ts +1 -0
  26. package/base-modules/user/drawer.js +25 -0
  27. package/base-modules/user/filter.d.ts +1 -0
  28. package/base-modules/user/filter.js +21 -0
  29. package/base-modules/user/form.d.ts +1 -0
  30. package/base-modules/user/form.js +28 -0
  31. package/base-modules/user/more-actions.d.ts +1 -0
  32. package/base-modules/user/more-actions.js +48 -0
  33. package/base-modules/user/page.d.ts +30 -0
  34. package/base-modules/user/page.js +120 -0
  35. package/base-modules/user/validate.d.ts +16 -0
  36. package/base-modules/user/validate.js +29 -0
  37. package/base-modules/user/view.d.ts +1 -0
  38. package/base-modules/user/view.js +24 -0
  39. package/base-modules/workspace-user/cache.d.ts +14 -0
  40. package/base-modules/workspace-user/cache.js +31 -0
  41. package/base-modules/workspace-user/constants.d.ts +21 -0
  42. package/base-modules/workspace-user/constants.js +27 -0
  43. package/base-modules/workspace-user/context.d.ts +155 -0
  44. package/base-modules/workspace-user/context.js +382 -0
  45. package/base-modules/workspace-user/filter.d.ts +1 -0
  46. package/base-modules/workspace-user/filter.js +23 -0
  47. package/base-modules/workspace-user/form.d.ts +1 -0
  48. package/base-modules/workspace-user/form.js +12 -0
  49. package/base-modules/workspace-user/more-actions.d.ts +1 -0
  50. package/base-modules/workspace-user/more-actions.js +51 -0
  51. package/base-modules/workspace-user/page.d.ts +28 -0
  52. package/base-modules/workspace-user/page.js +106 -0
  53. package/base-modules/workspace-user/validate.d.ts +12 -0
  54. package/base-modules/workspace-user/validate.js +15 -0
  55. package/base-modules/workspace-user/view.d.ts +1 -0
  56. package/base-modules/workspace-user/view.js +20 -0
  57. package/components/timeline.d.ts +11 -0
  58. package/components/timeline.js +4 -0
  59. package/package.json +4 -2
  60. package/tsconfig.build.tsbuildinfo +1 -1
  61. package/utils/toast-network-error.d.ts +1 -0
  62. package/utils/toast-network-error.js +7 -0
@@ -0,0 +1,141 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * Teacher Page Component
5
+ *
6
+ * Thin wrapper around GenericModulePage. All handlers, header actions, and row
7
+ * actions live in context.tsx — this file only owns:
8
+ * - tableBodyCols (static, module-level constant)
9
+ * - teacherConfig (memoised on locale change only; size fixed per drawer so
10
+ * the component type produced by createGenericModulePage never changes at
11
+ * runtime, preventing the infinite-remount re-render loop)
12
+ * - permission guard
13
+ */
14
+ import { useMemo } from "react";
15
+ import { COMPONENT_TYPE } from "@appcorp/shadcn/components/enhanced-table";
16
+ import { createGenericModulePage, } from "@react-pakistan/util-functions/factory/generic-component-factory";
17
+ import { useTeacherModule, TeacherProvider, TEACHER_DRAWER, TEACHER_ACTION_TYPES, } from "./context";
18
+ import { TeacherFilter } from "./filter";
19
+ import { TeacherForm } from "./form";
20
+ import { TeacherMoreActions } from "./more-actions";
21
+ import { TeacherView } from "./view";
22
+ import { resolveRbacPermissions } from "../../utils/resolve-rbac-permissions";
23
+ import { RbacNoAccess } from "../../components/rbac-no-access";
24
+ // ============================================================================
25
+ // TABLE COLUMN CONFIGURATION (static — no runtime deps)
26
+ // ============================================================================
27
+ const tableBodyCols = [
28
+ { componentType: COMPONENT_TYPE.ID, key: "id" },
29
+ { componentType: COMPONENT_TYPE.TEXT, key: "teacherCode" },
30
+ {
31
+ componentType: COMPONENT_TYPE.TEXT,
32
+ key: "name",
33
+ textFormatter: (_, row) => {
34
+ var _a;
35
+ return ((_a = row === null || row === void 0 ? void 0 : row.user) === null || _a === void 0 ? void 0 : _a.name) || "N/A";
36
+ },
37
+ },
38
+ {
39
+ componentType: COMPONENT_TYPE.TEXT,
40
+ key: "email",
41
+ textFormatter: (_, row) => {
42
+ var _a;
43
+ return ((_a = row === null || row === void 0 ? void 0 : row.user) === null || _a === void 0 ? void 0 : _a.email) || "N/A";
44
+ },
45
+ },
46
+ { componentType: COMPONENT_TYPE.TEXT, key: "phone" },
47
+ { componentType: COMPONENT_TYPE.TEXT, key: "specialization" },
48
+ { componentType: COMPONENT_TYPE.BOOLEAN, key: "enabled" },
49
+ { componentType: COMPONENT_TYPE.ACTIONS },
50
+ ];
51
+ // ============================================================================
52
+ // COMPONENT FACTORY (creates JSX elements when config is created, not during render)
53
+ // ============================================================================
54
+ const createComponentInstances = () => ({
55
+ filter: _jsx(TeacherFilter, {}),
56
+ form: _jsx(TeacherForm, {}),
57
+ moreActions: _jsx(TeacherMoreActions, {}),
58
+ view: _jsx(TeacherView, {}),
59
+ });
60
+ const createTeacherConfig = ({ cancelLabel, dispatch, drawer, drawerTitle, labelActions, labelEmail, labelEnabled, labelId, labelName, labelPhone, labelSpecialization, labelTeacherCode, saveLabel, searchPlaceholder, tableDescription, tableTitle, }) => {
61
+ const components = createComponentInstances();
62
+ return {
63
+ moduleName: "teacher",
64
+ tableColumns: [
65
+ { label: labelId, width: "5%" },
66
+ { label: labelTeacherCode, width: "12%" },
67
+ { label: labelName, width: "18%" },
68
+ { label: labelEmail, width: "18%" },
69
+ { label: labelPhone, width: "14%" },
70
+ { label: labelSpecialization, width: "18%" },
71
+ { label: labelEnabled, width: "8%" },
72
+ { label: labelActions, width: "7%" },
73
+ ],
74
+ cancelLabel,
75
+ drawerTitle,
76
+ filterContent: components.filter,
77
+ formContent: components.form,
78
+ moreActionsContent: components.moreActions,
79
+ saveLabel,
80
+ searchPlaceholder,
81
+ tableDescription,
82
+ tableTitle,
83
+ viewContent: components.view,
84
+ size: drawer === TEACHER_DRAWER.FORM_DRAWER ? "full" : "small",
85
+ onClearFilters: () => {
86
+ dispatch({ type: TEACHER_ACTION_TYPES.RESET_FORM });
87
+ },
88
+ };
89
+ };
90
+ // ============================================================================
91
+ // STABLE PAGE COMPONENT (created once, outside render)
92
+ // ============================================================================
93
+ const GenericTeacherPage = createGenericModulePage();
94
+ const TeacherPageInner = (props) => {
95
+ const context = useTeacherModule();
96
+ // Memoize config creation - destructure props to avoid object reference changes
97
+ const teacherConfig = useMemo(() => createTeacherConfig({
98
+ dispatch: context.dispatch,
99
+ drawer: context.state.drawer,
100
+ cancelLabel: props.cancelLabel,
101
+ drawerTitle: props.drawerTitle,
102
+ labelActions: props.labelActions,
103
+ labelEmail: props.labelEmail,
104
+ labelEnabled: props.labelEnabled,
105
+ labelId: props.labelId,
106
+ labelName: props.labelName,
107
+ labelPhone: props.labelPhone,
108
+ labelSpecialization: props.labelSpecialization,
109
+ labelTeacherCode: props.labelTeacherCode,
110
+ saveLabel: props.saveLabel,
111
+ searchPlaceholder: props.searchPlaceholder,
112
+ tableDescription: props.tableDescription,
113
+ tableTitle: props.tableTitle,
114
+ }), [
115
+ context.dispatch,
116
+ context.state.drawer,
117
+ props.cancelLabel,
118
+ props.drawerTitle,
119
+ props.labelActions,
120
+ props.labelEmail,
121
+ props.labelEnabled,
122
+ props.labelId,
123
+ props.labelName,
124
+ props.labelPhone,
125
+ props.labelSpecialization,
126
+ props.labelTeacherCode,
127
+ props.saveLabel,
128
+ props.searchPlaceholder,
129
+ props.tableDescription,
130
+ props.tableTitle,
131
+ ]);
132
+ const hasPermission = resolveRbacPermissions({
133
+ userRole: props.userRole,
134
+ moduleName: "People Management",
135
+ });
136
+ if (!hasPermission) {
137
+ return _jsx(RbacNoAccess, { moduleName: "People Management" });
138
+ }
139
+ return (_jsx("div", { className: "p-4", children: _jsx(GenericTeacherPage, { overrideConfig: teacherConfig, context: context, tableBodyCols: tableBodyCols }) }));
140
+ };
141
+ export const TeacherPage = (props) => (_jsx(TeacherProvider, { children: _jsx(TeacherPageInner, Object.assign({}, props)) }));
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Teacher Validation Schema
3
+ *
4
+ * Zod validation schemas for teacher form data.
5
+ */
6
+ import { z } from "zod";
7
+ export declare const teacherFormValidation: z.ZodObject<{
8
+ address: z.ZodOptional<z.ZodString>;
9
+ avatar: z.ZodOptional<z.ZodString>;
10
+ bio: z.ZodOptional<z.ZodString>;
11
+ city: z.ZodOptional<z.ZodString>;
12
+ country: z.ZodOptional<z.ZodString>;
13
+ dateOfBirth: z.ZodNullable<z.ZodOptional<z.ZodString>>;
14
+ emergencyPhone: z.ZodOptional<z.ZodString>;
15
+ experience: z.ZodNullable<z.ZodOptional<z.ZodNumber>>;
16
+ firstName: z.ZodString;
17
+ gender: z.ZodNullable<z.ZodOptional<z.ZodString>>;
18
+ joiningDate: z.ZodString;
19
+ lastName: z.ZodString;
20
+ phone: z.ZodOptional<z.ZodString>;
21
+ postalCode: z.ZodOptional<z.ZodString>;
22
+ qualification: z.ZodOptional<z.ZodString>;
23
+ specialization: z.ZodOptional<z.ZodString>;
24
+ state: z.ZodOptional<z.ZodString>;
25
+ teacherCode: z.ZodString;
26
+ }, z.core.$strip>;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Teacher Validation Schema
3
+ *
4
+ * Zod validation schemas for teacher form data.
5
+ */
6
+ import { z } from "zod";
7
+ // ============================================================================
8
+ // VALIDATION SCHEMA
9
+ // ============================================================================
10
+ export const teacherFormValidation = z.object({
11
+ address: z.string().optional(),
12
+ avatar: z.string().optional(),
13
+ bio: z.string().optional(),
14
+ city: z.string().optional(),
15
+ country: z.string().optional(),
16
+ dateOfBirth: z.string().optional().nullable(),
17
+ emergencyPhone: z
18
+ .string()
19
+ .optional()
20
+ .refine((val) => !val ||
21
+ /^([+]?[\s0-9]+)?(\d{3}|[(]?[0-9]+[)]?)?([-]?[\s]?[0-9])+$/.test(val), "Invalid phone number format"),
22
+ experience: z.number().optional().nullable(),
23
+ firstName: z.string().min(1, "First name is required"),
24
+ gender: z.string().optional().nullable(),
25
+ joiningDate: z.string(),
26
+ lastName: z.string().min(1, "Last name is required"),
27
+ phone: z
28
+ .string()
29
+ .optional()
30
+ .refine((val) => !val ||
31
+ /^([+]?[\s0-9]+)?(\d{3}|[(]?[0-9]+[)]?)?([-]?[\s]?[0-9])+$/.test(val), "Invalid phone number format"),
32
+ postalCode: z.string().optional(),
33
+ qualification: z.string().optional(),
34
+ specialization: z.string().optional(),
35
+ state: z.string().optional(),
36
+ teacherCode: z.string().min(1, "Teacher code is required"),
37
+ });
@@ -0,0 +1 @@
1
+ export declare const TeacherView: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,27 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@appcorp/shadcn/components/ui/card";
4
+ import { Badge } from "@appcorp/shadcn/components/ui/badge";
5
+ import { Separator } from "@appcorp/shadcn/components/ui/separator";
6
+ import { Avatar, AvatarFallback, AvatarImage, } from "@appcorp/shadcn/components/ui/avatar";
7
+ import { User, Phone, MapPin, Calendar, GraduationCap, CheckCircle2, XCircle, Briefcase, } from "lucide-react";
8
+ import { useTranslations } from "next-intl";
9
+ import { formatValue } from "../../utils/format-value";
10
+ import { formatDate, DATE_FORMATS } from "@react-pakistan/util-functions";
11
+ import { useTeacherModule } from "./context";
12
+ export const TeacherView = () => {
13
+ const t = useTranslations("teacher");
14
+ const context = useTeacherModule();
15
+ const { address, avatar, bio, city, country, dateOfBirth, emergencyPhone, enabled, experience, firstName, gender, joiningDate, lastName, phone, postalCode, qualification, specialization, teacherCode, } = context.state;
16
+ const stateValue = context.state.state;
17
+ const fullName = `${firstName} ${lastName}`;
18
+ const formatDateValue = (date) => date ? formatDate(String(date), DATE_FORMATS.LOCALE_DATE) : "\u2014";
19
+ const getInitials = () => {
20
+ const first = (firstName === null || firstName === void 0 ? void 0 : firstName.charAt(0)) || "";
21
+ const last = (lastName === null || lastName === void 0 ? void 0 : lastName.charAt(0)) || "";
22
+ return (first + last).toUpperCase() || "T";
23
+ };
24
+ return (_jsxs("div", { className: "space-y-4", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(User, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("basicInformation") })] }), _jsx(CardDescription, { children: t("teachersPersonalDetails") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("profilePicture") }), _jsxs(Avatar, { className: "h-20 w-20", children: [_jsx(AvatarImage, { src: avatar || undefined, alt: fullName }), _jsx(AvatarFallback, { className: "text-lg", children: getInitials() })] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("teacherCode") }), _jsx("p", { className: "font-mono text-base", children: formatValue(teacherCode) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("name") }), _jsx("p", { className: "text-base", children: fullName })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("gender") }), _jsx("p", { className: "text-base", children: formatValue(gender) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Calendar, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("dateOfBirth") })] }), _jsx("p", { className: "text-base", children: formatDateValue(dateOfBirth) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("status") }), _jsx("div", { className: "flex items-center gap-2", children: enabled ? (_jsxs(_Fragment, { children: [_jsx(CheckCircle2, { className: "h-4 w-4 text-green-600" }), _jsx(Badge, { variant: "default", children: t("active") })] })) : (_jsxs(_Fragment, { children: [_jsx(XCircle, { className: "h-4 w-4 text-red-600" }), _jsx(Badge, { variant: "destructive", children: t("inactive") })] })) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("contactInformation") })] }), _jsx(CardDescription, { children: t("howToReachTheTeacher") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("phone") })] }), _jsx("p", { className: "text-base", children: formatValue(phone) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("emergencyPhone") })] }), _jsx("p", { className: "text-base", children: formatValue(emergencyPhone) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(GraduationCap, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("professionalInformation") })] }), _jsx(CardDescription, { children: t("teachingCredentialsAndExperience") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("qualification") }), _jsx("p", { className: "text-base", children: formatValue(qualification) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("specialization") }), _jsx("p", { className: "text-base", children: formatValue(specialization) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Briefcase, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("experience") })] }), _jsx("p", { className: "text-base", children: experience
25
+ ? t("experienceYears", { years: experience })
26
+ : "\u2014" })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Calendar, { className: "text-muted-foreground h-4 w-4" }), _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("joiningDate") })] }), _jsx("p", { className: "text-base", children: formatDateValue(joiningDate) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(MapPin, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("addressInformation") })] }), _jsx(CardDescription, { children: t("teachersResidentialAddress") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("address") }), _jsx("p", { className: "text-base", children: formatValue(address) })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("city") }), _jsx("p", { className: "text-base", children: formatValue(city) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("stateProvince") }), _jsx("p", { className: "text-base", children: formatValue(stateValue) })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("country") }), _jsx("p", { className: "text-base", children: formatValue(country) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("postalCode") }), _jsx("p", { className: "text-base", children: formatValue(postalCode) })] })] })] }) })] }), bio && (_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-lg", children: t("biography") }), _jsx(CardDescription, { children: t("aboutTheTeacher") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsx("p", { className: "text-base", children: bio }) })] }))] }));
27
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * User Module Cache Utilities
3
+ *
4
+ * Provides localStorage-based caching for users using generic cache system.
5
+ */
6
+ import { UserBE } from "../../type";
7
+ export declare const getCachedUsersSync: () => import("@react-pakistan/util-functions").ListResponse<UserBE>;
8
+ export declare const getCachedUsers: ({ params, }: {
9
+ params: Record<string, unknown>;
10
+ }) => Promise<import("@react-pakistan/util-functions").ListResponse<UserBE>>;
11
+ export declare const getCachedUserById: (userId: string) => UserBE | null;
12
+ export declare const invalidateUsersCache: () => void;
13
+ export declare const preloadUsers: () => Promise<import("@react-pakistan/util-functions").ListResponse<UserBE>>;
14
+ export declare const isUsersCacheStale: () => boolean;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * User Module Cache Utilities
3
+ *
4
+ * Provides localStorage-based caching for users using generic cache system.
5
+ */
6
+ import { LS_KEYS } from "../../constants";
7
+ import { USER_API_ROUTES } from "./constants";
8
+ import { getCachedData, getCachedDataSync, getCachedItemById, invalidateCache, isCacheStale, preloadCache, } from "@react-pakistan/util-functions";
9
+ // ============================================================================
10
+ // CACHE CONFIGURATION
11
+ // ============================================================================
12
+ const USER_CACHE_CONFIG = {
13
+ cacheKey: LS_KEYS.USERS,
14
+ apiUrl: USER_API_ROUTES.LIST,
15
+ };
16
+ // ============================================================================
17
+ // USER-SPECIFIC CACHE FUNCTIONS
18
+ // ============================================================================
19
+ export const getCachedUsersSync = () => getCachedDataSync(LS_KEYS.USERS);
20
+ export const getCachedUsers = ({ params, }) => getCachedData({
21
+ config: USER_CACHE_CONFIG,
22
+ params,
23
+ headers: {
24
+ "Content-Type": "application/json",
25
+ "x-api-token": process.env.NEXT_PUBLIC_API_KEY,
26
+ },
27
+ });
28
+ export const getCachedUserById = (userId) => getCachedItemById(LS_KEYS.USERS, userId);
29
+ export const invalidateUsersCache = () => invalidateCache(LS_KEYS.USERS);
30
+ export const preloadUsers = () => preloadCache(USER_CACHE_CONFIG);
31
+ export const isUsersCacheStale = () => isCacheStale(LS_KEYS.USERS);
@@ -0,0 +1,9 @@
1
+ /**
2
+ * User Constants
3
+ *
4
+ * Organization:
5
+ * - Page Configuration
6
+ * - API Routes
7
+ */
8
+ export declare const pageLimit: number;
9
+ export declare const USER_API_ROUTES: Record<string, string>;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * User Constants
3
+ *
4
+ * Organization:
5
+ * - Page Configuration
6
+ * - API Routes
7
+ */
8
+ // ============================================================================
9
+ // PAGE CONFIGURATION
10
+ // ============================================================================
11
+ export const pageLimit = Number(process.env.NEXT_PUBLIC_PAGE_LIMIT) || 10;
12
+ // ============================================================================
13
+ // API ROUTES
14
+ // ============================================================================
15
+ export const USER_API_ROUTES = {
16
+ LIST: "/api/v1/user",
17
+ UNIT: "/api/v1/user",
18
+ UNIT_BY_EMAIL: "/api/v1/user-by-email",
19
+ };
@@ -0,0 +1,218 @@
1
+ import { UserBE, USER_ROLE } from "@/type";
2
+ import { type RowAction, type TableRow } from "@appcorp/shadcn/components/enhanced-table";
3
+ export declare const USER_DRAWER: {
4
+ readonly FILTER_DRAWER: string;
5
+ readonly FORM_DRAWER: string;
6
+ readonly MORE_ACTIONS_DRAWER: string;
7
+ readonly VIEW_DRAWER: string;
8
+ };
9
+ export declare const USER_ACTION_TYPES: {
10
+ readonly RESET_FORM: "RESET_FORM";
11
+ readonly SET_CURRENT_PAGE: "SET_CURRENT_PAGE";
12
+ readonly SET_PAGE_LIMIT: "SET_PAGE_LIMIT";
13
+ readonly SET_SEARCH_QUERY: "SET_SEARCH_QUERY";
14
+ readonly SET_DRAWER: "SET_DRAWER";
15
+ readonly SET_ITEMS: "SET_ITEMS";
16
+ readonly SET_FORM_DATA: "SET_FORM_DATA";
17
+ readonly SET_DISABLE_SAVE_BUTTON: "SET_DISABLE_SAVE_BUTTON";
18
+ readonly SET_INPUT_FIELD: "SET_INPUT_FIELD";
19
+ readonly SET_ERRORS: "SET_ERRORS";
20
+ readonly SET_FILTERS: "SET_FILTERS";
21
+ }, userModuleConfig: import("@react-pakistan/util-functions/factory/generic-module-factory").ModuleConfig<{
22
+ items: UserBE[];
23
+ count: number;
24
+ currentPage: number;
25
+ pageLimit: number;
26
+ searchQuery: string;
27
+ disableSaveButton: boolean;
28
+ drawer: string | null;
29
+ errors: Record<string, string>;
30
+ id: string;
31
+ name: string;
32
+ email: string;
33
+ phone: string;
34
+ avatar: string;
35
+ password: string;
36
+ enabled: boolean;
37
+ userRole: USER_ROLE | null;
38
+ filterEnabled: boolean | undefined;
39
+ }>, initialUserState: {
40
+ items: UserBE[];
41
+ count: number;
42
+ currentPage: number;
43
+ pageLimit: number;
44
+ searchQuery: string;
45
+ disableSaveButton: boolean;
46
+ drawer: string | null;
47
+ errors: Record<string, string>;
48
+ id: string;
49
+ name: string;
50
+ email: string;
51
+ phone: string;
52
+ avatar: string;
53
+ password: string;
54
+ enabled: boolean;
55
+ userRole: USER_ROLE | null;
56
+ filterEnabled: boolean | undefined;
57
+ }, UserProvider: import("react").FC<{
58
+ children: React.ReactNode;
59
+ }>, userReducer: (state: {
60
+ items: UserBE[];
61
+ count: number;
62
+ currentPage: number;
63
+ pageLimit: number;
64
+ searchQuery: string;
65
+ disableSaveButton: boolean;
66
+ drawer: string | null;
67
+ errors: Record<string, string>;
68
+ id: string;
69
+ name: string;
70
+ email: string;
71
+ phone: string;
72
+ avatar: string;
73
+ password: string;
74
+ enabled: boolean;
75
+ userRole: USER_ROLE | null;
76
+ filterEnabled: boolean | undefined;
77
+ }, action: any) => {
78
+ items: UserBE[];
79
+ count: number;
80
+ currentPage: number;
81
+ pageLimit: number;
82
+ searchQuery: string;
83
+ disableSaveButton: boolean;
84
+ drawer: string | null;
85
+ errors: Record<string, string>;
86
+ id: string;
87
+ name: string;
88
+ email: string;
89
+ phone: string;
90
+ avatar: string;
91
+ password: string;
92
+ enabled: boolean;
93
+ userRole: USER_ROLE | null;
94
+ filterEnabled: boolean | undefined;
95
+ }, useUserContext: () => import("@react-pakistan/util-functions/factory/generic-module-factory").GenericModuleContext<{
96
+ items: UserBE[];
97
+ count: number;
98
+ currentPage: number;
99
+ pageLimit: number;
100
+ searchQuery: string;
101
+ disableSaveButton: boolean;
102
+ drawer: string | null;
103
+ errors: Record<string, string>;
104
+ id: string;
105
+ name: string;
106
+ email: string;
107
+ phone: string;
108
+ avatar: string;
109
+ password: string;
110
+ enabled: boolean;
111
+ userRole: USER_ROLE | null;
112
+ filterEnabled: boolean | undefined;
113
+ }>;
114
+ export declare const useUserModule: () => {
115
+ applyFilters: () => void;
116
+ byIdLoading: boolean;
117
+ clearFilters: () => void;
118
+ deleteLoading: boolean;
119
+ handleAvatar: (files: File[]) => void;
120
+ handleChange: (field: string, value: string | number | boolean | undefined | null) => void;
121
+ handleCloseDrawer: () => void;
122
+ handleCreate: () => void;
123
+ handleDelete: (row?: TableRow) => void;
124
+ handleEdit: (row?: TableRow) => void;
125
+ handleFilters: () => void;
126
+ handleMoreActions: () => void;
127
+ handlePageChange: (page: number) => void;
128
+ handlePageLimitChange: (limit: number) => void;
129
+ handleSearch: (query: string) => void;
130
+ handleSubmit: () => Promise<void>;
131
+ handleView: (row?: TableRow) => void;
132
+ headerActions: {
133
+ enabled: boolean;
134
+ handleOnClick: () => void;
135
+ label: string;
136
+ order: number;
137
+ icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
138
+ }[];
139
+ listLoading: boolean;
140
+ rowActions: RowAction[];
141
+ toggleStatus: (row?: TableRow) => void;
142
+ updateLoading: boolean;
143
+ state: {
144
+ items: UserBE[];
145
+ count: number;
146
+ currentPage: number;
147
+ pageLimit: number;
148
+ searchQuery: string;
149
+ disableSaveButton: boolean;
150
+ drawer: string | null;
151
+ errors: Record<string, string>;
152
+ id: string;
153
+ name: string;
154
+ email: string;
155
+ phone: string;
156
+ avatar: string;
157
+ password: string;
158
+ enabled: boolean;
159
+ userRole: USER_ROLE | null;
160
+ filterEnabled: boolean | undefined;
161
+ };
162
+ dispatch: React.Dispatch<any>;
163
+ };
164
+ /** @deprecated Use `UserProvider` */
165
+ export declare const UserStateContextProvider: import("react").FC<{
166
+ children: React.ReactNode;
167
+ }>;
168
+ /** @deprecated Use `useUserModule` */
169
+ export declare const useUserStateContext: () => {
170
+ applyFilters: () => void;
171
+ byIdLoading: boolean;
172
+ clearFilters: () => void;
173
+ deleteLoading: boolean;
174
+ handleAvatar: (files: File[]) => void;
175
+ handleChange: (field: string, value: string | number | boolean | undefined | null) => void;
176
+ handleCloseDrawer: () => void;
177
+ handleCreate: () => void;
178
+ handleDelete: (row?: TableRow) => void;
179
+ handleEdit: (row?: TableRow) => void;
180
+ handleFilters: () => void;
181
+ handleMoreActions: () => void;
182
+ handlePageChange: (page: number) => void;
183
+ handlePageLimitChange: (limit: number) => void;
184
+ handleSearch: (query: string) => void;
185
+ handleSubmit: () => Promise<void>;
186
+ handleView: (row?: TableRow) => void;
187
+ headerActions: {
188
+ enabled: boolean;
189
+ handleOnClick: () => void;
190
+ label: string;
191
+ order: number;
192
+ icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
193
+ }[];
194
+ listLoading: boolean;
195
+ rowActions: RowAction[];
196
+ toggleStatus: (row?: TableRow) => void;
197
+ updateLoading: boolean;
198
+ state: {
199
+ items: UserBE[];
200
+ count: number;
201
+ currentPage: number;
202
+ pageLimit: number;
203
+ searchQuery: string;
204
+ disableSaveButton: boolean;
205
+ drawer: string | null;
206
+ errors: Record<string, string>;
207
+ id: string;
208
+ name: string;
209
+ email: string;
210
+ phone: string;
211
+ avatar: string;
212
+ password: string;
213
+ enabled: boolean;
214
+ userRole: USER_ROLE | null;
215
+ filterEnabled: boolean | undefined;
216
+ };
217
+ dispatch: React.Dispatch<any>;
218
+ };