@appcorp/fusion-storybook 0.2.40 → 0.2.42

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 (98) hide show
  1. package/base-modules/admission/constants.d.ts +5 -17
  2. package/base-modules/admission/constants.js +12 -7
  3. package/base-modules/admission/context/use-admission-module.js +11 -48
  4. package/base-modules/admission/filter.js +23 -3
  5. package/base-modules/admission/form.js +49 -19
  6. package/base-modules/attendance/context.js +3 -37
  7. package/base-modules/attendance/form.js +26 -10
  8. package/base-modules/attendance/more-actions.js +34 -25
  9. package/base-modules/campus/context.js +7 -7
  10. package/base-modules/class/cache.js +0 -1
  11. package/base-modules/class/context.js +10 -48
  12. package/base-modules/class/more-actions.js +0 -2
  13. package/base-modules/course/context.js +3 -37
  14. package/base-modules/course/form.js +91 -292
  15. package/base-modules/discount-code/constants.d.ts +5 -0
  16. package/base-modules/discount-code/constants.js +5 -0
  17. package/base-modules/discount-code/context.d.ts +1 -0
  18. package/base-modules/discount-code/context.js +40 -39
  19. package/base-modules/discount-code/form.js +21 -15
  20. package/base-modules/discount-code/more-actions.js +1 -1
  21. package/base-modules/enrollment/context.js +3 -37
  22. package/base-modules/enrollment/form.js +38 -11
  23. package/base-modules/enrollment/more-actions.js +0 -2
  24. package/base-modules/expense/constants.js +1 -1
  25. package/base-modules/expense/context.js +5 -32
  26. package/base-modules/expense/filter.js +50 -3
  27. package/base-modules/expense/form.js +82 -6
  28. package/base-modules/family/context.js +7 -38
  29. package/base-modules/family-member/context.js +7 -39
  30. package/base-modules/fee-structure/context.js +1 -25
  31. package/base-modules/fee-structure/form.js +77 -89
  32. package/base-modules/fee-structure/more-actions.js +0 -2
  33. package/base-modules/rbac/context.d.ts +1 -0
  34. package/base-modules/rbac/context.js +23 -32
  35. package/base-modules/school/context.js +1 -1
  36. package/base-modules/school/form.js +34 -14
  37. package/base-modules/section/context.d.ts +1 -0
  38. package/base-modules/section/context.js +40 -47
  39. package/base-modules/section/form.js +25 -80
  40. package/base-modules/section/more-actions.js +0 -2
  41. package/base-modules/section/view.js +9 -7
  42. package/base-modules/student-fee/context/use-student-fee-module.d.ts +1 -0
  43. package/base-modules/student-fee/context/use-student-fee-module.js +48 -32
  44. package/base-modules/student-fee/context.d.ts +1 -1
  45. package/base-modules/student-fee/context.js +1 -1
  46. package/base-modules/student-fee/filter.js +23 -3
  47. package/base-modules/student-fee/form.js +93 -174
  48. package/base-modules/student-fee/view.d.ts +7 -1
  49. package/base-modules/student-fee/view.js +17 -20
  50. package/base-modules/student-profile/constants.d.ts +0 -6
  51. package/base-modules/student-profile/constants.js +1 -3
  52. package/base-modules/student-profile/context/use-student-profile-module.d.ts +1 -0
  53. package/base-modules/student-profile/context/use-student-profile-module.js +62 -55
  54. package/base-modules/student-profile/context.d.ts +1 -1
  55. package/base-modules/student-profile/context.js +1 -1
  56. package/base-modules/student-profile/filter.js +23 -3
  57. package/base-modules/student-profile/form.js +35 -3
  58. package/base-modules/subject/context.d.ts +1 -0
  59. package/base-modules/subject/context.js +38 -47
  60. package/base-modules/subject/more-actions.js +0 -2
  61. package/base-modules/teacher/constants.d.ts +0 -6
  62. package/base-modules/teacher/constants.js +0 -2
  63. package/base-modules/teacher/context.d.ts +1 -0
  64. package/base-modules/teacher/context.js +58 -39
  65. package/base-modules/teacher/form.js +46 -11
  66. package/base-modules/teacher/more-actions.js +0 -2
  67. package/base-modules/user/context/use-user-module.d.ts +1 -0
  68. package/base-modules/user/context/use-user-module.js +36 -32
  69. package/base-modules/user/context.js +1 -1
  70. package/base-modules/user/filter.js +6 -4
  71. package/base-modules/user/form.js +29 -5
  72. package/base-modules/user/more-actions.js +9 -7
  73. package/base-modules/user/view.js +3 -1
  74. package/base-modules/workspace/form.js +18 -8
  75. package/base-modules/workspace-user/context.d.ts +2 -1
  76. package/base-modules/workspace-user/context.js +31 -29
  77. package/package.json +1 -1
  78. package/tsconfig.build.tsbuildinfo +1 -1
  79. package/base-modules/admission/cache.d.ts +0 -14
  80. package/base-modules/admission/cache.js +0 -31
  81. package/base-modules/attendance/cache.d.ts +0 -14
  82. package/base-modules/attendance/cache.js +0 -31
  83. package/base-modules/course/cache.d.ts +0 -14
  84. package/base-modules/course/cache.js +0 -31
  85. package/base-modules/enrollment/cache.d.ts +0 -14
  86. package/base-modules/enrollment/cache.js +0 -31
  87. package/base-modules/expense/cache.d.ts +0 -14
  88. package/base-modules/expense/cache.js +0 -31
  89. package/base-modules/family/cache.d.ts +0 -14
  90. package/base-modules/family/cache.js +0 -31
  91. package/base-modules/family-member/cache.d.ts +0 -14
  92. package/base-modules/family-member/cache.js +0 -31
  93. package/base-modules/rbac/cache.d.ts +0 -27
  94. package/base-modules/rbac/cache.js +0 -46
  95. package/base-modules/student-fee/cache.d.ts +0 -15
  96. package/base-modules/student-fee/cache.js +0 -21
  97. package/base-modules/workspace-user/cache.d.ts +0 -14
  98. package/base-modules/workspace-user/cache.js +0 -31
