@appcorp/fusion-storybook 0.4.15 → 0.4.17
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/context/use-admission-module.d.ts +1 -1
- package/base-modules/admission/context/use-admission-module.js +20 -8
- package/base-modules/student-fee/auto-post-payload.d.ts +13 -0
- package/base-modules/student-fee/auto-post-payload.js +3 -0
- package/base-modules/student-fee/misc-2.js +12 -5
- package/base-modules/student-fee/more-actions.js +8 -4
- package/constants.d.ts +1 -0
- package/constants.js +1 -0
- package/package.json +3 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/utils/compress-pdf.d.ts +6 -0
- package/utils/compress-pdf.js +19 -0
- package/utils/wake-storage.d.ts +1 -0
- package/utils/wake-storage.js +8 -0
|
@@ -32,7 +32,7 @@ export declare const useAdmissionModule: () => {
|
|
|
32
32
|
listLoading: boolean;
|
|
33
33
|
rowActions: RowAction[];
|
|
34
34
|
updateLoading: boolean;
|
|
35
|
-
uploadAdmissionDocuments: (files: File[]) => Promise<string[]>;
|
|
35
|
+
uploadAdmissionDocuments: (files: File[], registrationCode: string) => Promise<string[]>;
|
|
36
36
|
state: {
|
|
37
37
|
items: AdmissionBE[];
|
|
38
38
|
count: number;
|
|
@@ -16,6 +16,8 @@ import { admissionFormValidation } from "../validate";
|
|
|
16
16
|
import { getCachedWorkspaceSync } from "../../workspace/cache";
|
|
17
17
|
import { downloadAdmissionFormPDF, } from "../../../utils/admission-pdf";
|
|
18
18
|
import { fileToBase64 } from "../../../utils/file-to-base64";
|
|
19
|
+
import { compressPdf, DocumentTooLargeError, isPdfFile, MAX_DOCUMENT_SIZE_BYTES, } from "../../../utils/compress-pdf";
|
|
20
|
+
import { wakeStorageServer } from "../../../utils/wake-storage";
|
|
19
21
|
import { normalizeIdNumber } from "../../../utils/id-number";
|
|
20
22
|
import { toE164Phone } from "../../../utils/to-e164-phone";
|
|
21
23
|
import { formatPhoneDisplay } from "@react-pakistan/util-functions/general/format-phone-display";
|
|
@@ -293,13 +295,19 @@ export const useAdmissionModule = () => {
|
|
|
293
295
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
294
296
|
}
|
|
295
297
|
}, [showToast, t]);
|
|
296
|
-
const uploadAdmissionDocuments = useCallback(async (files) => {
|
|
298
|
+
const uploadAdmissionDocuments = useCallback(async (files, registrationCode) => {
|
|
297
299
|
var _a;
|
|
298
300
|
const schoolId = (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id;
|
|
299
301
|
if (!schoolId) {
|
|
300
302
|
throw new Error("School context is not available");
|
|
301
303
|
}
|
|
302
|
-
const
|
|
304
|
+
const prepared = await Promise.all(files.map(async (file) => isPdfFile(file) ? await compressPdf(file) : file));
|
|
305
|
+
for (const file of prepared) {
|
|
306
|
+
if (file.size > MAX_DOCUMENT_SIZE_BYTES) {
|
|
307
|
+
throw new DocumentTooLargeError(file.name, file.size);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const payload = await Promise.all(prepared.map(async (file) => ({
|
|
303
311
|
fileName: file.name,
|
|
304
312
|
contentType: file.type || "application/octet-stream",
|
|
305
313
|
fileBase64: await fileToBase64(file),
|
|
@@ -310,7 +318,7 @@ export const useAdmissionModule = () => {
|
|
|
310
318
|
headers: {
|
|
311
319
|
"Content-Type": "application/json",
|
|
312
320
|
},
|
|
313
|
-
body: JSON.stringify({ schoolId, files: payload }),
|
|
321
|
+
body: JSON.stringify({ schoolId, registrationCode, files: payload }),
|
|
314
322
|
});
|
|
315
323
|
if (error || !(data === null || data === void 0 ? void 0 : data.urls)) {
|
|
316
324
|
throw new Error("Upload failed");
|
|
@@ -355,11 +363,12 @@ export const useAdmissionModule = () => {
|
|
|
355
363
|
resetFormAndCloseDrawer();
|
|
356
364
|
}, [resetFormAndCloseDrawer]);
|
|
357
365
|
const handleCreate = useCallback(() => {
|
|
366
|
+
wakeStorageServer();
|
|
358
367
|
dispatch({
|
|
359
368
|
type: ADMISSION_ACTION_TYPES.SET_DRAWER,
|
|
360
369
|
payload: { drawer: ADMISSION_DRAWER.FORM_DRAWER },
|
|
361
370
|
});
|
|
362
|
-
}, [dispatch]);
|
|
371
|
+
}, [dispatch, wakeStorageServer]);
|
|
363
372
|
const handleView = useCallback((row) => {
|
|
364
373
|
byIdFetchNow === null || byIdFetchNow === void 0 ? void 0 : byIdFetchNow(undefined, { params: { id: row === null || row === void 0 ? void 0 : row.id } });
|
|
365
374
|
dispatch({
|
|
@@ -368,12 +377,13 @@ export const useAdmissionModule = () => {
|
|
|
368
377
|
});
|
|
369
378
|
}, [dispatch, byIdFetchNow]);
|
|
370
379
|
const handleEdit = useCallback((row) => {
|
|
380
|
+
wakeStorageServer();
|
|
371
381
|
byIdFetchNow === null || byIdFetchNow === void 0 ? void 0 : byIdFetchNow(undefined, { params: { id: row === null || row === void 0 ? void 0 : row.id } });
|
|
372
382
|
dispatch({
|
|
373
383
|
type: ADMISSION_ACTION_TYPES.SET_DRAWER,
|
|
374
384
|
payload: { drawer: ADMISSION_DRAWER.FORM_DRAWER },
|
|
375
385
|
});
|
|
376
|
-
}, [dispatch, byIdFetchNow]);
|
|
386
|
+
}, [dispatch, byIdFetchNow, wakeStorageServer]);
|
|
377
387
|
const handleDelete = useCallback((row) => {
|
|
378
388
|
if (!confirm(t("messagesDeleteConfirmation")))
|
|
379
389
|
return;
|
|
@@ -638,7 +648,7 @@ export const useAdmissionModule = () => {
|
|
|
638
648
|
const merged = state.documentsFiles.length
|
|
639
649
|
? [
|
|
640
650
|
...(state.documents || []),
|
|
641
|
-
...(await uploadAdmissionDocuments(state.documentsFiles)),
|
|
651
|
+
...(await uploadAdmissionDocuments(state.documentsFiles, updateParams.registrationCode)),
|
|
642
652
|
]
|
|
643
653
|
: state.documents || [];
|
|
644
654
|
dispatch({
|
|
@@ -699,12 +709,14 @@ export const useAdmissionModule = () => {
|
|
|
699
709
|
}),
|
|
700
710
|
});
|
|
701
711
|
}
|
|
702
|
-
catch (
|
|
712
|
+
catch (error) {
|
|
703
713
|
dispatch({
|
|
704
714
|
type: ADMISSION_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
|
|
705
715
|
payload: { disabled: false },
|
|
706
716
|
});
|
|
707
|
-
showToast(t(
|
|
717
|
+
showToast(t(error instanceof DocumentTooLargeError
|
|
718
|
+
? "messagesDocumentTooLarge"
|
|
719
|
+
: "messagesDocumentsUploadFailed"), TOAST_VARIANT.ERROR);
|
|
708
720
|
}
|
|
709
721
|
},
|
|
710
722
|
errorCallback: (errors) => {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface BuildAutoPostPayloadInput {
|
|
2
|
+
schoolId: string;
|
|
3
|
+
computerNumbers: string[];
|
|
4
|
+
paidAt: string;
|
|
5
|
+
skipFine: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function buildAutoPostPayload(input: BuildAutoPostPayloadInput): {
|
|
8
|
+
skipFine?: boolean | undefined;
|
|
9
|
+
schoolId: string;
|
|
10
|
+
computerNumbers: string[];
|
|
11
|
+
paidAt: string;
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -22,6 +22,12 @@ import { DISCOUNT_TYPE, PAYMENT_STATUS } from "../../types";
|
|
|
22
22
|
import { PAYMENT_STATUS_OPTIONS } from "./constants";
|
|
23
23
|
import { Loader2 } from "lucide-react";
|
|
24
24
|
import { DATE_FORMATS, formatDate, } from "@react-pakistan/util-functions/general/format-date";
|
|
25
|
+
function toLocalDateString(date) {
|
|
26
|
+
const year = date.getFullYear();
|
|
27
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
28
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
29
|
+
return `${year}-${month}-${day}`;
|
|
30
|
+
}
|
|
25
31
|
export const StudentFeeSingle = () => {
|
|
26
32
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
27
33
|
const { dispatch, handleChange, state } = useStudentFeeModule();
|
|
@@ -40,13 +46,14 @@ export const StudentFeeSingle = () => {
|
|
|
40
46
|
var _a;
|
|
41
47
|
if (!debouncedComputerNumber)
|
|
42
48
|
return;
|
|
49
|
+
// When the chosen payment date differs from today, ask the API to recompute
|
|
50
|
+
// the fines as of that back-dated (or future) payment date.
|
|
51
|
+
const today = toLocalDateString(new Date());
|
|
52
|
+
const useAsOf = state.paidAt && state.paidAt !== today;
|
|
43
53
|
fetchByCNRef.current(undefined, {
|
|
44
|
-
params: {
|
|
45
|
-
computerNumber: debouncedComputerNumber,
|
|
46
|
-
schoolId: (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id,
|
|
47
|
-
},
|
|
54
|
+
params: Object.assign({ computerNumber: debouncedComputerNumber, schoolId: (_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id }, (useAsOf ? { asOf: state.paidAt } : {})),
|
|
48
55
|
});
|
|
49
|
-
}, [debouncedComputerNumber, (_c = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _c === void 0 ? void 0 : _c.id]);
|
|
56
|
+
}, [debouncedComputerNumber, (_c = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _c === void 0 ? void 0 : _c.id, state.paidAt]);
|
|
50
57
|
const accumulatedAmount = useMemo(() => {
|
|
51
58
|
var _a;
|
|
52
59
|
if (!((_a = feeByComputerNumber === null || feeByComputerNumber === void 0 ? void 0 : feeByComputerNumber.studentFees) === null || _a === void 0 ? void 0 : _a.length))
|
|
@@ -4,12 +4,14 @@ import { showErrorToast, showSuccessToast, showInfoToast, } from "@appcorp/shadc
|
|
|
4
4
|
import { getCachedWorkspaceSync } from "../workspace/cache";
|
|
5
5
|
import { useTranslations } from "next-intl";
|
|
6
6
|
import { STUDENT_FEE_API_ROUTES } from "../../constants";
|
|
7
|
+
import { buildAutoPostPayload } from "./auto-post-payload";
|
|
7
8
|
import { STUDENT_FEE_ACTION_TYPES, useStudentFeeModule } from "./context";
|
|
8
9
|
import { useRef, useEffect, useCallback, useState } from "react";
|
|
9
10
|
import { Button } from "@appcorp/shadcn/components/ui/button";
|
|
10
11
|
import { Separator } from "@appcorp/shadcn/components/ui/separator";
|
|
11
12
|
import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
|
|
12
13
|
import { EnhancedTextarea } from "@appcorp/shadcn/components/enhanced-textarea";
|
|
14
|
+
import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
|
|
13
15
|
const workspace = getCachedWorkspaceSync();
|
|
14
16
|
const POLL_INTERVAL_MS = 2000;
|
|
15
17
|
const POLL_TIMEOUT_MS = 300000;
|
|
@@ -61,6 +63,7 @@ export const StudentFeeMoreActions = () => {
|
|
|
61
63
|
const abortRef = useRef(null);
|
|
62
64
|
const [autoPostDate, setAutoPostDate] = useState("");
|
|
63
65
|
const [computerNumbersText, setComputerNumbersText] = useState("");
|
|
66
|
+
const [skipFine, setSkipFine] = useState(false);
|
|
64
67
|
const [submitting, setSubmitting] = useState(false);
|
|
65
68
|
useEffect(() => {
|
|
66
69
|
return () => {
|
|
@@ -127,11 +130,12 @@ export const StudentFeeMoreActions = () => {
|
|
|
127
130
|
headers: {
|
|
128
131
|
"Content-Type": "application/json",
|
|
129
132
|
},
|
|
130
|
-
body: JSON.stringify({
|
|
133
|
+
body: JSON.stringify(buildAutoPostPayload({
|
|
131
134
|
schoolId,
|
|
132
135
|
computerNumbers: uniqueNumbers,
|
|
133
136
|
paidAt: autoPostDate,
|
|
134
|
-
|
|
137
|
+
skipFine,
|
|
138
|
+
})),
|
|
135
139
|
signal,
|
|
136
140
|
});
|
|
137
141
|
if (!res.ok) {
|
|
@@ -187,9 +191,9 @@ export const StudentFeeMoreActions = () => {
|
|
|
187
191
|
finally {
|
|
188
192
|
setSubmitting(false);
|
|
189
193
|
}
|
|
190
|
-
}, [t, dispatch, closeDrawer, refreshList, computerNumbersText, autoPostDate]);
|
|
194
|
+
}, [t, dispatch, closeDrawer, refreshList, computerNumbersText, autoPostDate, skipFine]);
|
|
191
195
|
const canSubmit = autoPostDate.trim() !== "" &&
|
|
192
196
|
computerNumbersText.trim() !== "" &&
|
|
193
197
|
!submitting;
|
|
194
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsx(Button, { disabled: new Date().getDate() !== 1, onClick: handleCreateMonthly, children: t("actionsButtonCreateMonthly") }), _jsx(Button, { onClick: handleCreateSingleEntry, children: t("actionsButtonSingleEntry") }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-4", children: [_jsx(EnhancedInput, { id: "autoPostDate", info: t("formAutoPostDateInfo"), label: t("formAutoPostDateLabel"), onChange: (e) => setAutoPostDate(e.target.value), onClick: (e) => { var _a, _b; return (_b = (_a = e.currentTarget).showPicker) === null || _b === void 0 ? void 0 : _b.call(_a); }, type: "date", value: autoPostDate }), _jsx(EnhancedTextarea, { id: "autoPostComputerNumbers", info: t("formAutoPostComputerNumbersInfo"), label: t("formAutoPostComputerNumbersLabel"), onChange: (e) => setComputerNumbersText(e.target.value), placeholder: t("formAutoPostComputerNumbersPlaceholder"), rows: 8, value: computerNumbersText }), _jsx(Button, { disabled: !canSubmit, onClick: handleAutoPost, children: t("actionsButtonAutoPost") })] })] }));
|
|
198
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsx(Button, { disabled: new Date().getDate() !== 1, onClick: handleCreateMonthly, children: t("actionsButtonCreateMonthly") }), _jsx(Button, { onClick: handleCreateSingleEntry, children: t("actionsButtonSingleEntry") }), _jsx(Separator, {}), _jsxs("div", { className: "space-y-4", children: [_jsx(EnhancedInput, { id: "autoPostDate", info: t("formAutoPostDateInfo"), label: t("formAutoPostDateLabel"), onChange: (e) => setAutoPostDate(e.target.value), onClick: (e) => { var _a, _b; return (_b = (_a = e.currentTarget).showPicker) === null || _b === void 0 ? void 0 : _b.call(_a); }, type: "date", value: autoPostDate }), _jsx(EnhancedTextarea, { id: "autoPostComputerNumbers", info: t("formAutoPostComputerNumbersInfo"), label: t("formAutoPostComputerNumbersLabel"), onChange: (e) => setComputerNumbersText(e.target.value), placeholder: t("formAutoPostComputerNumbersPlaceholder"), rows: 8, value: computerNumbersText }), _jsx(EnhancedCheckbox, { id: "autoPostSkipFine", checked: skipFine, info: t("formSkipFineInfo"), label: t("formSkipFineLabel"), onCheckedChange: (checked) => setSkipFine(!!checked) }), _jsx(Button, { disabled: !canSubmit, onClick: handleAutoPost, children: t("actionsButtonAutoPost") })] })] }));
|
|
195
199
|
};
|
package/constants.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export declare const ADMISSION_API_ROUTES: {
|
|
|
21
21
|
export declare const DOCUMENT_UPLOAD_API_ROUTES: {
|
|
22
22
|
readonly UNIT: "/api/v1/document-upload";
|
|
23
23
|
};
|
|
24
|
+
export declare const STORAGE_WAKE_URL = "https://storage.edupilotpro.com/";
|
|
24
25
|
export declare const CAMPUS_API_ROUTES: Record<string, string>;
|
|
25
26
|
export declare const CLASS_API_ROUTES: {
|
|
26
27
|
readonly UNIT: "/api/v1/class";
|
package/constants.js
CHANGED
|
@@ -24,6 +24,7 @@ export const ADMISSION_API_ROUTES = {
|
|
|
24
24
|
export const DOCUMENT_UPLOAD_API_ROUTES = {
|
|
25
25
|
UNIT: "/api/v1/document-upload",
|
|
26
26
|
};
|
|
27
|
+
export const STORAGE_WAKE_URL = "https://storage.edupilotpro.com/";
|
|
27
28
|
export const CAMPUS_API_ROUTES = {
|
|
28
29
|
UNIT: "/api/v1/campus",
|
|
29
30
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appcorp/fusion-storybook",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.17",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"build-storybook": "storybook build",
|
|
6
6
|
"build:next": "next build",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"@commitlint/cli": "^20.5.0",
|
|
43
43
|
"@commitlint/config-conventional": "^20.5.0",
|
|
44
44
|
"@playwright/test": "^1.59.1",
|
|
45
|
+
"@quicktoolsone/pdf-compress": "^2.0.0",
|
|
45
46
|
"@radix-ui/react-avatar": "^1",
|
|
46
47
|
"@radix-ui/react-checkbox": "^1",
|
|
47
48
|
"@radix-ui/react-dialog": "^1",
|
|
@@ -106,6 +107,7 @@
|
|
|
106
107
|
"ts-jest": "^29.4.9",
|
|
107
108
|
"tw-animate-css": "^1.4.0",
|
|
108
109
|
"typescript": "^5",
|
|
110
|
+
"undici": "^8.10.0",
|
|
109
111
|
"uuid": "^13.0.0",
|
|
110
112
|
"vaul": "^1.1.2",
|
|
111
113
|
"vite": "^8.0.5",
|