@appcorp/fusion-storybook 0.2.61 → 0.2.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/base-modules/class/more-actions.js +1 -1
  2. package/base-modules/course/context.d.ts +12 -0
  3. package/base-modules/course/context.js +23 -7
  4. package/base-modules/course/form.js +34 -3
  5. package/base-modules/course/page.d.ts +1 -0
  6. package/base-modules/course/page.js +16 -5
  7. package/base-modules/course/validate.d.ts +1 -0
  8. package/base-modules/course/validate.js +1 -0
  9. package/base-modules/course/view.js +6 -2
  10. package/base-modules/enrollment/context.d.ts +13 -1
  11. package/base-modules/enrollment/context.js +3 -0
  12. package/base-modules/enrollment/form.js +31 -3
  13. package/base-modules/enrollment/more-actions.js +9 -7
  14. package/base-modules/enrollment/page.d.ts +1 -0
  15. package/base-modules/enrollment/page.js +15 -4
  16. package/base-modules/enrollment/validate.d.ts +1 -0
  17. package/base-modules/enrollment/validate.js +1 -0
  18. package/base-modules/enrollment/view.js +5 -2
  19. package/base-modules/section/cache.js +0 -1
  20. package/base-modules/section/context.d.ts +0 -6
  21. package/base-modules/section/context.js +0 -3
  22. package/base-modules/section/form.js +2 -36
  23. package/base-modules/section/more-actions.js +5 -7
  24. package/base-modules/section/page.d.ts +0 -1
  25. package/base-modules/section/page.js +3 -7
  26. package/base-modules/section/validate.d.ts +0 -1
  27. package/base-modules/section/validate.js +0 -1
  28. package/base-modules/section/view.js +2 -10
  29. package/constants.d.ts +0 -1
  30. package/constants.js +0 -1
  31. package/package.json +1 -1
  32. package/tsconfig.build.tsbuildinfo +1 -1
  33. package/types/academics.d.ts +5 -2
@@ -188,7 +188,7 @@ export const ClassMoreActions = () => {
188
188
  showSuccessToast(t("messagesBulkSuccess"));
189
189
  }