@@ -9,195 +9,114 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
10
10
  import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
11
11
  import { EnhancedTextarea } from "@appcorp/shadcn/components/enhanced-textarea";
12
- import { EnhancedCombobox } from "@appcorp/shadcn/components/enhanced-combobox";
13
- import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
14
- import { useEffect, useMemo, useState } from "react";
12
+ import { useEnhancedCombobox } from "@appcorp/shadcn/hooks/use-enhanced-combobox";
13
+ import { useMemo } from "react";
15
14
  import { useStudentFeeModule } from "./context";
16
- import { PAYMENT_STATUS_OPTIONS } from "./constants";
17
- import { getCachedStudentProfiles, getCachedStudentProfilesSync, } from "../student-profile/cache";
18
- import { getCachedFeeStructures, getCachedFeeStructuresSync, } from "../fee-structure/cache";
19
- import { getCachedDiscountCodesSync } from "../discount-code/cache";
15
+ import { PAYMENT_STATUS_OPTIONS, STUDENT_FEE_API_ROUTES } from "./constants";
20
16
  import { getCachedWorkspaceSync } from "../workspace/cache";
21
- import { DATE_FORMATS, formatDate } from "@react-pakistan/util-functions";
22
- import { DISCOUNT_TYPE } from "../../type";
17
+ import { API_METHODS, DATE_FORMATS, formatDate, } from "@react-pakistan/util-functions";
18
+ import { DISCOUNT_TYPE, } from "../../type";
23
19
  import { useTranslations } from "next-intl";
