@appcorp/fusion-storybook 0.2.39 → 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.
- package/base-modules/admission/constants.d.ts +5 -17
- package/base-modules/admission/constants.js +12 -7
- package/base-modules/admission/context/use-admission-module.js +11 -48
- package/base-modules/admission/filter.js +23 -3
- package/base-modules/admission/form.js +49 -19
- package/base-modules/attendance/context.js +3 -37
- package/base-modules/attendance/form.js +26 -10
- package/base-modules/attendance/more-actions.js +34 -25
- package/base-modules/campus/context.js +13 -44
- package/base-modules/class/cache.js +0 -1
- package/base-modules/class/context.js +10 -48
- package/base-modules/class/more-actions.js +0 -2
- package/base-modules/course/context.js +3 -37
- package/base-modules/course/form.js +91 -292
- package/base-modules/discount-code/constants.d.ts +5 -0
- package/base-modules/discount-code/constants.js +5 -0
- package/base-modules/discount-code/context.d.ts +1 -0
- package/base-modules/discount-code/context.js +40 -39
- package/base-modules/discount-code/form.js +21 -15
- package/base-modules/discount-code/more-actions.js +1 -1
- package/base-modules/enrollment/context.js +3 -37
- package/base-modules/enrollment/form.js +38 -11
- package/base-modules/enrollment/more-actions.js +0 -2
- package/base-modules/expense/constants.js +1 -1
- package/base-modules/expense/context.js +5 -32
- package/base-modules/expense/filter.js +50 -3
- package/base-modules/expense/form.js +82 -6
- package/base-modules/family/context.js +7 -38
- package/base-modules/family-member/context.js +7 -39
- package/base-modules/fee-structure/context.js +1 -25
- package/base-modules/fee-structure/form.js +77 -89
- package/base-modules/fee-structure/more-actions.js +0 -2
- package/base-modules/rbac/context.d.ts +1 -0
- package/base-modules/rbac/context.js +23 -32
- package/base-modules/school/context.js +1 -1
- package/base-modules/school/form.js +34 -14
- package/base-modules/section/context.d.ts +1 -0
- package/base-modules/section/context.js +40 -47
- package/base-modules/section/form.js +25 -80
- package/base-modules/section/more-actions.js +0 -2
- package/base-modules/section/view.js +9 -7
- package/base-modules/student-fee/context/use-student-fee-module.d.ts +1 -0
- package/base-modules/student-fee/context/use-student-fee-module.js +48 -32
- package/base-modules/student-fee/context.d.ts +1 -1
- package/base-modules/student-fee/context.js +1 -1
- package/base-modules/student-fee/filter.js +23 -3
- package/base-modules/student-fee/form.js +93 -174
- package/base-modules/student-fee/view.d.ts +7 -1
- package/base-modules/student-fee/view.js +17 -20
- package/base-modules/student-profile/constants.d.ts +0 -6
- package/base-modules/student-profile/constants.js +1 -3
- package/base-modules/student-profile/context/use-student-profile-module.d.ts +1 -0
- package/base-modules/student-profile/context/use-student-profile-module.js +62 -55
- package/base-modules/student-profile/context.d.ts +1 -1
- package/base-modules/student-profile/context.js +1 -1
- package/base-modules/student-profile/filter.js +23 -3
- package/base-modules/student-profile/form.js +35 -3
- package/base-modules/subject/context.d.ts +1 -0
- package/base-modules/subject/context.js +38 -47
- package/base-modules/subject/more-actions.js +0 -2
- package/base-modules/teacher/constants.d.ts +0 -6
- package/base-modules/teacher/constants.js +0 -2
- package/base-modules/teacher/context.d.ts +1 -0
- package/base-modules/teacher/context.js +58 -39
- package/base-modules/teacher/form.js +46 -11
- package/base-modules/teacher/more-actions.js +0 -2
- package/base-modules/user/context/use-user-module.d.ts +1 -0
- package/base-modules/user/context/use-user-module.js +36 -32
- package/base-modules/user/context.js +1 -1
- package/base-modules/user/filter.js +6 -4
- package/base-modules/user/form.js +29 -5
- package/base-modules/user/more-actions.js +9 -7
- package/base-modules/user/view.js +3 -1
- package/base-modules/workspace/form.js +18 -8
- package/base-modules/workspace-user/context.d.ts +2 -1
- package/base-modules/workspace-user/context.js +31 -29
- package/package.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/base-modules/admission/cache.d.ts +0 -14
- package/base-modules/admission/cache.js +0 -31
- package/base-modules/attendance/cache.d.ts +0 -14
- package/base-modules/attendance/cache.js +0 -31
- package/base-modules/campus/cache.d.ts +0 -14
- package/base-modules/campus/cache.js +0 -31
- package/base-modules/course/cache.d.ts +0 -14
- package/base-modules/course/cache.js +0 -31
- package/base-modules/enrollment/cache.d.ts +0 -14
- package/base-modules/enrollment/cache.js +0 -31
- package/base-modules/expense/cache.d.ts +0 -14
- package/base-modules/expense/cache.js +0 -31
- package/base-modules/family/cache.d.ts +0 -14
- package/base-modules/family/cache.js +0 -31
- package/base-modules/family-member/cache.d.ts +0 -14
- package/base-modules/family-member/cache.js +0 -31
- package/base-modules/rbac/cache.d.ts +0 -27
- package/base-modules/rbac/cache.js +0 -46
- package/base-modules/student-fee/cache.d.ts +0 -15
- package/base-modules/student-fee/cache.js +0 -21
- package/base-modules/workspace-user/cache.d.ts +0 -14
- 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 {
|
|
13
|
-
import {
|
|
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
|
|
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
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
.
|
|
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
|
-
|
|
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
|
-
}), [
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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,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
|
|
13
|
+
var _a, _b;
|
|
21
14
|
const { state } = useStudentFeeModule();
|
|
22
|
-
const { amount, amountDue, amountPaid, dueDate, enabled, feeStructureId,
|
|
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
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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;
|