190
190
  const schoolId = ((_f = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _f === void 0 ? void 0 : _f.id) || "";
191
- fetch(`${CLASS_API_ROUTES.LIST}?currentPage=1&pageLimit=${pageLimit}&schoolId=${schoolId}`, {
191
+ fetch(`${CLASS_API_ROUTES.UNIT}?currentPage=1&pageLimit=${pageLimit}&schoolId=${schoolId}`, {
192
192
  headers: {
193
193
  "Content-Type": "application/json",
194
194
  },
@@ -26,6 +26,8 @@ export declare const COURSE_ACTION_TYPES: {
26
26
  searchQuery: string;
27
27
  disableSaveButton: boolean;
28
28
  drawer: string | null;
29
+ classId: string;
30
+ classLabel: string;
29
31
  code: string;
30
32
  enabled: boolean;
31
33
  errors: Record<string, string>;
@@ -46,6 +48,8 @@ export declare const COURSE_ACTION_TYPES: {
46
48
  searchQuery: string;
47
49
  disableSaveButton: boolean;
48
50
  drawer: string | null;
51
+ classId: string;
52
+ classLabel: string;
49
53
  code: string;
50
54
  enabled: boolean;
51
55
  errors: Record<string, string>;
@@ -68,6 +72,8 @@ export declare const COURSE_ACTION_TYPES: {
68
72
  searchQuery: string;
69
73
  disableSaveButton: boolean;
70
74
  drawer: string | null;
75
+ classId: string;
76
+ classLabel: string;
71
77
  code: string;
72
78
  enabled: boolean;
73
79
  errors: Record<string, string>;
@@ -88,6 +94,8 @@ export declare const COURSE_ACTION_TYPES: {
88
94
  searchQuery: string;
89
95
  disableSaveButton: boolean;
90
96
  drawer: string | null;
97
+ classId: string;
98
+ classLabel: string;
91
99
  code: string;
92
100
  enabled: boolean;
93
101
  errors: Record<string, string>;
@@ -108,6 +116,8 @@ export declare const COURSE_ACTION_TYPES: {
108
116
  searchQuery: string;
109
117
  disableSaveButton: boolean;
110
118
  drawer: string | null;
119
+ classId: string;
120
+ classLabel: string;
111
121
  code: string;
112
122
  enabled: boolean;
113
123
  errors: Record<string, string>;
@@ -158,6 +168,8 @@ export declare const useCourseModule: () => {
158
168
  searchQuery: string;
159
169
  disableSaveButton: boolean;
160
170
  drawer: string | null;
171
+ classId: string;
172
+ classLabel: string;
161
173
  code: string;
162
174
  enabled: boolean;
163
175
  errors: Record<string, string>;
@@ -54,6 +54,8 @@ const courseConfig = {
54
54
  disableSaveButton: false,
55
55
  drawer: null,
56
56
  // Form State
57
+ classId: "",
58
+ classLabel: "",
57
59
  code: "",
58
60
  enabled: true,
59
61
  errors: {},
@@ -102,6 +104,7 @@ export const useCourseModule = () => {
102
104
  schoolId,
103
105
  ]);
104
106
  const updateParams = useMemo(() => ({
107
+ classId: state.classId,
105
108
  code: state.code,
106
109
  enabled: state.enabled,
107
110
  id: state.id,
@@ -172,7 +175,7 @@ export const useCourseModule = () => {
172
175
  }
173
176
  }, [resetFormAndCloseDrawer, showToast, t]);
174
177
  const byIdCallback = useCallback(({ data, error }) => {
175
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
178
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
176
179
  if (error) {
177
180
  showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
178
181
  return;
@@ -183,13 +186,26 @@ export const useCourseModule = () => {
183
186
  type: COURSE_ACTION_TYPES.SET_INPUT_FIELD,
184
187
  payload: { key: "id", value: course.id },
185
188
  });
189
+ dispatch({
190
+ type: COURSE_ACTION_TYPES.SET_INPUT_FIELD,
191
+ payload: { key: "classId", value: course.classId },
192
+ });
193
+ dispatch({
194
+ type: COURSE_ACTION_TYPES.SET_INPUT_FIELD,
195
+ payload: {
196
+ key: "classLabel",
197
+ value: ((_a = course.class) === null || _a === void 0 ? void 0 : _a.name) && ((_b = course.class) === null || _b === void 0 ? void 0 : _b.code)
198
+ ? `${course.class.name} (${course.class.code})`
199
+ : course.classId,
200
+ },
201
+ });
186
202
  dispatch({
187
203
  type: COURSE_ACTION_TYPES.SET_INPUT_FIELD,
188
204
  payload: { key: "code", value: course.code },
189
205
  });
190
206
  dispatch({
191
207
  type: COURSE_ACTION_TYPES.SET_INPUT_FIELD,
192
- payload: { key: "enabled", value: (_a = course.enabled) !== null && _a !== void 0 ? _a : true },
208
+ payload: { key: "enabled", value: (_c = course.enabled) !== null && _c !== void 0 ? _c : true },
193
209
  });
194
210
  dispatch({
195
211
  type: COURSE_ACTION_TYPES.SET_INPUT_FIELD,
@@ -203,9 +219,9 @@ export const useCourseModule = () => {
203
219
  type: COURSE_ACTION_TYPES.SET_INPUT_FIELD,
204
220
  payload: {
205
221
  key: "sectionLabel",
206
- value: ((_c = (_b = course.section) === null || _b === void 0 ? void 0 : _b.class) === null || _c === void 0 ? void 0 : _c.code) && ((_d = course.section) === null || _d === void 0 ? void 0 : _d.name)
222
+ value: ((_e = (_d = course.section) === null || _d === void 0 ? void 0 : _d.class) === null || _e === void 0 ? void 0 : _e.code) && ((_f = course.section) === null || _f === void 0 ? void 0 : _f.name)
207
223
  ? `${course.section.class.code}-${course.section.name}`
208
- : ((_e = course.section) === null || _e === void 0 ? void 0 : _e.name) || course.sectionId,
224
+ : ((_g = course.section) === null || _g === void 0 ? void 0 : _g.name) || course.sectionId,
209
225
  },
210
226
  });
211
227
  dispatch({
@@ -216,7 +232,7 @@ export const useCourseModule = () => {
216
232
  type: COURSE_ACTION_TYPES.SET_INPUT_FIELD,
217
233
  payload: {
218
234
  key: "subjectLabel",
219
- value: ((_f = course.subject) === null || _f === void 0 ? void 0 : _f.name) || course.subjectId,
235
+ value: ((_h = course.subject) === null || _h === void 0 ? void 0 : _h.name) || course.subjectId,
220
236
  },
221
237
  });
222
238
  dispatch({
@@ -227,8 +243,8 @@ export const useCourseModule = () => {
227
243
  type: COURSE_ACTION_TYPES.SET_INPUT_FIELD,
228
244
  payload: {
229
245
  key: "teacherLabel",
230
- value: `${((_g = course.teacher) === null || _g === void 0 ? void 0 : _g.firstName) || ""} ${((_h = course.teacher) === null || _h === void 0 ? void 0 : _h.lastName) || ""}`.trim() ||
231
- ((_j = course.teacher) === null || _j === void 0 ? void 0 : _j.teacherCode) ||
246
+ value: `${((_j = course.teacher) === null || _j === void 0 ? void 0 : _j.firstName) || ""} ${((_k = course.teacher) === null || _k === void 0 ? void 0 : _k.lastName) || ""}`.trim() ||
247
+ ((_l = course.teacher) === null || _l === void 0 ? void 0 : _l.teacherCode) ||
232
248
  course.teacherId,
233
249
  },
234
250
  });
@@ -10,7 +10,7 @@ import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
10
10
  import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
11
11
  import { useEnhancedCombobox } from "@appcorp/shadcn/hooks/use-enhanced-combobox";
12
12
  import { useCourseModule } from "./context";
13
- import { SECTION_API_ROUTES, SUBJECT_API_ROUTES, TEACHER_API_ROUTES, } from "../../constants";
13
+ import { CLASS_API_ROUTES, SECTION_API_ROUTES, SUBJECT_API_ROUTES, TEACHER_API_ROUTES, } from "../../constants";
14
14
  import { useTranslations } from "next-intl";
15
15
  import { useFetch } from "@react-pakistan/util-functions/hooks/use-fetch";
16
16
  import { API_METHODS } from "@react-pakistan/util-functions";
@@ -19,7 +19,11 @@ export const CourseForm = () => {
19
19
  const workspace = getCachedWorkspaceSync();
20
20
  const t = useTranslations("course");
21
21
  const { state, handleChange } = useCourseModule();
22
- const { code, enabled, errors, sectionId, subjectId, teacherId } = state;
22
+ const { classId, code, enabled, errors, sectionId, subjectId, teacherId } = state;
23
+ const { data: classes } = useFetch("/api/v1/class", {
24
+ method: API_METHODS.GET,
25
+ params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
26
+ });
23
27
  const { data: sections } = useFetch("/api/v1/sections", {
24
28
  method: API_METHODS.GET,
25
29
  params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
@@ -32,6 +36,33 @@ export const CourseForm = () => {
32
36
  method: API_METHODS.GET,
33
37
  params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
34
38
  });
39
+ const { enhancedComboboxElement: classIdCombo } = useEnhancedCombobox({
40
+ emptyText: t("formNoClassEmpty"),
41
+ id: "classId",
42
+ info: t("formClassInfo"),
43
+ label: t("formClassLabel"),
44
+ onValueChange: (value) => {
45
+ var _a;
46
+ handleChange("classId", value);
47
+ handleChange("classLabel", ((_a = classes === null || classes === void 0 ? void 0 : classes.find((c) => c.id === value)) === null || _a === void 0 ? void 0 : _a.name) || "");
48
+ },
49
+ options: classes === null || classes === void 0 ? void 0 : classes.map((c) => ({
50
+ value: c.id,
51
+ label: `${c.name} (${c.code})`,
52
+ })),
53
+ placeholder: t("formClassPlaceholder"),
54
+ required: true,
55
+ searchEndpoint: CLASS_API_ROUTES.UNIT,
56
+ searchPlaceholder: t("formSearchClassPlaceholder"),
57
+ formatSearchResult: (item) => {
58
+ var _a, _b;
59
+ return ({
60
+ label: String((_a = item.label) !== null && _a !== void 0 ? _a : ""),
61
+ value: String((_b = item.value) !== null && _b !== void 0 ? _b : ""),
62
+ });
63
+ },
64
+ value: classId,
65
+ });
35
66
  const { enhancedComboboxElement: sectionIdCombo } = useEnhancedCombobox({
36
67
  emptyText: t("formNoSectionEmpty"),
37
68
  id: "sectionId",
@@ -124,5 +155,5 @@ export const CourseForm = () => {
124
155
  },
125
156
  value: teacherId,
126
157
  });
127
- return (_jsxs("div", { className: "space-y-4", children: [_jsx(EnhancedInput, { error: errors.code, id: "code", info: t("formCourseCodeInfo"), label: t("formCourseCodeLabel"), onChange: (e) => handleChange("code", e.target.value), placeholder: t("formCourseCodePlaceholder"), required: true, value: code }), sectionIdCombo, subjectIdCombo, teacherIdCombo, _jsx(EnhancedCheckbox, { label: t("formActiveCourseLabel"), defaultChecked: enabled, onCheckedChange: (checked) => handleChange("enabled", checked), info: t("actionToggleEnableOrDisableCourse") })] }));
158
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(EnhancedInput, { error: errors.code, id: "code", info: t("formCourseCodeInfo"), label: t("formCourseCodeLabel"), onChange: (e) => handleChange("code", e.target.value), placeholder: t("formCourseCodePlaceholder"), required: true, value: code }), classIdCombo, sectionIdCombo, subjectIdCombo, teacherIdCombo, _jsx(EnhancedCheckbox, { label: t("formActiveCourseLabel"), defaultChecked: enabled, onCheckedChange: (checked) => handleChange("enabled", checked), info: t("actionToggleEnableOrDisableCourse") })] }));
128
159
  };
@@ -24,6 +24,7 @@ interface Props {
24
24
  drawerViewDescription: string;
25
25
  drawerViewTitle: string;
26
26
  labelActions: string;
27
+ labelClass: string;
27
28
  labelCode: string;
28
29
  labelEnabled: string;
29
30
  labelId: string;
@@ -29,6 +29,14 @@ import { RbacNoAccess } from "../../components/rbac-no-access";
29
29
  const tableBodyCols = [
30
30
  { componentType: COMPONENT_TYPE.ID, key: "id" },
31
31
  { componentType: COMPONENT_TYPE.TEXT, key: "code" },
32
+ {
33
+ componentType: COMPONENT_TYPE.TEXT,
34
+ key: "class",
35
+ textFormatter: (_, row) => {
36
+ const cls = row.class;
37
+ return cls ? `${cls.name} (${cls.code})` : "N/A";
38
+ },
39
+ },
32
40
  {
33
41
  componentType: COMPONENT_TYPE.TEXT,
34
42
  key: "section:name",
@@ -61,16 +69,17 @@ const createComponentInstances = () => ({
61
69
  moreActions: _jsx(CourseMoreActions, {}),
62
70
  view: _jsx(CourseView, {}),
63
71
  });
64
- const createCourseConfig = ({ cancelLabel, dispatch, drawerFilterDescription, drawerFilterTitle, drawerFormDescription, drawerFormTitle, drawerMoreActionsDescription, drawerMoreActionsTitle, drawerViewDescription, drawerViewTitle, labelActions, labelCode, labelEnabled, labelId, labelSection, labelSubject, labelTeacher, saveLabel, searchPlaceholder, tableDescription, tableTitle, }) => {
72
+ const createCourseConfig = ({ cancelLabel, dispatch, drawerFilterDescription, drawerFilterTitle, drawerFormDescription, drawerFormTitle, drawerMoreActionsDescription, drawerMoreActionsTitle, drawerViewDescription, drawerViewTitle, labelActions, labelClass, labelCode, labelEnabled, labelId, labelSection, labelSubject, labelTeacher, saveLabel, searchPlaceholder, tableDescription, tableTitle, }) => {
65
73
  const components = createComponentInstances();
66
74
  return {
67
75
  moduleName: "course",
68
76
  tableColumns: [
69
77
  { label: labelId, width: "5%" },
70
- { label: labelCode, width: "20%" },
71
- { label: labelSection, width: "20%" },
72
- { label: labelSubject, width: "20%" },
73
- { label: labelTeacher, width: "20%" },
78
+ { label: labelCode, width: "15%" },
79
+ { label: labelClass, width: "15%" },
80
+ { label: labelSection, width: "15%" },
81
+ { label: labelSubject, width: "15%" },
82
+ { label: labelTeacher, width: "15%" },
74
83
  { label: labelEnabled, width: "10%" },
75
84
  { label: labelActions, width: "5%" },
76
85
  ],
@@ -114,6 +123,7 @@ const CoursePageInner = (props) => {
114
123
  drawerMoreActionsTitle: props.drawerMoreActionsTitle,
115
124
  drawerMoreActionsDescription: props.drawerMoreActionsDescription,
116
125
  labelActions: props.labelActions,
126
+ labelClass: props.labelClass,
117
127
  labelCode: props.labelCode,
118
128
  labelEnabled: props.labelEnabled,
119
129
  labelId: props.labelId,
@@ -136,6 +146,7 @@ const CoursePageInner = (props) => {
136
146
  props.drawerMoreActionsTitle,
137
147
  props.drawerMoreActionsDescription,
138
148
  props.labelActions,
149
+ props.labelClass,
139
150
  props.labelCode,
140
151
  props.labelEnabled,
141
152
  props.labelId,
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { z } from "zod";
7
7
  export declare const courseFormValidation: z.ZodObject<{
8
+ classId: z.ZodString;
8
9
  code: z.ZodString;
9
10
  sectionId: z.ZodString;
10
11
  subjectId: z.ZodString;
@@ -8,6 +8,7 @@ import { z } from "zod";
8
8
  // VALIDATION SCHEMA
9
9
  // ============================================================================
10
10
  export const courseFormValidation = z.object({
11
+ classId: z.string().min(1, "Class is required"),
11
12
  code: z.string().min(1, "Course code is required"),
12
13
  sectionId: z.string().min(1, "Section is required"),
13
14
  subjectId: z.string().min(1, "Subject is required"),
@@ -10,6 +10,7 @@ import { Badge } from "@appcorp/shadcn/components/ui/badge";
10
10
  import { Separator } from "@appcorp/shadcn/components/ui/separator";
11
11
  import { BookMarked, CheckCircle2, XCircle } from "lucide-react";
12
12
  import { useCourseModule } from "./context";
13
+ import { getCachedClassesSync } from "../class/cache";
13
14
  import { getCachedSectionsSync } from "../section/cache";
14
15
  import { getCachedSubjectsSync } from "../subject/cache";
15
16
  import { getCachedTeachersSync } from "../teacher/cache";
@@ -19,10 +20,13 @@ export const CourseView = () => {
19
20
  var _a, _b, _c, _d, _e;
20
21
  const t = useTranslations("course");
21
22
  const { state } = useCourseModule();
22
- const { code, enabled, sectionId, subjectId, teacherId } = state;
23
+ const { classId, code, enabled, sectionId, subjectId, teacherId } = state;
24
+ const classes = getCachedClassesSync().items;
23
25
  const sections = getCachedSectionsSync().items;
24
26
  const subjects = getCachedSubjectsSync().items;
25
27
  const teachers = getCachedTeachersSync().items;
28
+ const cls = classes.find((c) => c.id === classId);
29
+ const className = cls ? `${cls.name} (${cls.code})` : (classId !== null && classId !== void 0 ? classId : "—");
26
30
  const section = sections.find((s) => s.id === sectionId);
27
31
  const sectionName = section
28
32
  ? ((_a = section.class) === null || _a === void 0 ? void 0 : _a.code)
@@ -36,7 +40,7 @@ export const CourseView = () => {
36
40
  teacher.teacherCode ||
37
41
  "—"
38
42
  : "—";
39
- 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: [_jsx("div", { className: "bg-primary/10 flex h-24 w-24 items-center justify-center rounded-full", children: _jsx(BookMarked, { className: "text-primary h-12 w-12" }) }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("h2", { className: "text-2xl font-bold", children: formatValue(code) }), enabled ? (_jsx(CheckCircle2, { className: "h-5 w-5 text-green-500" })) : (_jsx(XCircle, { className: "h-5 w-5 text-red-500" }))] }), _jsx("p", { className: "text-muted-foreground mt-1", children: sectionName })] })] }) }) }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(BookMarked, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionCourseDetails") })] }), _jsx(CardDescription, { children: t("viewSectionCompleteCourseInformation") })] }), _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-muted-foreground text-sm font-medium", children: t("viewFieldCourseCode") }), _jsx("p", { className: "text-base", children: formatValue(code) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("section") }), _jsx("p", { className: "text-base", children: sectionName })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldSubject") }), _jsx("p", { className: "text-base", children: subjectName })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldTeacher") }), _jsx("p", { className: "text-base", children: teacherName })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldStatus") }), _jsx(Badge, { variant: enabled ? "default" : "secondary", children: enabled
43
+ 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: [_jsx("div", { className: "bg-primary/10 flex h-24 w-24 items-center justify-center rounded-full", children: _jsx(BookMarked, { className: "text-primary h-12 w-12" }) }), _jsxs("div", { className: "flex-1", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("h2", { className: "text-2xl font-bold", children: formatValue(code) }), enabled ? (_jsx(CheckCircle2, { className: "h-5 w-5 text-green-500" })) : (_jsx(XCircle, { className: "h-5 w-5 text-red-500" }))] }), _jsxs("p", { className: "text-muted-foreground mt-1", children: [className, " \u2014 ", sectionName] })] })] }) }) }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(BookMarked, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionCourseDetails") })] }), _jsx(CardDescription, { children: t("viewSectionCompleteCourseInformation") })] }), _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-muted-foreground text-sm font-medium", children: t("viewFieldCourseCode") }), _jsx("p", { className: "text-base", children: formatValue(code) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("labelClass") }), _jsx("p", { className: "text-base", children: className })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("section") }), _jsx("p", { className: "text-base", children: sectionName })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldSubject") }), _jsx("p", { className: "text-base", children: subjectName })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldTeacher") }), _jsx("p", { className: "text-base", children: teacherName })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldStatus") }), _jsx(Badge, { variant: enabled ? "default" : "secondary", children: enabled
40
44
  ? t("viewFieldStatusActive")