20
+ import { useFetch } from "@react-pakistan/util-functions/hooks/use-fetch";
24
21
  export const StudentFeeForm = () => {
25
- var _a, _b, _c;
22
+ var _a, _b;
26
23
  const { state, handleChange } = useStudentFeeModule();
27
24
  const { amount, amountDue, amountPaid, discountAmount, discountCodeId, dueDate, enabled, errors, familyId, feeStructureId, remarks, status, studentProfileId, } = state;
28
25
  const workspace = getCachedWorkspaceSync();
29
26
  const currency = (_b = (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.currency) !== null && _b !== void 0 ? _b : "";
30
- const schoolId = ((_c = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _c === void 0 ? void 0 : _c.id) || "";
31
27
  const t = useTranslations("studentFee");
32
- const cachedStudentProfiles = getCachedStudentProfilesSync();
33
- const [studentSearchQuery, setStudentSearchQuery] = useState("");
34
- const [remoteStudentOptions, setRemoteStudentOptions] = useState(() => cachedStudentProfiles.items.map((s) => {
35
- var _a, _b;
36
- return ({
37
- label: `${s.computerNumber} - ${(_a = s.familyMember) === null || _a === void 0 ? void 0 : _a.firstName} ${(_b = s.familyMember) === null || _b === void 0 ? void 0 : _b.lastName}` ||
38
- s.id,
39
- value: s.id,
40
- });
41
- }));
42
- const [studentOptionsLoading, setStudentOptionsLoading] = useState(false);
43
- const debouncedStudentSearchQuery = useDebounce(studentSearchQuery, 300);
44
- const trimmedStudentSearchQuery = debouncedStudentSearchQuery.trim();
45
- const cachedStudentOptions = useMemo(() => cachedStudentProfiles.items
46
- .filter((s) => {
28
+ const paymentStatusLabelMap = {
29
+ PENDING: t("formOptionPending"),
30
+ PARTIAL: t("formOptionPartial"),
31
+ PAID: t("formOptionPaid"),
32
+ OVERDUE: t("formOptionOverdue"),
33
+ CANCELLED: t("formOptionCancelled"),
34
+ REFUNDED: t("formOptionRefunded"),
35
+ };
36
+ const { data: studentProfiles } = useFetch("/api/v1/student-profile", {
37
+ params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
38
+ method: API_METHODS.GET,
39
+ });
40
+ const { data: feeStructures } = useFetch("/api/v1/fee-structure", {
41
+ params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
42
+ method: API_METHODS.GET,
43
+ });
44
+ const { data: discountCodes } = useFetch("/api/v1/discount-code", {
45
+ params: { workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
46
+ method: API_METHODS.GET,
47
+ });
48
+ const filteredStudentOptions = useMemo(() => studentProfiles === null || studentProfiles === void 0 ? void 0 : studentProfiles.filter((s) => {
47
49
  var _a;
48
50
  if (!familyId)
49
51
  return true;
50
52
  return ((_a = s.familyMember) === null || _a === void 0 ? void 0 : _a.familyId) === familyId;
51
- })
52
- .map((s) => {
53
+ }).map((s) => {
53
54
  var _a, _b;
54
55
  return ({
55
- label: `${s.computerNumber} - ${(_a = s.familyMember) === null || _a === void 0 ? void 0 : _a.firstName} ${(_b = s.familyMember) === null || _b === void 0 ? void 0 : _b.lastName}` ||
56
+ id: s.id,
57
+ name: `${s.computerNumber} - ${(_a = s.familyMember) === null || _a === void 0 ? void 0 : _a.firstName} ${(_b = s.familyMember) === null || _b === void 0 ? void 0 : _b.lastName}` ||
56
58
  s.id,
57
- value: s.id,
58
59
  });
59
- }), [cachedStudentProfiles.items, familyId]);
60
- const selectedStudentOption = useMemo(() => {
61
- var _a, _b;
62
- const selected = cachedStudentProfiles.items.find((s) => s.id === studentProfileId);
63
- return selected
64
- ? [
65
- {
66
- label: `${selected.computerNumber} - ${(_a = selected.familyMember) === null || _a === void 0 ? void 0 : _a.firstName} ${(_b = selected.familyMember) === null || _b === void 0 ? void 0 : _b.lastName}` ||
67
- selected.id,
68
- value: selected.id,
69
- },
70
- ]
71
- : [];
72
- }, [cachedStudentProfiles.items, studentProfileId]);
73
- const displayedStudentOptions = useMemo(() => {
74
- const sourceOptions = trimmedStudentSearchQuery
75
- ? remoteStudentOptions
76
- : cachedStudentOptions;
77
- const mergedOptions = [...selectedStudentOption, ...sourceOptions];
78
- const uniqueOptions = new Map(mergedOptions.map((option) => [option.value, option]));
79
- return [...uniqueOptions.values()];
80
- }, [
81
- cachedStudentOptions,
82
- remoteStudentOptions,
83
- selectedStudentOption,
84
- trimmedStudentSearchQuery,
85
- ]);
86
- useEffect(() => {
87
- if (!trimmedStudentSearchQuery || !schoolId)
88
- return;
89
- let isActive = true;
90
- const fetchStudents = async () => {
91
- setStudentOptionsLoading(true);
92
- try {
93
- const { items } = await getCachedStudentProfiles({
94
- params: {
95
- schoolId,
96
- searchQuery: trimmedStudentSearchQuery,
97
- },
98
- });
99
- if (!isActive)
100
- return;
101
- setRemoteStudentOptions((items || []).map((s) => {
102
- var _a, _b;
103
- return ({
104
- label: `${s.computerNumber} - ${(_a = s.familyMember) === null || _a === void 0 ? void 0 : _a.firstName} ${(_b = s.familyMember) === null || _b === void 0 ? void 0 : _b.lastName}` ||
105
- s.id,
106
- value: s.id,
107
- });
108
- }));
109
- }
110
- catch (_a) {
111
- if (!isActive)
112
- return;
113
- setRemoteStudentOptions([]);
114
- }
115
- finally {
116
- if (isActive) {
117
- setStudentOptionsLoading(false);
118
- }
119
- }
120
- };
121
- void fetchStudents();
122
- return () => {
123
- isActive = false;
124
- };
125
- }, [schoolId, trimmedStudentSearchQuery]);
126
- const cachedFeeStructures = getCachedFeeStructuresSync();
127
- const [feeStructureSearchQuery, setFeeStructureSearchQuery] = useState("");
128
- const [remoteFeeStructureOptions, setRemoteFeeStructureOptions] = useState(() => cachedFeeStructures.items.map((fs) => ({
129
- label: fs.name || fs.id,
130
- value: fs.id,
131
- })));
132
- const [feeStructureOptionsLoading, setFeeStructureOptionsLoading] = useState(false);
133
- const debouncedFeeStructureSearchQuery = useDebounce(feeStructureSearchQuery, 300);
134
- const trimmedFeeStructureSearchQuery = debouncedFeeStructureSearchQuery.trim();
135
- const cachedFeeStructureOptions = useMemo(() => cachedFeeStructures.items.map((fs) => ({
136
- label: fs.name || fs.id,
137
- value: fs.id,
138
- })), [cachedFeeStructures.items]);
139
- const selectedFeeStructureOption = useMemo(() => {
140
- const selected = cachedFeeStructures.items.find((fs) => fs.id === feeStructureId);
141
- return selected
142
- ? [{ label: selected.name || selected.id, value: selected.id }]
143
- : [];
144
- }, [cachedFeeStructures.items, feeStructureId]);
145
- const displayedFeeStructureOptions = useMemo(() => {
146
- const sourceOptions = trimmedFeeStructureSearchQuery
147
- ? remoteFeeStructureOptions
148
- : cachedFeeStructureOptions;
149
- const mergedOptions = [...selectedFeeStructureOption, ...sourceOptions];
150
- const uniqueOptions = new Map(mergedOptions.map((option) => [option.value, option]));
151
- return [...uniqueOptions.values()];
152
- }, [
153
- cachedFeeStructureOptions,
154
- remoteFeeStructureOptions,
155
- selectedFeeStructureOption,
156
- trimmedFeeStructureSearchQuery,
157
- ]);
158
- useEffect(() => {
159
- if (!trimmedFeeStructureSearchQuery || !schoolId)
160
- return;
161
- let isActive = true;
162
- const fetchFeeStructures = async () => {
163
- setFeeStructureOptionsLoading(true);
164
- try {
165
- const { items } = await getCachedFeeStructures({
166
- params: {
167
- schoolId,
168
- searchQuery: trimmedFeeStructureSearchQuery,
169
- },
170
- });
171
- if (!isActive)
172
- return;
173
- setRemoteFeeStructureOptions((items || []).map((fs) => ({
174
- label: fs.name || fs.id,
175
- value: fs.id,
176
- })));
177
- }
178
- catch (_a) {
179
- if (!isActive)
180
- return;
181
- setRemoteFeeStructureOptions([]);
182
- }
183
- finally {
184
- if (isActive) {
185
- setFeeStructureOptionsLoading(false);
186
- }
187
- }
188
- };
189
- void fetchFeeStructures();
190
- return () => {
191
- isActive = false;
192
- };
193
- }, [schoolId, trimmedFeeStructureSearchQuery]);
194
- const discountCodes = getCachedDiscountCodesSync();
195
- const discountCodeOptions = (discountCodes.items || [])
196
- .filter((code) => code.enabled)
197
- .map((code) => ({
198
- label: `${code.code} - ${code.discountValue}${code.discountType === DISCOUNT_TYPE.PERCENTAGE ? "%" : currency}`,
199
- value: code.id,
200
- description: code.description || undefined,
201
- }));
202
- return (_jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedCombobox, { emptyText: t("formNoStudentEmpty"), error: errors.studentProfileId, id: "studentProfileId", info: t("formStudentInfo"), label: t("formStudentLabel"), loading: studentOptionsLoading && Boolean(trimmedStudentSearchQuery), onSearchChange: setStudentSearchQuery, onValueChange: (value) => handleChange("studentProfileId", value), options: displayedStudentOptions, placeholder: t("formStudentPlaceholder"), required: true, searchPlaceholder: t("formSearchStudentsPlaceholder"), value: studentProfileId || "" }), _jsx(EnhancedCombobox, { emptyText: t("formNoFeeStructureEmpty"), error: errors.feeStructureId, id: "feeStructureId", info: t("formFeeStructureInfo"), label: t("formFeeStructureLabel"), loading: feeStructureOptionsLoading && Boolean(trimmedFeeStructureSearchQuery), onSearchChange: setFeeStructureSearchQuery, onValueChange: (value) => handleChange("feeStructureId", value), options: displayedFeeStructureOptions, placeholder: t("formFeeStructurePlaceholder"), required: true, searchPlaceholder: t("formSearchFeeStructuresPlaceholder"), value: feeStructureId || "" }), _jsx(EnhancedCombobox, { emptyText: t("formNoDiscountCodeEmpty"), error: errors.discountCodeId, id: "discountCodeId", info: t("formDiscountCodeInfo"), label: t("formDiscountCodeLabel"), onValueChange: (value) => handleChange("discountCodeId", value), options: discountCodeOptions, placeholder: t("formDiscountCodePlaceholder"), searchPlaceholder: t("formSearchDiscountCodesPlaceholder"), value: discountCodeId || "" }), _jsx(EnhancedInput, { error: errors.discountAmount, id: "discountAmount", info: t("formDiscountAmountInfo"), label: t("formDiscountAmountLabel"), min: "0", onChange: (e) => handleChange("discountAmount", Number(e.target.value)), placeholder: "0.00", required: true, step: "0.01", type: "number", value: discountAmount || 0 }), _jsx(EnhancedInput, { error: errors.amount, id: "amount", info: t("formTotalAmountInfo"), label: t("formTotalAmountLabel"), min: "0", onChange: (e) => handleChange("amount", Number(e.target.value)), placeholder: "0.00", required: true, step: "0.01", type: "number", value: amount }), _jsx(EnhancedInput, { error: errors.amountPaid, id: "amountPaid", info: t("formAmountPaidInfo"), label: t("formAmountPaidLabel"), min: "0", onChange: (e) => handleChange("amountPaid", Number(e.target.value)), placeholder: "0.00", step: "0.01", type: "number", value: amountPaid }), _jsx(EnhancedInput, { disabled: true, error: errors.amountDue, id: "amountDue", info: t("formAmountDueInfo"), label: t("formAmountDueLabel"), min: "0", onChange: (e) => handleChange("amountDue", Number(e.target.value)), placeholder: "0.00", step: "0.01", type: "number", value: amountDue }), _jsx(EnhancedInput, { error: errors.dueDate, id: "dueDate", info: t("formDueDateInfo"), label: t("formDueDateLabel"), onChange: (e) => handleChange("dueDate", e.target.value), required: true, type: "date", value: formatDate(dueDate, DATE_FORMATS.YYYY_MM_DD) }), _jsx(EnhancedCombobox, { emptyText: t("formNoStatusEmpty"), error: errors.status, id: "status", info: t("formStatusInfo"), label: t("formOptionStatus"), onValueChange: (value) => handleChange("status", value), options: PAYMENT_STATUS_OPTIONS, placeholder: t("formStatusPlaceholder"), required: true, searchPlaceholder: t("formSearchStatusPlaceholder"), value: status }), _jsx(EnhancedTextarea, { error: errors.remarks, id: "remarks", label: t("formRemarksLabel"), onChange: (e) => handleChange("remarks", e.target.value), placeholder: t("formRemarksPlaceholder"), value: remarks || "" }), _jsx(EnhancedCheckbox, { checked: enabled, error: errors.enabled, id: "enabled", info: t("formEnabledInfo"), label: t("badgeActive"), onCheckedChange: (checked) => handleChange("enabled", !!checked) })] }));
60
+ }), [studentProfiles, familyId]);
61
+ const { enhancedComboboxElement: studentProfileIdCombo } = useEnhancedCombobox({
62
+ emptyText: t("formNoStudentEmpty"),
63
+ id: "studentProfileId",
64
+ info: t("formStudentInfo"),
65
+ label: t("formStudentLabel"),
66
+ onValueChange: (value) => handleChange("studentProfileId", value),
67
+ options: filteredStudentOptions,
68
+ placeholder: t("formStudentPlaceholder"),
69
+ required: true,
70
+ searchEndpoint: STUDENT_FEE_API_ROUTES.UNIT,
71
+ searchPlaceholder: t("formSearchStudentsPlaceholder"),
72
+ value: studentProfileId || "",
73
+ });
74
+ const { enhancedComboboxElement: feeStructureIdCombo } = useEnhancedCombobox({
75
+ emptyText: t("formNoFeeStructureEmpty"),
76
+ id: "feeStructureId",
77
+ info: t("formFeeStructureInfo"),
78
+ label: t("formFeeStructureLabel"),
79
+ onValueChange: (value) => handleChange("feeStructureId", value),
80
+ options: feeStructures === null || feeStructures === void 0 ? void 0 : feeStructures.map((fs) => ({
81
+ id: fs.id,
82
+ name: fs.name || fs.id,
83
+ })),
84
+ placeholder: t("formFeeStructurePlaceholder"),
85
+ required: true,
86
+ searchEndpoint: STUDENT_FEE_API_ROUTES.UNIT,
87
+ searchPlaceholder: t("formSearchFeeStructuresPlaceholder"),
88
+ value: feeStructureId || "",
89
+ });
90
+ const { enhancedComboboxElement: discountCodeIdCombo } = useEnhancedCombobox({
91
+ emptyText: t("formNoDiscountCodeEmpty"),
92
+ id: "discountCodeId",
93
+ info: t("formDiscountCodeInfo"),
94
+ label: t("formDiscountCodeLabel"),
95
+ onValueChange: (value) => handleChange("discountCodeId", value),
96
+ options: (discountCodes === null || discountCodes === void 0 ? void 0 : discountCodes.map((code) => ({
97
+ id: code.id,
98
+ name: `${code.code} - ${code.discountValue}${code.discountType === DISCOUNT_TYPE.PERCENTAGE ? "%" : currency}`,
99
+ }))) || [],
100
+ placeholder: t("formDiscountCodePlaceholder"),
101
+ searchEndpoint: STUDENT_FEE_API_ROUTES.UNIT,
102
+ searchPlaceholder: t("formSearchDiscountCodesPlaceholder"),
103
+ value: discountCodeId || "",
104
+ });
105
+ const { enhancedComboboxElement: statusCombo } = useEnhancedCombobox({
106
+ emptyText: t("formNoStatusEmpty"),
107
+ id: "status",
108
+ info: t("formStatusInfo"),
109
+ label: t("formOptionStatus"),
110
+ onValueChange: (value) => handleChange("status", value),
111
+ options: PAYMENT_STATUS_OPTIONS.map((opt) => ({
112
+ id: opt.value,
113
+ name: paymentStatusLabelMap[opt.value] || opt.label,
114
+ })),
115
+ placeholder: t("formStatusPlaceholder"),
116
+ required: true,
117
+ searchEndpoint: STUDENT_FEE_API_ROUTES.UNIT,
118
+ searchPlaceholder: t("formSearchStatusPlaceholder"),
119
+ value: status,
120
+ });
121
+ return (_jsxs("div", { className: "grid grid-cols-1 gap-4", children: [studentProfileIdCombo, feeStructureIdCombo, discountCodeIdCombo, _jsx(EnhancedInput, { error: errors.discountAmount, id: "discountAmount", info: t("formDiscountAmountInfo"), label: t("formDiscountAmountLabel"), min: "0", onChange: (e) => handleChange("discountAmount", Number(e.target.value)), placeholder: "0.00", required: true, step: "0.01", type: "number", value: discountAmount || 0 }), _jsx(EnhancedInput, { error: errors.amount, id: "amount", info: t("formTotalAmountInfo"), label: t("formTotalAmountLabel"), min: "0", onChange: (e) => handleChange("amount", Number(e.target.value)), placeholder: "0.00", required: true, step: "0.01", type: "number", value: amount }), _jsx(EnhancedInput, { error: errors.amountPaid, id: "amountPaid", info: t("formAmountPaidInfo"), label: t("formAmountPaidLabel"), min: "0", onChange: (e) => handleChange("amountPaid", Number(e.target.value)), placeholder: "0.00", step: "0.01", type: "number", value: amountPaid }), _jsx(EnhancedInput, { disabled: true, error: errors.amountDue, id: "amountDue", info: t("formAmountDueInfo"), label: t("formAmountDueLabel"), min: "0", onChange: (e) => handleChange("amountDue", Number(e.target.value)), placeholder: "0.00", step: "0.01", type: "number", value: amountDue }), _jsx(EnhancedInput, { error: errors.dueDate, id: "dueDate", info: t("formDueDateInfo"), label: t("formDueDateLabel"), onChange: (e) => handleChange("dueDate", e.target.value), required: true, type: "date", value: formatDate(dueDate, DATE_FORMATS.YYYY_MM_DD) }), statusCombo, _jsx(EnhancedTextarea, { error: errors.remarks, id: "remarks", label: t("formRemarksLabel"), onChange: (e) => handleChange("remarks", e.target.value), placeholder: t("formRemarksPlaceholder"), value: remarks || "" }), _jsx(EnhancedCheckbox, { checked: enabled, error: errors.enabled, id: "enabled", info: t("formEnabledInfo"), label: t("badgeActive"), onCheckedChange: (checked) => handleChange("enabled", !!checked) })] }));
203
122
  };
