@appcorp/fusion-storybook 0.1.4

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 (131) hide show
  1. package/README.md +147 -0
  2. package/base-modules/admission/cache.d.ts +14 -0
  3. package/base-modules/admission/cache.js +31 -0
  4. package/base-modules/admission/constants.d.ts +32 -0
  5. package/base-modules/admission/constants.js +37 -0
  6. package/base-modules/admission/context.d.ts +369 -0
  7. package/base-modules/admission/context.js +755 -0
  8. package/base-modules/admission/filter.d.ts +1 -0
  9. package/base-modules/admission/filter.js +31 -0
  10. package/base-modules/admission/form.d.ts +1 -0
  11. package/base-modules/admission/form.js +86 -0
  12. package/base-modules/admission/more-actions.d.ts +1 -0
  13. package/base-modules/admission/more-actions.js +5 -0
  14. package/base-modules/admission/page.d.ts +16 -0
  15. package/base-modules/admission/page.js +128 -0
  16. package/base-modules/admission/validate.d.ts +38 -0
  17. package/base-modules/admission/validate.js +70 -0
  18. package/base-modules/admission/view.d.ts +1 -0
  19. package/base-modules/admission/view.js +40 -0
  20. package/base-modules/discount-code/cache.d.ts +27 -0
  21. package/base-modules/discount-code/cache.js +46 -0
  22. package/base-modules/discount-code/constants.d.ts +19 -0
  23. package/base-modules/discount-code/constants.js +26 -0
  24. package/base-modules/discount-code/context.d.ts +154 -0
  25. package/base-modules/discount-code/context.js +416 -0
  26. package/base-modules/discount-code/filter.d.ts +9 -0
  27. package/base-modules/discount-code/filter.js +14 -0
  28. package/base-modules/discount-code/form.d.ts +1 -0
  29. package/base-modules/discount-code/form.js +44 -0
  30. package/base-modules/discount-code/more-actions.d.ts +9 -0
  31. package/base-modules/discount-code/more-actions.js +13 -0
  32. package/base-modules/discount-code/page.d.ts +16 -0
  33. package/base-modules/discount-code/page.js +120 -0
  34. package/base-modules/discount-code/validate.d.ts +19 -0
  35. package/base-modules/discount-code/validate.js +38 -0
  36. package/base-modules/discount-code/view.d.ts +1 -0
  37. package/base-modules/discount-code/view.js +26 -0
  38. package/base-modules/family/cache.d.ts +14 -0
  39. package/base-modules/family/cache.js +31 -0
  40. package/base-modules/family/constants.d.ts +22 -0
  41. package/base-modules/family/constants.js +26 -0
  42. package/base-modules/family/context.d.ts +173 -0
  43. package/base-modules/family/context.js +441 -0
  44. package/base-modules/family/filter.d.ts +1 -0
  45. package/base-modules/family/filter.js +28 -0
  46. package/base-modules/family/form.d.ts +1 -0
  47. package/base-modules/family/form.js +12 -0
  48. package/base-modules/family/more-actions.d.ts +1 -0
  49. package/base-modules/family/more-actions.js +5 -0
  50. package/base-modules/family/page.d.ts +16 -0
  51. package/base-modules/family/page.js +120 -0
  52. package/base-modules/family/validate.d.ts +15 -0
  53. package/base-modules/family/validate.js +18 -0
  54. package/base-modules/family/view.d.ts +1 -0
  55. package/base-modules/family/view.js +18 -0
  56. package/base-modules/family-member/cache.d.ts +14 -0
  57. package/base-modules/family-member/cache.js +31 -0
  58. package/base-modules/family-member/constants.d.ts +22 -0
  59. package/base-modules/family-member/constants.js +26 -0
  60. package/base-modules/family-member/context.d.ts +215 -0
  61. package/base-modules/family-member/context.js +486 -0
  62. package/base-modules/family-member/filter.d.ts +1 -0
  63. package/base-modules/family-member/filter.js +28 -0
  64. package/base-modules/family-member/form.d.ts +1 -0
  65. package/base-modules/family-member/form.js +17 -0
  66. package/base-modules/family-member/more-actions.d.ts +1 -0
  67. package/base-modules/family-member/more-actions.js +5 -0
  68. package/base-modules/family-member/page.d.ts +16 -0
  69. package/base-modules/family-member/page.js +122 -0
  70. package/base-modules/family-member/validate.d.ts +24 -0
  71. package/base-modules/family-member/validate.js +27 -0
  72. package/base-modules/family-member/view.d.ts +1 -0
  73. package/base-modules/family-member/view.js +40 -0
  74. package/base-modules/student-profile/cache.d.ts +14 -0
  75. package/base-modules/student-profile/cache.js +31 -0
  76. package/base-modules/student-profile/constants.d.ts +105 -0
  77. package/base-modules/student-profile/constants.js +132 -0
  78. package/base-modules/student-profile/context.d.ts +290 -0
  79. package/base-modules/student-profile/context.js +583 -0
  80. package/base-modules/student-profile/filter.d.ts +1 -0
  81. package/base-modules/student-profile/filter.js +26 -0
  82. package/base-modules/student-profile/form.d.ts +1 -0
  83. package/base-modules/student-profile/form.js +19 -0
  84. package/base-modules/student-profile/more-actions.d.ts +1 -0
  85. package/base-modules/student-profile/more-actions.js +5 -0
  86. package/base-modules/student-profile/page.d.ts +9 -0
  87. package/base-modules/student-profile/page.js +86 -0
  88. package/base-modules/student-profile/validate.d.ts +23 -0
  89. package/base-modules/student-profile/validate.js +34 -0
  90. package/base-modules/student-profile/view.d.ts +1 -0
  91. package/base-modules/student-profile/view.js +29 -0
  92. package/base-modules/workspace/cache.d.ts +9 -0
  93. package/base-modules/workspace/cache.js +28 -0
  94. package/base-modules/workspace/constants.d.ts +10 -0
  95. package/base-modules/workspace/constants.js +18 -0
  96. package/base-modules/workspace/context.d.ts +187 -0
  97. package/base-modules/workspace/context.js +293 -0
  98. package/base-modules/workspace/drawer.d.ts +1 -0
  99. package/base-modules/workspace/drawer.js +24 -0
  100. package/base-modules/workspace/filter.d.ts +1 -0
  101. package/base-modules/workspace/filter.js +13 -0
  102. package/base-modules/workspace/form.d.ts +1 -0
  103. package/base-modules/workspace/form.js +40 -0
  104. package/base-modules/workspace/more-actions.d.ts +1 -0
  105. package/base-modules/workspace/more-actions.js +13 -0
  106. package/base-modules/workspace/page.d.ts +1 -0
  107. package/base-modules/workspace/page.js +31 -0
  108. package/base-modules/workspace/validate.d.ts +9 -0
  109. package/base-modules/workspace/validate.js +8 -0
  110. package/base-modules/workspace/view.d.ts +1 -0
  111. package/base-modules/workspace/view.js +52 -0
  112. package/components/rbac-no-access.d.ts +6 -0
  113. package/components/rbac-no-access.js +4 -0
  114. package/constants.d.ts +81 -0
  115. package/constants.js +81 -0
  116. package/lib/utils.d.ts +2 -0
  117. package/lib/utils.js +5 -0
  118. package/package.json +104 -0
  119. package/tsconfig.build.tsbuildinfo +1 -0
  120. package/type.d.ts +1141 -0
  121. package/type.js +427 -0
  122. package/utils/admission-pdf.d.ts +78 -0
  123. package/utils/admission-pdf.js +73 -0
  124. package/utils/clear-cache.d.ts +1 -0
  125. package/utils/clear-cache.js +8 -0
  126. package/utils/format-value.d.ts +1 -0
  127. package/utils/format-value.js +1 -0
  128. package/utils/pdf-generator.d.ts +41 -0
  129. package/utils/pdf-generator.js +107 -0
  130. package/utils/resolve-rbac-permissions.d.ts +11 -0
  131. package/utils/resolve-rbac-permissions.js +251 -0