41
45
  : t("viewFieldStatusInactive") })] })] }) })] })] }));
42
46
  };
@@ -1,5 +1,5 @@
1
1
  import { type RowAction, type TableRow } from "@appcorp/shadcn/components/enhanced-table";
2
- import { EnrollmentBE, SectionBE, StudentProfileBE } from "../../type";
2
+ import { ClassBE, EnrollmentBE, SectionBE, StudentProfileBE } from "../../type";
3
3
  export declare const ENROLLMENT_DRAWER: {
4
4
  readonly FILTER_DRAWER: string;
5
5
  readonly FORM_DRAWER: string;
@@ -26,6 +26,7 @@ export declare const ENROLLMENT_ACTION_TYPES: {
26
26
  searchQuery: string;
27
27
  disableSaveButton: boolean;
28
28
  drawer: string | null;
29
+ classId: string;
29
30
  enabled: boolean;
30
31
  enrollmentDate: string;
31
32
  errors: Record<string, string>;
@@ -33,6 +34,7 @@ export declare const ENROLLMENT_ACTION_TYPES: {
33
34
  id: string;
34
35
  sectionId: string;
35
36
  studentProfileId: string;
37
+ class: ClassBE | undefined;
36
38
  section: SectionBE | undefined;
37
39
  studentProfile: StudentProfileBE | undefined;
38
40
  }>, initialEnrollmentState: {
@@ -43,6 +45,7 @@ export declare const ENROLLMENT_ACTION_TYPES: {
43
45
  searchQuery: string;
44
46
  disableSaveButton: boolean;
45
47
  drawer: string | null;
48
+ classId: string;
46
49
  enabled: boolean;
47
50
  enrollmentDate: string;
48
51
  errors: Record<string, string>;
@@ -50,6 +53,7 @@ export declare const ENROLLMENT_ACTION_TYPES: {
50
53
  id: string;
51
54
  sectionId: string;
52
55
  studentProfileId: string;
56
+ class: ClassBE | undefined;
53
57
  section: SectionBE | undefined;
54
58
  studentProfile: StudentProfileBE | undefined;
55
59
  }, EnrollmentProvider: import("react").FC<{
@@ -62,6 +66,7 @@ export declare const ENROLLMENT_ACTION_TYPES: {
62
66
  searchQuery: string;
63
67
  disableSaveButton: boolean;
64
68
  drawer: string | null;
69
+ classId: string;
65
70
  enabled: boolean;
66
71
  enrollmentDate: string;
67
72
  errors: Record<string, string>;
@@ -69,6 +74,7 @@ export declare const ENROLLMENT_ACTION_TYPES: {
69
74
  id: string;
70
75
  sectionId: string;
71
76
  studentProfileId: string;
77
+ class: ClassBE | undefined;
72
78
  section: SectionBE | undefined;
73
79
  studentProfile: StudentProfileBE | undefined;
74
80
  }, action: any) => {
@@ -79,6 +85,7 @@ export declare const ENROLLMENT_ACTION_TYPES: {
79
85
  searchQuery: string;
80
86
  disableSaveButton: boolean;
81
87
  drawer: string | null;
88
+ classId: string;
82
89
  enabled: boolean;
83
90
  enrollmentDate: string;
84
91
  errors: Record<string, string>;
@@ -86,6 +93,7 @@ export declare const ENROLLMENT_ACTION_TYPES: {
86
93
  id: string;
87
94
  sectionId: string;
88
95
  studentProfileId: string;
96
+ class: ClassBE | undefined;
89
97
  section: SectionBE | undefined;
90
98
  studentProfile: StudentProfileBE | undefined;
91
99
  }, useEnrollmentContext: () => import("@react-pakistan/util-functions/factory/generic-module-factory").GenericModuleContextWithHandlers<{
@@ -96,6 +104,7 @@ export declare const ENROLLMENT_ACTION_TYPES: {
96
104
  searchQuery: string;
97
105
  disableSaveButton: boolean;
98
106
  drawer: string | null;
107
+ classId: string;
99
108
  enabled: boolean;
100
109
  enrollmentDate: string;
101
110
  errors: Record<string, string>;
@@ -103,6 +112,7 @@ export declare const ENROLLMENT_ACTION_TYPES: {
103
112
  id: string;
104
113
  sectionId: string;
105
114
  studentProfileId: string;
115
+ class: ClassBE | undefined;
106
116
  section: SectionBE | undefined;
107
117
  studentProfile: StudentProfileBE | undefined;
108
118
  }>;
@@ -143,6 +153,7 @@ export declare const useEnrollmentModule: () => {
143
153
  searchQuery: string;
144
154
  disableSaveButton: boolean;
145
155
  drawer: string | null;
156
+ classId: string;
146
157
  enabled: boolean;
147
158
  enrollmentDate: string;
148
159
  errors: Record<string, string>;
@@ -150,6 +161,7 @@ export declare const useEnrollmentModule: () => {
150
161
  id: string;
151
162
  sectionId: string;
152
163
  studentProfileId: string;
164
+ class: ClassBE | undefined;
153
165
  section: SectionBE | undefined;
154
166
  studentProfile: StudentProfileBE | undefined;
155
167
  };
@@ -54,6 +54,7 @@ const enrollmentConfig = {
54
54
  disableSaveButton: false,
55
55
  drawer: null,
56
56
  // Form State
57
+ classId: "",
57
58
  enabled: true,
58
59
  enrollmentDate: new Date().toISOString().split("T")[0],
59
60
  errors: {},
@@ -62,6 +63,7 @@ const enrollmentConfig = {
62
63
  sectionId: "",
63
64
  studentProfileId: "",
64
65
  // Relations (populated from byId fetch)
66
+ class: undefined,
65
67
  section: undefined,
66
68
  studentProfile: undefined,
67
69
  },
@@ -100,6 +102,7 @@ export const useEnrollmentModule = () => {
100
102
  debouncedQuery,
101
103
  ]);
102
104
  const updateParams = useMemo(() => ({
105
+ classId: state.classId,
103
106
  enabled: state.enabled,
104
107
  enrollmentDate: state.enrollmentDate,
105
108
  id: state.id,
@@ -15,7 +15,7 @@ import { useEnhancedCombobox } from "@appcorp/shadcn/hooks/use-enhanced-combobox
15
15
  import { Separator } from "@appcorp/shadcn/components/ui/separator";
16
16
  import { API_METHODS, DATE_FORMATS, formatDate, } from "@react-pakistan/util-functions";
17
17
  import { useEnrollmentModule } from "./context";
18
- import { SECTION_API_ROUTES, STUDENT_PROFILE_API_ROUTES, } from "../../constants";
18
+ import { CLASS_API_ROUTES, SECTION_API_ROUTES, STUDENT_PROFILE_API_ROUTES, } from "../../constants";
19
19
  import { useTranslations } from "next-intl";
20
20
  import { useFetch } from "@react-pakistan/util-functions/hooks/use-fetch";
21
21
  import { useEffect } from "react";
@@ -24,13 +24,17 @@ import { getCachedWorkspaceSync } from "../workspace/cache";
24
24
  // COMPONENT
25
25
  // ============================================================================
26
26
  export const EnrollmentForm = () => {
27
- const { state: { enabled, enrollmentDate, errors, sectionId, studentProfileId }, handleChange, } = useEnrollmentModule();
27
+ const { state: { classId, enabled, enrollmentDate, errors, sectionId, studentProfileId }, handleChange, } = useEnrollmentModule();
28
28
  const workspace = getCachedWorkspaceSync();
29
29
  const t = useTranslations("enrollment");
30
30
  const { fetchNow: studentProfileFetchNow, data: studentProfileData } = useFetch(STUDENT_PROFILE_API_ROUTES.UNIT, {
31
31
  method: API_METHODS.GET,
32
32
  params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
33
33
  });
34
+ const { fetchNow: classFetchNow, data: classData } = useFetch(CLASS_API_ROUTES.UNIT, {
35
+ method: API_METHODS.GET,
36
+ params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
37
+ });
34
38
  const { fetchNow: sectionFetchNow, data: sectionData } = useFetch(SECTION_API_ROUTES.UNIT, {
35
39
  method: API_METHODS.GET,
36
40
  params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
@@ -38,6 +42,7 @@ export const EnrollmentForm = () => {
38
42
  useEffect(() => {
39
43
  if (workspace === null || workspace === void 0 ? void 0 : workspace.id) {
40
44
  studentProfileFetchNow();
45
+ classFetchNow();
41
46
  sectionFetchNow();
42
47
  }
43
48
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -69,6 +74,29 @@ export const EnrollmentForm = () => {
69
74
  },
70
75
  value: studentProfileId || "",
71
76
  });
77
+ const { enhancedComboboxElement: classIdCombo } = useEnhancedCombobox({
78
+ emptyText: t("formNoClassEmpty"),
79
+ id: "classId",
80
+ info: t("formClassInfo"),
81
+ label: t("formClassLabel"),
82
+ onValueChange: (value) => handleChange("classId", value),
83
+ options: ((classData === null || classData === void 0 ? void 0 : classData.items) || []).map((c) => ({
84
+ value: c.id,
85
+ label: `${c.name} (${c.code})`,
86
+ })),
87
+ placeholder: t("formClassPlaceholder"),
88
+ required: true,
89
+ searchEndpoint: CLASS_API_ROUTES.UNIT,
90
+ searchPlaceholder: t("formSearchClassPlaceholder"),
91
+ formatSearchResult: (item) => {
92
+ const cls = Object.assign({}, item);
93
+ return {
94
+ label: `${cls.name} (${cls.code})`,
95
+ value: cls.id,
96
+ };
97
+ },
98
+ value: classId || "",
99
+ });
72
100
  const { enhancedComboboxElement: sectionIdCombo } = useEnhancedCombobox({
73
101
  emptyText: t("formNoSectionEmpty"),
74
102
  id: "sectionId",
@@ -98,5 +126,5 @@ export const EnrollmentForm = () => {
98
126
  });
99
127
  return (_jsxs("div", { className: "space-y-4", children: [_jsx(EnhancedInput, { error: errors.enrollmentDate, id: "enrollmentDate", info: t("formEnrollmentDateInfo"), label: t("formEnrollmentDateLabel"), onChange: (e) => handleChange("enrollmentDate", e.target.value), placeholder: t("formEnrollmentDatePlaceholder"), required: true, type: "date", value: enrollmentDate
100
128
  ? formatDate(enrollmentDate, DATE_FORMATS.YYYY_MM_DD)
101
- : "" }), _jsx(Separator, {}), studentProfileIdCombo, sectionIdCombo, _jsx(EnhancedCheckbox, { checked: enabled, error: errors.enabled, id: "enabled", info: t("actionToggleEnableOrDisableEnrollment"), label: t("formActiveEnrollmentLabel"), onCheckedChange: (checked) => handleChange("enabled", checked) })] }));
129
+ : "" }), _jsx(Separator, {}), studentProfileIdCombo, classIdCombo, sectionIdCombo, _jsx(EnhancedCheckbox, { checked: enabled, error: errors.enabled, id: "enabled", info: t("actionToggleEnableOrDisableEnrollment"), label: t("formActiveEnrollmentLabel"), onCheckedChange: (checked) => handleChange("enabled", checked) })] }));
102
130
  };
@@ -91,7 +91,7 @@ export const EnrollmentMoreActions = () => {
91
91
  };
92
92
  }, []);
93
93
  const handleBulkFlow = useCallback(async (files, method) => {
94
- var _a, _b, _c, _d, _e, _f, _g, _h;
94
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
95
95
  const closeDrawer = () => {
96
96
  dispatch({
97
97
  type: ENROLLMENT_ACTION_TYPES.SET_DRAWER,
@@ -120,13 +120,15 @@ export const EnrollmentMoreActions = () => {
120
120
  if (method === "POST") {
121
121
  if (!((_b = row.studentProfileId) === null || _b === void 0 ? void 0 : _b.trim()))
122
122
  msgs.push(t("validationRequiredStudentProfileId"));
123
- if (!((_c = row.sectionId) === null || _c === void 0 ? void 0 : _c.trim()))
123
+ if (!((_c = row.classId) === null || _c === void 0 ? void 0 : _c.trim()))
124
+ msgs.push(t("validationRequiredClassId"));
125
+ if (!((_d = row.sectionId) === null || _d === void 0 ? void 0 : _d.trim()))
124
126
  msgs.push(t("validationRequiredSectionId"));
125
- if (!((_d = row.enrollmentDate) === null || _d === void 0 ? void 0 : _d.trim()))
127
+ if (!((_e = row.enrollmentDate) === null || _e === void 0 ? void 0 : _e.trim()))
126
128
  msgs.push(t("validationRequiredEnrollmentDate"));
127
129
  }
128
130
  else {
129
- if (!((_e = row.id) === null || _e === void 0 ? void 0 : _e.trim()))
131
+ if (!((_f = row.id) === null || _f === void 0 ? void 0 : _f.trim()))
130
132
  msgs.push(t("validationRequiredIdForUpdate"));
131
133
  }
132
134
  if (msgs.length > 0) {
@@ -169,7 +171,7 @@ export const EnrollmentMoreActions = () => {
169
171
  return;
170
172
  if (status.status === "completed") {
171
173
  const r = status.results;
172
- if (r && ((_f = r.errors) === null || _f === void 0 ? void 0 : _f.length) > 0) {
174
+ if (r && ((_g = r.errors) === null || _g === void 0 ? void 0 : _g.length) > 0) {
173
175
  const summary = formatErrorSummary(t, r.errors);
174
176
  showSuccessToast(t("messagesBulkResults", {
175
177
  created: r.created,
@@ -189,7 +191,7 @@ export const EnrollmentMoreActions = () => {
189
191
  else {
190
192
  showSuccessToast(t("messagesBulkSuccess"));
191
193
  }
192
- const schoolId = ((_g = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _g === void 0 ? void 0 : _g.id) || "";
194
+ const schoolId = ((_h = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _h === void 0 ? void 0 : _h.id) || "";
193
195
  fetch(`${ENROLLMENT_API_ROUTES.LIST}?currentPage=1&pageLimit=${pageLimit}&schoolId=${schoolId}`, {
194
196
  headers: {
195
197
  "Content-Type": "application/json",
@@ -213,7 +215,7 @@ export const EnrollmentMoreActions = () => {
213
215
  }
214
216
  else {
215
217
  const r = status.results;
216
- const detail = ((_h = r === null || r === void 0 ? void 0 : r.errors) === null || _h === void 0 ? void 0 : _h.length)
218
+ const detail = ((_j = r === null || r === void 0 ? void 0 : r.errors) === null || _j === void 0 ? void 0 : _j.length)
217
219
  ? formatErrorSummary(t, r.errors)
218
220
  : t("unknownError");
219
221
  showErrorToast(t("messagesBulkFailed", { action: label }) + "\n" + detail);
@@ -24,6 +24,7 @@ interface Props {
24
24
  drawerViewDescription: string;
25
25
  drawerViewTitle: string;
26
26
  labelActions: string;
27
+ labelClass: string;
27
28
  labelEnabled: string;
28
29
  labelEnrollmentDate: string;
29
30
  labelId: string;
@@ -34,6 +34,14 @@ const tableBodyCols = [
34
34
  key: "studentProfile",
35
35
  textFormatter: (_, row) => { var _a, _b; return (_b = (_a = row.studentProfile) === null || _a === void 0 ? void 0 : _a.studentCode) !== null && _b !== void 0 ? _b : "N/A"; },
36
36
  },
37
+ {
38
+ componentType: COMPONENT_TYPE.TEXT,
39
+ key: "class",
40
+ textFormatter: (_, row) => {
41
+ const cls = row.class;
42
+ return cls ? `${cls.name} (${cls.code})` : "N/A";
43
+ },
44
+ },
37
45
  {
38
46
  componentType: COMPONENT_TYPE.TEXT,
39
47
  key: "section",
@@ -64,16 +72,17 @@ const createComponentInstances = () => ({
64
72
  moreActions: _jsx(EnrollmentMoreActions, {}),
65
73
  view: _jsx(EnrollmentView, {}),
66
74
  });
67
- const createEnrollmentConfig = ({ cancelLabel, dispatch, drawerFilterDescription, drawerFilterTitle, drawerFormDescription, drawerFormTitle, drawerMoreActionsDescription, drawerMoreActionsTitle, drawerViewDescription, drawerViewTitle, labelActions, labelEnabled, labelEnrollmentDate, labelId, labelSection, labelStudent, saveLabel, searchPlaceholder, tableDescription, tableTitle, }) => {
75
+ const createEnrollmentConfig = ({ cancelLabel, dispatch, drawerFilterDescription, drawerFilterTitle, drawerFormDescription, drawerFormTitle, drawerMoreActionsDescription, drawerMoreActionsTitle, drawerViewDescription, drawerViewTitle, labelActions, labelClass, labelEnabled, labelEnrollmentDate, labelId, labelSection, labelStudent, saveLabel, searchPlaceholder, tableDescription, tableTitle, }) => {
68
76
  const components = createComponentInstances();
69
77
  return {
70
78
  moduleName: "enrollment",
71
79
  tableColumns: [
72
80
  { label: labelId, width: "5%" },
73
- { label: labelStudent, width: "25%" },
74
- { label: labelSection, width: "25%" },
81
+ { label: labelStudent, width: "20%" },
82
+ { label: labelClass, width: "15%" },
83
+ { label: labelSection, width: "20%" },
75
84
  { label: labelEnrollmentDate, width: "20%" },
76
- { label: labelEnabled, width: "15%" },
85
+ { label: labelEnabled, width: "10%" },
77
86
  { label: labelActions, width: "5%" },
78
87
  ],
79
88
  cancelLabel,
@@ -116,6 +125,7 @@ const EnrollmentPageInner = (props) => {
116
125
  drawerMoreActionsTitle: props.drawerMoreActionsTitle,
117
126
  drawerMoreActionsDescription: props.drawerMoreActionsDescription,
118
127
  labelActions: props.labelActions,
128
+ labelClass: props.labelClass,
119
129
  labelEnabled: props.labelEnabled,
120
130
  labelEnrollmentDate: props.labelEnrollmentDate,
121
131
  labelId: props.labelId,
@@ -137,6 +147,7 @@ const EnrollmentPageInner = (props) => {
137
147
  props.drawerMoreActionsTitle,
138
148
  props.drawerMoreActionsDescription,
139
149
  props.labelActions,
150
+ props.labelClass,
140
151
  props.labelEnabled,
141
152
  props.labelEnrollmentDate,
142
153
  props.labelId,