@@ -1 +1,7 @@
1
- export declare const StudentFeeView: () => import("react").JSX.Element;
1
+ /**
2
+ * StudentFee View
3
+ *
4
+ * Read-only detail view for a StudentFee record.
5
+ */
6
+ import React from "react";
7
+ export declare const StudentFeeView: () => React.JSX.Element;
@@ -1,35 +1,32 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- /**
4
- * StudentFee View
5
- *
6
- * Read-only detail view for a StudentFee record.
7
- */
8
- import { useMemo } from "react";
9
3
  import { useStudentFeeModule } from "./context";
10
4
  import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@appcorp/shadcn/components/ui/card";
11
5
  import { Badge } from "@appcorp/shadcn/components/ui/badge";
12
6
  import { Separator } from "@appcorp/shadcn/components/ui/separator";
13
7
  import { Calendar, FileText, CheckCircle2, XCircle } from "lucide-react";
14
- import { getCachedFeeStructuresSync } from "../fee-structure/cache";
15
- import { getCachedStudentFeesSync } from "./cache";
16
8
  import { getCachedWorkspaceSync } from "../workspace/cache";
17
- import { formatDate, DATE_FORMATS } from "@react-pakistan/util-functions";
9
+ import { formatDate, DATE_FORMATS, API_METHODS, } from "@react-pakistan/util-functions";
10
+ import { useFetch } from "@react-pakistan/util-functions/hooks/use-fetch";
18
11
  import { useTranslations } from "next-intl";