@@ -0,0 +1,122 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * Family Member 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
+ * - familyMemberConfig (memoised on locale change only; size fixed so the
10
+ * 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 { useFamilyMemberModule, FamilyMemberProvider, FAMILY_MEMBER_DRAWER, FAMILY_MEMBER_ACTION_TYPES, } from "./context";
18
+ import { FamilyMemberFilter } from "./filter";
19
+ import { FamilyMemberForm } from "./form";
20
+ import { FamilyMemberMoreActions } from "./more-actions";
21
+ import { FamilyMemberView } from "./view";
22
+ import { resolveRbacPermissions } from "@/utils/resolve-rbac-permissions";
23
+ import { RbacNoAccess } from "@/components/rbac-no-access";
24
+ import { useTranslations } from "next-intl";
25
+ // ============================================================================
26
+ // TABLE COLUMN CONFIGURATION (static — no runtime deps)
27
+ // ============================================================================
28
+ const tableBodyCols = [
29
+ { componentType: COMPONENT_TYPE.ID, key: "id" },
30
+ { componentType: COMPONENT_TYPE.BOLD_TEXT, key: ["firstName", "lastName"] },
31
+ { componentType: COMPONENT_TYPE.TEXT, key: "role" },
32
+ { componentType: COMPONENT_TYPE.TEXT, key: "email" },
33
+ { componentType: COMPONENT_TYPE.TEXT, key: "phone" },
34
+ { componentType: COMPONENT_TYPE.BOOLEAN, key: "isPrimary" },
35
+ { componentType: COMPONENT_TYPE.BOOLEAN, key: "enabled" },
36
+ { componentType: COMPONENT_TYPE.ACTIONS },
37
+ ];
38
+ const tableColumns = [
39
+ { label: "id", width: "5%" },
40
+ { label: "firstName", width: "20%" },
41
+ { label: "role", width: "15%" },
42
+ { label: "email", width: "20%" },
43
+ { label: "phone", width: "15%" },
44
+ { label: "primaryContact", width: "10%" },
45
+ { label: "status", width: "10%" },
46
+ { label: "actions", width: "5%" },
47
+ ];
48
+ // ============================================================================
49
+ // TRANSLATED COLUMNS HELPER
50
+ // ============================================================================
51
+ const getTranslatedColumns = (t) => tableColumns.map((col) => (Object.assign(Object.assign({}, col), { label: t(col.label) })));
52
+ // ============================================================================
53
+ // COMPONENT FACTORY (creates JSX elements when config is created, not during render)
54
+ // ============================================================================
55
+ const createComponentInstances = () => ({
56
+ filter: _jsx(FamilyMemberFilter, {}),
57
+ form: _jsx(FamilyMemberForm, {}),
58
+ moreActions: _jsx(FamilyMemberMoreActions, {}),
59
+ view: _jsx(FamilyMemberView, {}),
60
+ });
61
+ // ============================================================================
62
+ // CONFIG CREATION HELPER
63
+ // ============================================================================
64
+ const createFamilyMemberConfig = (t, drawer, dispatch) => {
65
+ const components = createComponentInstances();
66
+ return {
67
+ moduleName: "familyMember",
68
+ tableColumns: getTranslatedColumns(t),
69
+ cancelLabel: t("cancel"),
70
+ drawerTitle: t("familyMember"),
71
+ filterContent: components.filter,
72
+ formContent: components.form,
73
+ moreActionsContent: components.moreActions,
74
+ saveLabel: t("save"),
75
+ searchPlaceholder: t("searchFamilyMembers"),
76
+ tableDescription: t("manageFamilyMembersAndTheirInformation"),
77
+ tableTitle: t("familyMember"),
78
+ viewContent: components.view,
79
+ size: drawer === FAMILY_MEMBER_DRAWER.FORM_DRAWER ? "full" : "small",
80
+ onClearFilters: () => {
81
+ dispatch({ type: FAMILY_MEMBER_ACTION_TYPES.RESET_FORM });
82
+ },
83
+ };
84
+ };
85
+ // ============================================================================
86
+ // STABLE PAGE COMPONENT (created once, outside render)
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
+ });
104
+ // ============================================================================
105
+ // INNER PAGE (requires FamilyMemberProvider context)
106
+ // ============================================================================
107
+ const FamilyMemberPageInner = ({ userRole }) => {
108
+ const t = useTranslations("familyMember");
109
+ const context = useFamilyMemberModule();
110
+ // Memoize permission check to avoid recalculation on every render
111
+ const hasPermission = useMemo(() => resolveRbacPermissions({
112
+ userRole,
113
+ moduleName: "People Management",
114
+ }), [userRole]);
115
+ // Memoize config creation
116
+ const familyMemberConfig = useMemo(() => createFamilyMemberConfig(t, context.state.drawer, context.dispatch), [t, context.state.drawer, context.dispatch]);
117
+ if (!hasPermission) {
118
+ return _jsx(RbacNoAccess, { moduleName: "People Management" });
119
+ }
120
+ return (_jsx("div", { className: "p-4", children: _jsx(GenericFamilyMemberPage, { config: familyMemberConfig, context: context, tableBodyCols: tableBodyCols }) }));
121
+ };
122
+ export const FamilyMemberPage = ({ userRole }) => (_jsx(FamilyMemberProvider, { children: _jsx(FamilyMemberPageInner, { userRole: userRole }) }));
@@ -0,0 +1,24 @@
1
+ /**
2
+ * FamilyMember Validation Schema
3
+ *
4
+ * Zod validation schemas for family-member form data.
5
+ */
6
+ import { z } from "zod";
7
+ export declare const familyMemberFormValidation: z.ZodObject<{
8
+ familyId: z.ZodString;
9
+ firstName: z.ZodString;
10
+ lastName: z.ZodString;
11
+ role: z.ZodString;
12
+ dateOfBirth: z.ZodOptional<z.ZodString>;
13
+ gender: z.ZodOptional<z.ZodString>;
14
+ bloodGroup: z.ZodOptional<z.ZodString>;
15
+ phone: z.ZodOptional<z.ZodString>;
16
+ email: z.ZodUnion<[z.ZodOptional<z.ZodString>, z.ZodLiteral<"">]>;
17
+ relationship: z.ZodOptional<z.ZodString>;
18
+ occupation: z.ZodOptional<z.ZodString>;
19
+ emergencyPhone: z.ZodOptional<z.ZodString>;
20
+ idNumber: z.ZodOptional<z.ZodString>;
21
+ avatar: z.ZodOptional<z.ZodString>;
22
+ isPrimary: z.ZodOptional<z.ZodBoolean>;
23
+ enabled: z.ZodOptional<z.ZodBoolean>;
24
+ }, z.core.$strip>;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * FamilyMember Validation Schema
3
+ *
4
+ * Zod validation schemas for family-member form data.
5
+ */
6
+ import { z } from "zod";
7
+ // ============================================================================
8
+ // VALIDATION SCHEMA
9
+ // ============================================================================
10
+ export const familyMemberFormValidation = z.object({
11
+ familyId: z.string().min(1, "Family is required"),
12
+ firstName: z.string().min(1, "First name is required"),
13
+ lastName: z.string().min(1, "Last name is required"),
14
+ role: z.string().min(1, "Role is required"),
15
+ dateOfBirth: z.string().optional(),
16
+ gender: z.string().optional(),
17
+ bloodGroup: z.string().optional(),
18
+ phone: z.string().optional(),
19
+ email: z.string().email().optional().or(z.literal("")),
20
+ relationship: z.string().optional(),
21
+ occupation: z.string().optional(),
22
+ emergencyPhone: z.string().optional(),
23
+ idNumber: z.string().optional(),
24
+ avatar: z.string().optional(),
25
+ isPrimary: z.boolean().optional(),
26
+ enabled: z.boolean().optional(),
27
+ });
@@ -0,0 +1 @@
1
+ export declare const FamilyMemberView: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * FamilyMember View Component
5
+ *
6
+ * Read-only detail view for a family member record.
7
+ */
8
+ import { Avatar, AvatarFallback, AvatarImage, } from "@appcorp/shadcn/components/ui/avatar";
9
+ import { Badge } from "@appcorp/shadcn/components/ui/badge";
10
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@appcorp/shadcn/components/ui/card";
11
+ import { Separator } from "@appcorp/shadcn/components/ui/separator";
12
+ import { DATE_FORMATS, formatDate } from "@react-pakistan/util-functions";
13
+ import { Briefcase, Calendar, CheckCircle2, Heart, Mail, Phone, ShieldCheck, User, Users, XCircle, } from "lucide-react";
14
+ import { useFamilyMemberModule } from "./context";
15
+ import { useTranslations } from "next-intl";
16
+ import { formatValue } from "@/utils/format-value";
17
+ export const FamilyMemberView = () => {
18
+ const { state } = useFamilyMemberModule();
19
+ const { avatar, bloodGroup, dateOfBirth, email, emergencyPhone, enabled, firstName, gender, idNumber, isPrimary, lastName, occupation, phone, relationship, role, } = state;
20
+ const t = useTranslations("familyMember");
21
+ const fullName = [firstName, lastName].filter(Boolean).join(" ") || t("familyMember");
22
+ const initials = `${(firstName === null || firstName === void 0 ? void 0 : firstName[0]) || ""}${(lastName === null || lastName === void 0 ? void 0 : lastName[0]) || ""}`
23
+ .toUpperCase()
24
+ .slice(0, 2);
25
+ const formatEnumValue = (value) => {
26
+ if (!value)
27
+ return "—";
28
+ return value.toLowerCase().replace(/_/g, " ");
29
+ };
30
+ const formatDateValue = (value) => {
31
+ if (!value)
32
+ return "—";
33
+ return formatDate(new Date(value).toISOString(), DATE_FORMATS.LOCALE_DATE);
34
+ };
35
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(Card, { children: _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "flex items-center gap-6", children: [_jsxs(Avatar, { className: "h-24 w-24", children: [_jsx(AvatarImage, { src: avatar || undefined, alt: fullName }), _jsx(AvatarFallback, { className: "text-2xl", children: initials || "FM" })] }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("h2", { className: "text-2xl font-bold", children: fullName }), enabled ? (_jsxs(Badge, { variant: "default", className: "gap-1", children: [_jsx(CheckCircle2, { className: "h-3 w-3" }), t("active")] })) : (_jsxs(Badge, { variant: "secondary", className: "gap-1", children: [_jsx(XCircle, { className: "h-3 w-3" }), t("inactive")] })), isPrimary && (_jsxs(Badge, { variant: "outline", className: "gap-1", children: [_jsx(ShieldCheck, { className: "h-3 w-3" }), t("primaryContact")] }))] }), _jsx("p", { className: "mt-1 text-sm text-muted-foreground", children: t("familyMemberProfile") }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [role ? (_jsx(Badge, { variant: "secondary", className: "capitalize", children: formatEnumValue(role) })) : null, relationship ? (_jsx(Badge, { variant: "outline", className: "capitalize", children: formatEnumValue(relationship) })) : null, gender ? (_jsx(Badge, { variant: "outline", className: "capitalize", children: formatEnumValue(gender) })) : null] })] })] }) }) }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(User, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { className: "text-lg", children: t("personalInformation") })] }), _jsx(CardDescription, { children: t("basicIdentityAndProfileDetails") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("firstName") }), _jsx("p", { className: "text-base", children: formatValue(firstName) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("lastName") }), _jsx("p", { className: "text-base", children: formatValue(lastName) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("role") }), role ? (_jsx(Badge, { variant: "secondary", className: "capitalize", children: formatEnumValue(role) })) : (_jsx("p", { className: "text-base", children: "\u2014" }))] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Calendar, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("dateOfBirth") })] }), _jsx("p", { className: "text-base", children: formatDateValue(dateOfBirth) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("gender") }), gender ? (_jsx(Badge, { variant: "outline", className: "capitalize", children: formatEnumValue(gender) })) : (_jsx("p", { className: "text-base", children: "\u2014" }))] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Heart, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("bloodGroup") })] }), _jsx("p", { className: "text-base", children: formatValue(bloodGroup) })] }), _jsxs("div", { className: "space-y-1 md:col-span-2", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("idNumber") }), _jsx("p", { className: "text-base", children: formatValue(idNumber) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { className: "text-lg", children: t("contactInformation") })] }), _jsx(CardDescription, { children: t("reachabilityAndEmergencyContactDetails") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", 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(Mail, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("email") })] }), _jsx("p", { className: "text-base", children: formatValue(email) })] }), _jsxs("div", { className: "space-y-1 md:col-span-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Phone, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", 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(Users, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { className: "text-lg", children: t("familyRole") })] }), _jsx(CardDescription, { children: t("relationshipAndHouseholdResponsibilities") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("relationship") }), relationship ? (_jsx(Badge, { variant: "secondary", className: "capitalize", children: formatEnumValue(relationship) })) : (_jsx("p", { className: "text-base", children: "\u2014" }))] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Briefcase, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("occupation") })] }), _jsx("p", { className: "text-base", children: formatValue(occupation) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ShieldCheck, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { className: "text-lg", children: t("status") })] }), _jsx(CardDescription, { children: t("primaryContactAndAccountActivity") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2", children: [_jsxs("div", { className: "flex items-start gap-3", children: [_jsx(ShieldCheck, { className: "mt-0.5 h-5 w-5 text-primary" }), _jsxs("div", { children: [_jsx("p", { className: "font-medium", children: isPrimary ? t("primaryContact") : t("secondaryContact") }), _jsx("p", { className: "text-sm text-muted-foreground", children: isPrimary
36
+ ? t("thisIsPrimaryFamilyContact")
37
+ : t("thisIsAdditionalFamilyContact") })] })] }), _jsxs("div", { className: "flex items-start gap-3", children: [enabled ? (_jsx(CheckCircle2, { className: "mt-0.5 h-5 w-5 text-green-500" })) : (_jsx(XCircle, { className: "mt-0.5 h-5 w-5 text-red-500" })), _jsxs("div", { children: [_jsx("p", { className: "font-medium", children: enabled ? t("active") : t("inactive") }), _jsx("p", { className: "text-sm text-muted-foreground", children: enabled
38
+ ? t("thisAccountIsCurrentlyActive")
39
+ : t("thisAccountIsCurrentlyInactive") })] })] })] }) })] })] }));
40
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Student Profile Module Cache Utilities
3
+ *
4
+ * Provides localStorage-based caching for student profiles using generic cache system.
5
+ */
6
+ import { StudentProfileBE } from "@/type";
7
+ export declare const getCachedStudentProfilesSync: () => import("@react-pakistan/util-functions").ListResponse<StudentProfileBE>;
8
+ export declare const getCachedStudentProfiles: ({ params, }: {
9
+ params?: Record<string, unknown>;
10
+ }) => Promise<import("@react-pakistan/util-functions").ListResponse<StudentProfileBE>>;
11
+ export declare const getCachedStudentProfileById: (studentProfileId: string) => StudentProfileBE | null;
12
+ export declare const invalidateStudentProfilesCache: () => void;
13
+ export declare const preloadStudentProfiles: () => Promise<import("@react-pakistan/util-functions").ListResponse<StudentProfileBE>>;
14
+ export declare const isStudentProfilesCacheStale: () => boolean;
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Student Profile Module Cache Utilities
3
+ *
4
+ * Provides localStorage-based caching for student profiles using generic cache system.
5
+ */
6
+ import { LS_KEYS } from "@/constants";
7
+ import { STUDENT_PROFILE_API_ROUTES } from "./constants";
8
+ import { getCachedData, getCachedDataSync, getCachedItemById, invalidateCache, isCacheStale, preloadCache, } from "@react-pakistan/util-functions";
9
+ // ============================================================================
10
+ // CACHE CONFIGURATION
11
+ // ============================================================================
12
+ const STUDENT_PROFILE_CACHE_CONFIG = {
13
+ apiUrl: STUDENT_PROFILE_API_ROUTES.UNIT,
14
+ cacheKey: LS_KEYS.STUDENT_PROFILES,
15
+ };
16
+ // ============================================================================
17
+ // STUDENT_PROFILE-SPECIFIC CACHE FUNCTIONS
18
+ // ============================================================================
19
+ export const getCachedStudentProfilesSync = () => getCachedDataSync(LS_KEYS.STUDENT_PROFILES);
20
+ export const getCachedStudentProfiles = ({ params, }) => getCachedData({
21
+ config: STUDENT_PROFILE_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 getCachedStudentProfileById = (studentProfileId) => getCachedItemById(LS_KEYS.STUDENT_PROFILES, studentProfileId);
29
+ export const invalidateStudentProfilesCache = () => invalidateCache(LS_KEYS.STUDENT_PROFILES);
30
+ export const preloadStudentProfiles = () => preloadCache(STUDENT_PROFILE_CACHE_CONFIG);
31
+ export const isStudentProfilesCacheStale = () => isCacheStale(LS_KEYS.STUDENT_PROFILES);
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Student Constants
3
+ *
4
+ * Organization:
5
+ * - Page Configuration
6
+ * - API Routes
7
+ * - Table Configuration
8
+ * - Status Options
9
+ * - Gender Options
10
+ */
11
+ import { COMPONENT_TYPE } from "@appcorp/shadcn/components/enhanced-table";
12
+ export declare const pageLimit: number;
13
+ export declare const STUDENT_PROFILE_API_ROUTES: Record<string, string>;
14
+ export declare const tableHeadItems: {
15
+ label: string;
16
+ width: string;
17
+ }[];
18
+ export declare const tableBodyCols: ({
19
+ componentType: COMPONENT_TYPE;
20
+ key: string;
21
+ textFormatter?: undefined;
22
+ } | {
23
+ componentType: COMPONENT_TYPE;
24
+ key: string[];
25
+ textFormatter?: undefined;
26
+ } | {
27
+ componentType: COMPONENT_TYPE;
28
+ key: string;
29
+ textFormatter: (value: unknown) => string;
30
+ } | {
31
+ componentType: COMPONENT_TYPE;
32
+ key?: undefined;
33
+ textFormatter?: undefined;
34
+ })[];
35
+ export declare const STATUS_OPTIONS: readonly [{
36
+ readonly label: "All Status";
37
+ readonly value: "";
38
+ }, {
39
+ readonly label: "Active";
40
+ readonly value: "ACTIVE";
41
+ }, {
42
+ readonly label: "Inactive";
43
+ readonly value: "INACTIVE";
44
+ }, {
45
+ readonly label: "Graduated";
46
+ readonly value: "GRADUATED";
47
+ }, {
48
+ readonly label: "Transferred";
49
+ readonly value: "TRANSFERRED";
50
+ }, {
51
+ readonly label: "Expelled";
52
+ readonly value: "EXPELLED";
53
+ }];
54
+ export declare const STATUS_BADGE_COLORS: Record<string, string>;
55
+ export declare const GENDER_OPTIONS: readonly [{
56
+ readonly label: "All Genders";
57
+ readonly value: "";
58
+ }, {
59
+ readonly label: "Male";
60
+ readonly value: "MALE";
61
+ }, {
62
+ readonly label: "Female";
63
+ readonly value: "FEMALE";
64
+ }, {
65
+ readonly label: "Other";
66
+ readonly value: "OTHER";
67
+ }];
68
+ export declare const ENABLED_OPTIONS: readonly [{
69
+ readonly label: "All";
70
+ readonly value: "";
71
+ }, {
72
+ readonly label: "Enabled";
73
+ readonly value: "true";
74
+ }, {
75
+ readonly label: "Disabled";
76
+ readonly value: "false";
77
+ }];
78
+ export declare const BLOOD_GROUP_OPTIONS: readonly [{
79
+ readonly label: "Select Blood Group";
80
+ readonly value: "";
81
+ }, {
82
+ readonly label: "A+";
83
+ readonly value: "A+";
84
+ }, {
85
+ readonly label: "A-";
86
+ readonly value: "A-";
87
+ }, {
88
+ readonly label: "B+";
89
+ readonly value: "B+";
90
+ }, {
91
+ readonly label: "B-";
92
+ readonly value: "B-";
93
+ }, {
94
+ readonly label: "AB+";
95
+ readonly value: "AB+";
96
+ }, {
97
+ readonly label: "AB-";
98
+ readonly value: "AB-";
99
+ }, {
100
+ readonly label: "O+";
101
+ readonly value: "O+";
102
+ }, {
103
+ readonly label: "O-";
104
+ readonly value: "O-";
105
+ }];
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Student Constants
3
+ *
4
+ * Organization:
5
+ * - Page Configuration
6
+ * - API Routes
7
+ * - Table Configuration
8
+ * - Status Options
9
+ * - Gender Options
10
+ */
11
+ import { COMPONENT_TYPE } from "@appcorp/shadcn/components/enhanced-table";
12
+ // ============================================================================
13
+ // PAGE CONFIGURATION
14
+ // ============================================================================
15
+ export const pageLimit = Number(process.env.NEXT_PUBLIC_PAGE_LIMIT) || 10;
16
+ // ============================================================================
17
+ // API ROUTES
18
+ // ============================================================================
19
+ export const STUDENT_PROFILE_API_ROUTES = {
20
+ UNIT: "/api/v1/student-profile",
21
+ };
22
+ // ============================================================================
23
+ // TABLE CONFIGURATION
24
+ // ============================================================================
25
+ export const tableHeadItems = [
26
+ { label: "ID", width: "5%" },
27
+ { label: "First Name", width: "15%" },
28
+ { label: "Last Name", width: "15%" },
29
+ { label: "Computer Number", width: "15%" },
30
+ { label: "Discount Code", width: "15%" },
31
+ { label: "Enrolled Class", width: "15%" },
32
+ { label: "Status", width: "10%" },
33
+ { label: "Enabled", width: "5%" },
34
+ { label: "Actions", width: "5%" },
35
+ ];
36
+ export const tableBodyCols = [
37
+ {
38
+ componentType: COMPONENT_TYPE.ID,
39
+ key: "id",
40
+ },
41
+ {
42
+ componentType: COMPONENT_TYPE.OBJECT,
43
+ key: ["familyMember:firstName"],
44
+ },
45
+ {
46
+ componentType: COMPONENT_TYPE.OBJECT,
47
+ key: ["familyMember:lastName"],
48
+ },
49
+ {
50
+ componentType: COMPONENT_TYPE.TEXT,
51
+ key: "computerNumber",
52
+ },
53
+ {
54
+ componentType: COMPONENT_TYPE.TEXT,
55
+ key: "discountCode",
56
+ textFormatter: (value) => value || "N/A",
57
+ },
58
+ {
59
+ componentType: COMPONENT_TYPE.TEXT,
60
+ key: "enrollments",
61
+ textFormatter: (value) => {
62
+ var _a;
63
+ const enrollments = value;
64
+ if (!enrollments || enrollments.length === 0)
65
+ return "No enrollments";
66
+ if (enrollments.length === 1) {
67
+ return ((_a = enrollments[0].course) === null || _a === void 0 ? void 0 : _a.code) || "Unknown course";
68
+ }
69
+ return `${enrollments.length} courses`;
70
+ },
71
+ },
72
+ {
73
+ componentType: COMPONENT_TYPE.TEXT,
74
+ key: "status",
75
+ },
76
+ {
77
+ componentType: COMPONENT_TYPE.BOOLEAN,
78
+ key: "enabled",
79
+ },
80
+ {
81
+ componentType: COMPONENT_TYPE.ACTIONS,
82
+ },
83
+ ];
84
+ // ============================================================================
85
+ // STATUS OPTIONS
86
+ // ============================================================================
87
+ export const STATUS_OPTIONS = [
88
+ { label: "All Status", value: "" },
89
+ { label: "Active", value: "ACTIVE" },
90
+ { label: "Inactive", value: "INACTIVE" },
91
+ { label: "Graduated", value: "GRADUATED" },
92
+ { label: "Transferred", value: "TRANSFERRED" },
93
+ { label: "Expelled", value: "EXPELLED" },
94
+ ];
95
+ export const STATUS_BADGE_COLORS = {
96
+ ACTIVE: "bg-green-500/10 text-green-700 dark:text-green-400",
97
+ INACTIVE: "bg-gray-500/10 text-gray-700 dark:text-gray-400",
98
+ GRADUATED: "bg-blue-500/10 text-blue-700 dark:text-blue-400",
99
+ TRANSFERRED: "bg-yellow-500/10 text-yellow-700 dark:text-yellow-400",
100
+ EXPELLED: "bg-red-500/10 text-red-700 dark:text-red-400",
101
+ };
102
+ // ============================================================================
103
+ // GENDER OPTIONS
104
+ // ============================================================================
105
+ export const GENDER_OPTIONS = [
106
+ { label: "All Genders", value: "" },
107
+ { label: "Male", value: "MALE" },
108
+ { label: "Female", value: "FEMALE" },
109
+ { label: "Other", value: "OTHER" },
110
+ ];
111
+ // ============================================================================
112
+ // ENABLED OPTIONS
113
+ // ============================================================================
114
+ export const ENABLED_OPTIONS = [
115
+ { label: "All", value: "" },
116
+ { label: "Enabled", value: "true" },
117
+ { label: "Disabled", value: "false" },
118
+ ];
119
+ // ============================================================================
120
+ // BLOOD GROUP OPTIONS
121
+ // ============================================================================
122
+ export const BLOOD_GROUP_OPTIONS = [
123
+ { label: "Select Blood Group", value: "" },
124
+ { label: "A+", value: "A+" },
125
+ { label: "A-", value: "A-" },
126
+ { label: "B+", value: "B+" },
127
+ { label: "B-", value: "B-" },
128
+ { label: "AB+", value: "AB+" },
129
+ { label: "AB-", value: "AB-" },
130
+ { label: "O+", value: "O+" },
131
+ { label: "O-", value: "O-" },
132
+ ];