19
12
  export const StudentFeeView = () => {
20
- var _a, _b, _c, _d;
13
+ var _a, _b;
21
14
  const { state } = useStudentFeeModule();
22
- const { amount, amountDue, amountPaid, dueDate, enabled, feeStructureId, id: studentFeeId, remarks, status, studentProfileId, } = state;
15
+ const { amount, amountDue, amountPaid, dueDate, enabled, feeStructureId, remarks, status, studentProfileId, } = state;
23
16
  const workspace = getCachedWorkspaceSync();
24
17
  const currency = (_b = (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.currency) !== null && _b !== void 0 ? _b : "";
25
18
  const t = useTranslations("studentFee");
26
- const studentFee = getCachedStudentFeesSync().items.find(({ id }) => id === studentFeeId);
27
- const studentMember = useMemo(() => {
28
- var _a, _b, _c;
29
- return (_c = (_b = (_a = studentFee === null || studentFee === void 0 ? void 0 : studentFee.family) === null || _a === void 0 ? void 0 : _a.members) === null || _b === void 0 ? void 0 : _b.filter(({ studentProfile }) => !!studentProfile)) === null || _c === void 0 ? void 0 : _c.find(({ studentProfile }) => (studentProfile === null || studentProfile === void 0 ? void 0 : studentProfile.id) === studentProfileId);
30
- }, [studentFee, studentProfileId]);
31
- const feeStructureName = (_c = getCachedFeeStructuresSync().items.find(({ id }) => id === feeStructureId)) === null || _c === void 0 ? void 0 : _c.name;
32
- return (_jsx("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(FileText, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionStudentFeeDetails") })] }), _jsx(CardDescription, { children: t("viewSectionReadOnlyStudentFeeInformation") })] }), _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-sm font-medium text-muted-foreground", children: t("viewFieldStudent") }), _jsx("p", { className: "text-base", children: studentMember
33
- ? `${studentMember.firstName} ${studentMember.lastName}`
34
- : "—" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewFieldComputerNumber") }), _jsx("p", { className: "text-base", children: ((_d = studentMember === null || studentMember === void 0 ? void 0 : studentMember.studentProfile) === null || _d === void 0 ? void 0 : _d.computerNumber) || "—" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewFieldFeeStructure") }), _jsx("p", { className: "text-base", children: feeStructureName || "—" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewFieldTotalAmount") }), _jsxs("p", { className: "text-base", children: [currency, " ", (amount !== null && amount !== void 0 ? amount : 0).toFixed(2)] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewFieldAmountPaid") }), _jsxs("p", { className: "text-base", children: [currency, " ", (amountPaid !== null && amountPaid !== void 0 ? amountPaid : 0).toFixed(2)] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewFieldAmountDue") }), _jsxs("p", { className: "text-base", children: [currency, " ", (amountDue !== null && amountDue !== void 0 ? amountDue : 0).toFixed(2)] })] }), _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("viewFieldDueDate") })] }), _jsx("p", { className: "text-base", children: formatDate(dueDate, DATE_FORMATS.LOCALE_DATE) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewFieldStatus") }), _jsx(Badge, { variant: "secondary", children: status || "—" })] }), remarks && (_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewFieldRemarks") }), _jsx("p", { className: "text-base", children: remarks })] })), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewFieldRecordState") }), _jsxs(Badge, { className: "gap-1", variant: enabled ? "default" : "destructive", children: [enabled ? (_jsx(CheckCircle2, { className: "h-3 w-3" })) : (_jsx(XCircle, { className: "h-3 w-3" })), enabled ? t("viewFieldStatusActive") : t("viewFieldStatusInactive")] })] })] }) })] }) }));
19
+ const { data: studentProfile } = useFetch("/api/v1/student-profile", {
20
+ method: API_METHODS.GET,
21
+ params: { id: studentProfileId, workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
22
+ });
23
+ const { data: feeStructure } = useFetch("/api/v1/fee-structure", {
24
+ method: API_METHODS.GET,
25
+ params: { id: feeStructureId, workspaceId: workspace === null || workspace === void 0 ? void 0 : workspace.id },
26
+ });
27
+ return (_jsx("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(FileText, { className: "text-primary h-5 w-5" }), _jsx(CardTitle, { className: "text-lg", children: t("viewSectionStudentFeeDetails") })] }), _jsx(CardDescription, { children: t("viewSectionReadOnlyStudentFeeInformation") })] }), _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("viewFieldStudent") }), _jsx("p", { className: "text-base", children: studentProfile
28
+ ? `${studentProfile.firstName} ${studentProfile.lastName}`
29
+ : "—" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldComputerNumber") }), _jsx("p", { className: "text-base", children: (studentProfile === null || studentProfile === void 0 ? void 0 : studentProfile.computerNumber) || "—" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldFeeStructure") }), _jsx("p", { className: "text-base", children: (feeStructure === null || feeStructure === void 0 ? void 0 : feeStructure.name) || "—" })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldTotalAmount") }), _jsxs("p", { className: "text-base", children: [currency, " ", (amount !== null && amount !== void 0 ? amount : 0).toFixed(2)] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldAmountPaid") }), _jsxs("p", { className: "text-base", children: [currency, " ", (amountPaid !== null && amountPaid !== void 0 ? amountPaid : 0).toFixed(2)] })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldAmountDue") }), _jsxs("p", { className: "text-base", children: [currency, " ", (amountDue !== null && amountDue !== void 0 ? amountDue : 0).toFixed(2)] })] }), _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("viewFieldDueDate") })] }), _jsx("p", { className: "text-base", children: formatDate(dueDate, DATE_FORMATS.LOCALE_DATE) })] }), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldStatus") }), _jsx(Badge, { variant: "secondary", children: status || "—" })] }), remarks && (_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldRemarks") }), _jsx("p", { className: "text-base", children: remarks })] })), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-muted-foreground text-sm font-medium", children: t("viewFieldRecordState") }), _jsxs(Badge, { className: "gap-1", variant: enabled ? "default" : "destructive", children: [enabled ? (_jsx(CheckCircle2, { className: "h-3 w-3" })) : (_jsx(XCircle, { className: "h-3 w-3" })), enabled
30
+ ? t("viewFieldStatusActive")
31
+ : t("viewFieldStatusInactive")] })] })] }) })] }) }));
35
32
  };
@@ -33,9 +33,6 @@ export declare const tableBodyCols: ({
33
33
  textFormatter?: undefined;
34
34
  })[];
35
35
  export declare const STATUS_OPTIONS: readonly [{
36
- readonly label: "All Status";
37
- readonly value: "";
38
- }, {
39
36
  readonly label: "Active";
40
37
  readonly value: "ACTIVE";
41
38
  }, {
@@ -53,9 +50,6 @@ export declare const STATUS_OPTIONS: readonly [{
53
50
  }];
54
51
  export declare const STATUS_BADGE_COLORS: Record<string, string>;
55
52
  export declare const GENDER_OPTIONS: readonly [{
56
- readonly label: "All Genders";
57
- readonly value: "";
58
- }, {
59
53
  readonly label: "Male";
60
54
  readonly value: "MALE";
61
55
  }, {
@@ -68,7 +68,7 @@ export const tableBodyCols = [
68
68
  const courseCount = (_b = (_a = section === null || section === void 0 ? void 0 : section.courses) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
69
69
  return courseCount > 0
70
70
  ? `${(_c = section === null || section === void 0 ? void 0 : section.name) !== null && _c !== void 0 ? _c : "Section"} (${courseCount} subjects)`
71
- : (_d = section === null || section === void 0 ? void 0 : section.name) !== null && _d !== void 0 ? _d : "Enrolled";
71
+ : ((_d = section === null || section === void 0 ? void 0 : section.name) !== null && _d !== void 0 ? _d : "Enrolled");
72
72
  }
73
73
  return `${enrollments.length} sections`;
74
74
  },
@@ -89,7 +89,6 @@ export const tableBodyCols = [
89
89
  // STATUS OPTIONS
90
90
  // ============================================================================
91
91
  export const STATUS_OPTIONS = [
92
- { label: "All Status", value: "" },
93
92
  { label: "Active", value: "ACTIVE" },
94
93
  { label: "Inactive", value: "INACTIVE" },
95
94
  { label: "Graduated", value: "GRADUATED" },
@@ -107,7 +106,6 @@ export const STATUS_BADGE_COLORS = {
107
106
  // GENDER OPTIONS
108
107
  // ============================================================================
109
108
  export const GENDER_OPTIONS = [
110
- { label: "All Genders", value: "" },
111
109
  { label: "Male", value: "MALE" },
112
110
  { label: "Female", value: "FEMALE" },
113
111
  { label: "Other", value: "OTHER" },
@@ -29,6 +29,7 @@ export declare const useStudentProfileModule: () => {
29
29
  }[];
30
30
  listFetchNow: (url?: string, config?: import("@react-pakistan/util-functions/hooks/use-fetch").FetchConfig) => void;
31
31
  listLoading: boolean;
32
+ resetRecordFormState: () => void;
32
33
  rowActions: RowAction[];
33
34
  toggleStatus: (row?: TableRow) => void;
34
35
  updateLoading: boolean;