@appcorp/fusion-storybook 0.2.40 → 0.2.44
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/filter.js +3 -1
- package/base-modules/attendance/form.js +26 -10
- package/base-modules/attendance/more-actions.js +34 -25
- package/base-modules/campus/context.js +7 -7
- package/base-modules/class/cache.js +0 -1
- package/base-modules/class/context.js +10 -48
- package/base-modules/class/more-actions.js +47 -24
- 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 +48 -25
- 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 +45 -22
- package/base-modules/rbac/context.d.ts +1 -0
- package/base-modules/rbac/context.js +24 -33
- package/base-modules/rbac/form.js +3 -1
- 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 +47 -24
- 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 +24 -4
- 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 +47 -24
- 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 +45 -22
- 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/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
|
@@ -1,38 +1,47 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { useEnhancedCombobox } from "@appcorp/shadcn/hooks/use-enhanced-combobox";
|
|
4
4
|
import { EnhancedRadio } from "@appcorp/shadcn/components/enhanced-radio";
|
|
5
5
|
import { EnhancedTextarea } from "@appcorp/shadcn/components/enhanced-textarea";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { getCachedStudentProfilesSync } from "../student-profile/cache";
|
|
9
|
-
import { useMemo, useState } from "react";
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
import { ATTENDANCE_API_ROUTES } from "./constants";
|
|
10
8
|
export const AttendanceMoreActions = ({ labelAttendanceStatus, labelCourse, labelCourseInfo, labelCoursePlaceholder, labelNoCourseFound, labelRemarks, labelRemarksInfo, labelRemarksPlaceholder, labelSearchCourses, labelStatusAbsent, labelStatusExcused, labelStatusHalfDay, labelStatusLate, labelStatusPresent, }) => {
|
|
11
|
-
const enrollment = getCachedEnrollmentsSync().items;
|
|
12
|
-
const studentProfiles = getCachedStudentProfilesSync().items;
|
|
13
|
-
const courses = getCachedCoursesSync().items;
|
|
9
|
+
// const enrollment = getCachedEnrollmentsSync().items;
|
|
10
|
+
// const studentProfiles = getCachedStudentProfilesSync().items;
|
|
11
|
+
// const courses = getCachedCoursesSync().items;
|
|
14
12
|
const [courseId, setCourseId] = useState("");
|
|
15
13
|
const [remarks, setRemarks] = useState({});
|
|
16
14
|
const [attendance, setAttendance] = useState({});
|
|
17
15
|
const [errors] = useState({});
|
|
16
|
+
const { enhancedComboboxElement: courseIdCombo } = useEnhancedCombobox({
|
|
17
|
+
emptyText: labelNoCourseFound,
|
|
18
|
+
id: "courseId",
|
|
19
|
+
info: labelCourseInfo,
|
|
20
|
+
label: labelCourse,
|
|
21
|
+
onValueChange: (value) => setCourseId(value),
|
|
22
|
+
options: [{ id: "", code: "" }].map((c) => ({
|
|
23
|
+
id: c.id,
|
|
24
|
+
name: c.code.trim(),
|
|
25
|
+
})),
|
|
26
|
+
placeholder: labelCoursePlaceholder,
|
|
27
|
+
required: true,
|
|
28
|
+
searchEndpoint: ATTENDANCE_API_ROUTES.UNIT,
|
|
29
|
+
searchPlaceholder: labelSearchCourses,
|
|
30
|
+
value: courseId || "",
|
|
31
|
+
});
|
|
18
32
|
// Find the section for the selected course, then get students enrolled in that section
|
|
19
|
-
const studentsInCourse = useMemo(() => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
studentsInCourse.length > 0 &&
|
|
32
|
-
studentsInCourse.map((s) => {
|
|
33
|
-
var _a, _b, _c, _d;
|
|
34
|
-
const student = studentProfiles.find((sp) => sp.id === s);
|
|
35
|
-
return (_jsxs("div", { children: [_jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsxs("div", { className: "flex flex-col items-center justify-center", children: [_jsxs("p", { children: [(_a = student === null || student === void 0 ? void 0 : student.familyMember) === null || _a === void 0 ? void 0 : _a.firstName, " ", (_b = student === null || student === void 0 ? void 0 : student.familyMember) === null || _b === void 0 ? void 0 : _b.lastName] }), _jsx("img", { src: (_c = student === null || student === void 0 ? void 0 : student.familyMember) === null || _c === void 0 ? void 0 : _c.avatar, alt: (_d = student === null || student === void 0 ? void 0 : student.familyMember) === null || _d === void 0 ? void 0 : _d.firstName, width: 100, height: 100, className: "rounded-full" })] }), _jsx("div", { children: _jsx(EnhancedRadio, { label: labelAttendanceStatus, name: "attendanceStatus", value: attendance[s] || "PRESENT", options: [
|
|
33
|
+
// const studentsInCourse = useMemo(() => {
|
|
34
|
+
// const courseObj = courses.find((c) => c.id === courseId);
|
|
35
|
+
// if (!courseObj) return [];
|
|
36
|
+
// return enrollment
|
|
37
|
+
// .filter((e) => e.sectionId === courseObj.sectionId)
|
|
38
|
+
// .map((e) => e.studentProfileId);
|
|
39
|
+
// }, [enrollment, courseId, courses]);
|
|
40
|
+
return (_jsxs("div", { className: "space-y-4", children: [courseIdCombo, courseId &&
|
|
41
|
+
[].length > 0 &&
|
|
42
|
+
[].map((s) => {
|
|
43
|
+
// const student = studentProfiles.find((sp) => sp.id === s);
|
|
44
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsxs("div", { className: "flex flex-col items-center justify-center", children: [_jsx("p", { children: " " }), _jsx("img", { src: "student?.familyMember?.avatar", alt: "student?.familyMember?.firstName", width: 100, height: 100, className: "rounded-full" })] }), _jsx("div", { children: _jsx(EnhancedRadio, { label: labelAttendanceStatus, name: "attendanceStatus", value: attendance[s] || "PRESENT", options: [
|
|
36
45
|
{ label: labelStatusPresent, value: "PRESENT" },
|
|
37
46
|
{ label: labelStatusAbsent, value: "ABSENT" },
|
|
38
47
|
{ label: labelStatusLate, value: "LATE" },
|
|
@@ -397,19 +397,19 @@ export const useCampusModule = () => {
|
|
|
397
397
|
{
|
|
398
398
|
enabled: false,
|
|
399
399
|
handleOnClick: handleMoreActions,
|
|
400
|
-
label: t("
|
|
400
|
+
label: t("actionsButtonMoreActions"),
|
|
401
401
|
order: 0,
|
|
402
402
|
},
|
|
403
403
|
{
|
|
404
404
|
enabled: true,
|
|
405
405
|
handleOnClick: handleFilters,
|
|
406
|
-
label: t("
|
|
406
|
+
label: t("actionsButtonFilters"),
|
|
407
407
|
order: 1,
|
|
408
408
|
},
|
|
409
409
|
{
|
|
410
410
|
enabled: true,
|
|
411
411
|
handleOnClick: handleCreate,
|
|
412
|
-
label: t("
|
|
412
|
+
label: t("actionsButtonAdd"),
|
|
413
413
|
order: 2,
|
|
414
414
|
},
|
|
415
415
|
], [handleCreate, handleFilters, handleMoreActions, t]);
|
|
@@ -417,26 +417,26 @@ export const useCampusModule = () => {
|
|
|
417
417
|
{
|
|
418
418
|
enabled: true,
|
|
419
419
|
handleOnClick: handleView,
|
|
420
|
-
label: t("
|
|
420
|
+
label: t("actionsButtonView"),
|
|
421
421
|
order: 1,
|
|
422
422
|
},
|
|
423
423
|
{
|
|
424
424
|
enabled: (row) => (row === null || row === void 0 ? void 0 : row.enabled) === true,
|
|
425
425
|
handleOnClick: handleEdit,
|
|
426
|
-
label: t("
|
|
426
|
+
label: t("actionsButtonEdit"),
|
|
427
427
|
order: 2,
|
|
428
428
|
},
|
|
429
429
|
{
|
|
430
430
|
enabled: (row) => (row === null || row === void 0 ? void 0 : row.enabled) === false,
|
|
431
431
|
handleOnClick: handleDelete,
|
|
432
|
-
label: t("
|
|
432
|
+
label: t("actionsButtonDelete"),
|
|
433
433
|
order: 3,
|
|
434
434
|
variant: "destructive",
|
|
435
435
|
},
|
|
436
436
|
{
|
|
437
437
|
enabled: false,
|
|
438
438
|
handleOnClick: toggleStatus,
|
|
439
|
-
label: t("
|
|
439
|
+
label: t("actionsButtonToggleStatus"),
|
|
440
440
|
order: 4,
|
|
441
441
|
},
|
|
442
442
|
], [handleDelete, handleEdit, handleView, t, toggleStatus]);
|
|
@@ -22,7 +22,6 @@ export const getCachedClasses = ({ params, }) => getCachedData({
|
|
|
22
22
|
params,
|
|
23
23
|
headers: {
|
|
24
24
|
"Content-Type": "application/json",
|
|
25
|
-
// "x-api-token": process.env.NEXT_PUBLIC_API_KEY!,
|
|
26
25
|
},
|
|
27
26
|
});
|
|
28
27
|
export const getCachedClassById = (classId) => getCachedItemById(LS_KEYS.CLASSES, classId);
|
|
@@ -28,7 +28,6 @@ import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-com
|
|
|
28
28
|
import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
|
|
29
29
|
import { CLASS_API_ROUTES, pageLimit } from "./constants";
|
|
30
30
|
import { classFormValidation } from "./validate";
|
|
31
|
-
import { getCachedClasses, invalidateClassesCache } from "./cache";
|
|
32
31
|
import { getCachedWorkspaceSync } from "../workspace/cache";
|
|
33
32
|
// ============================================================================
|
|
34
33
|
// 1.1 DRAWER TYPES
|
|
@@ -159,7 +158,6 @@ export const useClassModule = () => {
|
|
|
159
158
|
}
|
|
160
159
|
if (data) {
|
|
161
160
|
const isCreated = isCreatedOrUpdated(data);
|
|
162
|
-
invalidateClassesCache();
|
|
163
161
|
showToast(isCreated ? t("messagesCreateSuccess") : t("messagesSaveSuccess"), TOAST_VARIANT.SUCCESS);
|
|
164
162
|
resetFormAndCloseDrawer();
|
|
165
163
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
@@ -184,7 +182,6 @@ export const useClassModule = () => {
|
|
|
184
182
|
return;
|
|
185
183
|
}
|
|
186
184
|
if (data) {
|
|
187
|
-
invalidateClassesCache();
|
|
188
185
|
showToast(t("messagesDeleteSuccess"), TOAST_VARIANT.SUCCESS);
|
|
189
186
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
190
187
|
}
|
|
@@ -378,19 +375,19 @@ export const useClassModule = () => {
|
|
|
378
375
|
{
|
|
379
376
|
enabled: true,
|
|
380
377
|
handleOnClick: handleMoreActions,
|
|
381
|
-
label: t("
|
|
378
|
+
label: t("actionsButtonMoreActions"),
|
|
382
379
|
order: 0,
|
|
383
380
|
},
|
|
384
381
|
{
|
|
385
382
|
enabled: true,
|
|
386
383
|
handleOnClick: handleFilters,
|
|
387
|
-
label: t("
|
|
384
|
+
label: t("actionsButtonFilters"),
|
|
388
385
|
order: 1,
|
|
389
386
|
},
|
|
390
387
|
{
|
|
391
388
|
enabled: true,
|
|
392
389
|
handleOnClick: handleCreate,
|
|
393
|
-
label: t("
|
|
390
|
+
label: t("actionsButtonAdd"),
|
|
394
391
|
order: 2,
|
|
395
392
|
},
|
|
396
393
|
], [handleCreate, handleFilters, handleMoreActions, t]);
|
|
@@ -398,74 +395,39 @@ export const useClassModule = () => {
|
|
|
398
395
|
{
|
|
399
396
|
enabled: true,
|
|
400
397
|
handleOnClick: handleView,
|
|
401
|
-
label: t("
|
|
398
|
+
label: t("actionsButtonView"),
|
|
402
399
|
order: 1,
|
|
403
400
|
},
|
|
404
401
|
{
|
|
405
402
|
enabled: (row) => (row === null || row === void 0 ? void 0 : row.enabled) === true,
|
|
406
403
|
handleOnClick: handleEdit,
|
|
407
|
-
label: t("
|
|
404
|
+
label: t("actionsButtonEdit"),
|
|
408
405
|
order: 2,
|
|
409
406
|
},
|
|
410
407
|
{
|
|
411
408
|
enabled: (row) => (row === null || row === void 0 ? void 0 : row.enabled) === false,
|
|
412
409
|
handleOnClick: handleDelete,
|
|
413
|
-
label: t("
|
|
410
|
+
label: t("actionsButtonDelete"),
|
|
414
411
|
order: 3,
|
|
415
412
|
variant: "destructive",
|
|
416
413
|
},
|
|
417
414
|
{
|
|
418
415
|
enabled: false,
|
|
419
416
|
handleOnClick: toggleStatus,
|
|
420
|
-
label: t("
|
|
417
|
+
label: t("actionsButtonToggleStatus"),
|
|
421
418
|
order: 4,
|
|
422
419
|
},
|
|
423
420
|
], [handleDelete, handleEdit, handleView, t, toggleStatus]);
|
|
424
421
|
// ============================================================================
|
|
425
422
|
// 1.4.9 EFFECTS
|
|
426
423
|
// ============================================================================
|
|
427
|
-
// Always keep the ref current so the main effect can call the latest listFetchNow
|
|
428
|
-
// without including it in the dependency array (listFetchNow changes identity every
|
|
429
|
-
// render because useModuleEntityV2 passes an inline headers object to useFetch).
|
|
430
|
-
// Declared first so the ref is populated before the fetch effect runs.
|
|
431
424
|
useEffect(() => {
|
|
432
425
|
listFetchNowRef.current = listFetchNow;
|
|
433
|
-
});
|
|
434
|
-
// Initial load via cache; re-fetch directly from API on page/pageLimit/filter/search changes.
|
|
435
|
-
// listFetchNow is intentionally excluded from deps — it changes every render due to the
|
|
436
|
-
// inline headers object in useModuleEntityV2. We call it via the stable ref instead.
|
|
426
|
+
}, [listFetchNow]);
|
|
437
427
|
useEffect(() => {
|
|
438
428
|
var _a;
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
const currentPage = Number(listParams.currentPage) || 1;
|
|
442
|
-
const currentPageLimit = Number(listParams.pageLimit) || pageLimit;
|
|
443
|
-
const isDefaultLoad = currentPage === 1 &&
|
|
444
|
-
currentPageLimit === pageLimit &&
|
|
445
|
-
!listParams.searchQuery &&
|
|
446
|
-
listParams.filterEnabled === undefined;
|
|
447
|
-
if (isDefaultLoad) {
|
|
448
|
-
(async () => {
|
|
449
|
-
try {
|
|
450
|
-
const { count, items } = await getCachedClasses({
|
|
451
|
-
params: listParams,
|
|
452
|
-
});
|
|
453
|
-
dispatch({
|
|
454
|
-
type: CLASS_ACTION_TYPES.SET_ITEMS,
|
|
455
|
-
payload: { items: items || [], count: count || 0 },
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
catch (_a) {
|
|
459
|
-
showToast(t("messagesFetchFailed"), TOAST_VARIANT.ERROR);
|
|
460
|
-
}
|
|
461
|
-
})();
|
|
462
|
-
}
|
|
463
|
-
else {
|
|
464
|
-
// Bypass cache for pagination, pageLimit, filter and search changes.
|
|
465
|
-
// Use ref to avoid the infinite-loop caused by listFetchNow's unstable identity.
|
|
466
|
-
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
467
|
-
}
|
|
468
|
-
}, [dispatch, listParams, schoolId, showToast, t]);
|
|
429
|
+
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
430
|
+
}, [listParams]);
|
|
469
431
|
// ============================================================================
|
|
470
432
|
// 1.4.10 RETURN
|
|
471
433
|
// ============================================================================
|
|
@@ -7,7 +7,6 @@ import converter from "json-2-csv";
|
|
|
7
7
|
import { Timeline } from "../../components/timeline";
|
|
8
8
|
import { useTranslations } from "next-intl";
|
|
9
9
|
import { CLASS_API_ROUTES, pageLimit } from "./constants";
|
|
10
|
-
import { invalidateClassesCache } from "./cache";
|
|
11
10
|
import { CLASS_ACTION_TYPES, useClassContext } from "./context";
|
|
12
11
|
import { useRef, useEffect, useCallback } from "react";
|
|
13
12
|
const workspace = getCachedWorkspaceSync();
|
|
@@ -68,13 +67,17 @@ async function pollBulkJob(jobId, signal, onProgress) {
|
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
}
|
|
71
|
-
function formatErrorSummary(
|
|
70
|
+
function formatErrorSummary(
|
|
71
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
|
+
t, errors) {
|
|
72
73
|
if (!(errors === null || errors === void 0 ? void 0 : errors.length))
|
|
73
74
|
return "";
|
|
74
|
-
const lines = errors
|
|
75
|
+
const lines = errors
|
|
76
|
+
.slice(0, 5)
|
|
77
|
+
.map((e) => t("messagesBulkRowError", { row: e.row, error: e.error }));
|
|
75
78
|
const remaining = errors.length - 5;
|
|
76
79
|
if (remaining > 0)
|
|
77
|
-
lines.push(
|
|
80
|
+
lines.push(t("messagesBulkMoreRows", { count: remaining }));
|
|
78
81
|
return lines.join("\n");
|
|
79
82
|
}
|
|
80
83
|
export const ClassMoreActions = () => {
|
|
@@ -107,7 +110,7 @@ export const ClassMoreActions = () => {
|
|
|
107
110
|
const text = await file.text();
|
|
108
111
|
const records = converter.csv2json(text);
|
|
109
112
|
if (!Array.isArray(records) || records.length === 0) {
|
|
110
|
-
showErrorToast("
|
|
113
|
+
showErrorToast(t("messagesBulkCsvEmpty"));
|
|
111
114
|
return;
|
|
112
115
|
}
|
|
113
116
|
// Client-side validation — basic required field check
|
|
@@ -117,55 +120,72 @@ export const ClassMoreActions = () => {
|
|
|
117
120
|
const msgs = [];
|
|
118
121
|
if (method === "POST") {
|
|
119
122
|
if (!((_b = row.code) === null || _b === void 0 ? void 0 : _b.trim()))
|
|
120
|
-
msgs.push("
|
|
123
|
+
msgs.push(t("validationRequiredCode"));
|
|
121
124
|
if (!((_c = row.name) === null || _c === void 0 ? void 0 : _c.trim()))
|
|
122
|
-
msgs.push("
|
|
125
|
+
msgs.push(t("validationRequiredName"));
|
|
123
126
|
}
|
|
124
127
|
else {
|
|
125
128
|
if (!((_d = row.id) === null || _d === void 0 ? void 0 : _d.trim()))
|
|
126
|
-
msgs.push("
|
|
129
|
+
msgs.push(t("validationRequiredIdForUpdate"));
|
|
127
130
|
}
|
|
128
131
|
if (msgs.length > 0) {
|
|
129
132
|
validationErrors.push({ row: i + 1, messages: msgs });
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
if (validationErrors.length > 0) {
|
|
133
|
-
const
|
|
136
|
+
const errorsList = validationErrors
|
|
134
137
|
.slice(0, 5)
|
|
135
|
-
.map((e) =>
|
|
138
|
+
.map((e) => t("messagesBulkRowError", {
|
|
139
|
+
row: e.row,
|
|
140
|
+
error: e.messages.join("; "),
|
|
141
|
+
}))
|
|
136
142
|
.join("\n");
|
|
137
143
|
const remaining = validationErrors.length - 5;
|
|
138
|
-
|
|
144
|
+
const errorsStr = remaining > 0
|
|
145
|
+
? `${errorsList}\n${t("messagesBulkMoreRows", { count: remaining })}`
|
|
146
|
+
: errorsList;
|
|
147
|
+
showErrorToast(t("messagesBulkValidationFailed", {
|
|
148
|
+
count: validationErrors.length,
|
|
149
|
+
errors: errorsStr,
|
|
150
|
+
}));
|
|
139
151
|
return;
|
|
140
152
|
}
|
|
141
153
|
try {
|
|
142
|
-
showInfoToast(
|
|
154
|
+
showInfoToast(t("messagesBulkJobQueued", { action: label, count: records.length }));
|
|
143
155
|
let jobId;
|
|
144
156
|
try {
|
|
145
157
|
jobId = await submitBulkJob(text, method, signal);
|
|
146
158
|
}
|
|
147
159
|
catch (submitError) {
|
|
148
|
-
showErrorToast(
|
|
160
|
+
showErrorToast(t("messagesBulkJobSubmitFailed", {
|
|
161
|
+
action: label,
|
|
162
|
+
error: submitError instanceof Error
|
|
163
|
+
? submitError.message
|
|
164
|
+
: t("unknownError"),
|
|
165
|
+
}));
|
|
149
166
|
return;
|
|
150
167
|
}
|
|
151
168
|
const status = await pollBulkJob(jobId, signal, (processed, total) => {
|
|
152
|
-
showInfoToast(
|
|
169
|
+
showInfoToast(t("messagesBulkProgress", { processed, total }));
|
|
153
170
|
});
|
|
154
171
|
if (signal.aborted)
|
|
155
172
|
return;
|
|
156
173
|
if (status.status === "completed") {
|
|
157
174
|
const r = status.results;
|
|
158
175
|
if (r && ((_e = r.errors) === null || _e === void 0 ? void 0 : _e.length) > 0) {
|
|
159
|
-
const summary = formatErrorSummary(r.errors);
|
|
160
|
-
showSuccessToast(
|
|
176
|
+
const summary = formatErrorSummary(t, r.errors);
|
|
177
|
+
showSuccessToast(`${t("messagesBulkResults", { created: r.created, updated: r.updated, skipped: r.skipped })}\n${summary}`);
|
|
161
178
|
}
|
|
162
179
|
else if (r) {
|
|
163
|
-
showSuccessToast(
|
|
180
|
+
showSuccessToast(t("messagesBulkResults", {
|
|
181
|
+
created: r.created,
|
|
182
|
+
updated: r.updated,
|
|
183
|
+
skipped: r.skipped,
|
|
184
|
+
}));
|
|
164
185
|
}
|
|
165
186
|
else {
|
|
166
|
-
showSuccessToast("
|
|
187
|
+
showSuccessToast(t("messagesBulkSuccess"));
|
|
167
188
|
}
|
|
168
|
-
invalidateClassesCache();
|
|
169
189
|
const schoolId = ((_f = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _f === void 0 ? void 0 : _f.id) || "";
|
|
170
190
|
fetch(`${CLASS_API_ROUTES.LIST}?currentPage=1&pageLimit=${pageLimit}&schoolId=${schoolId}`, {
|
|
171
191
|
headers: {
|
|
@@ -191,17 +211,20 @@ export const ClassMoreActions = () => {
|
|
|
191
211
|
else {
|
|
192
212
|
const r = status.results;
|
|
193
213
|
const detail = ((_g = r === null || r === void 0 ? void 0 : r.errors) === null || _g === void 0 ? void 0 : _g.length)
|
|
194
|
-
? formatErrorSummary(r.errors)
|
|
195
|
-
: "
|
|
196
|
-
showErrorToast(
|
|
214
|
+
? formatErrorSummary(t, r.errors)
|
|
215
|
+
: t("unknownError");
|
|
216
|
+
showErrorToast(`${t("messagesBulkFailed", { action: label })}\n${detail}`);
|
|
197
217
|
}
|
|
198
218
|
}
|
|
199
219
|
catch (error) {
|
|
200
220
|
if (error.message === "Polling cancelled")
|
|
201
221
|
return;
|
|
202
|
-
showErrorToast(
|
|
222
|
+
showErrorToast(t("messagesBulkFailedDetail", {
|
|
223
|
+
action: label,
|
|
224
|
+
error: error instanceof Error ? error.message : t("unknownError"),
|
|
225
|
+
}));
|
|
203
226
|
}
|
|
204
|
-
}, [dispatch]);
|
|
227
|
+
}, [dispatch, t]);
|
|
205
228
|
const handleBulkCreate = useCallback((files) => handleBulkFlow(files, "POST"), [handleBulkFlow]);
|
|
206
229
|
const handleBulkUpdate = useCallback((files) => handleBulkFlow(files, "PUT"), [handleBulkFlow]);
|
|
207
230
|
const create = [
|
|
@@ -25,7 +25,6 @@ import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
|
|
|
25
25
|
import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
|
|
26
26
|
import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
|
|
27
27
|
import { COURSE_API_ROUTES, pageLimit } from "./constants";
|
|
28
|
-
import { getCachedCourses, invalidateCoursesCache } from "./cache";
|
|
29
28
|
import { courseFormValidation } from "./validate";
|
|
30
29
|
import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
|
|
31
30
|
import { getCachedWorkspaceSync } from "../workspace/cache";
|
|
@@ -167,7 +166,6 @@ export const useCourseModule = () => {
|
|
|
167
166
|
showToast(isCreatedOrUpdated(data)
|
|
168
167
|
? t("messagesCourseCreated")
|
|
169
168
|
: t("messagesCourseUpdated"), TOAST_VARIANT.SUCCESS);
|
|
170
|
-
invalidateCoursesCache();
|
|
171
169
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
172
170
|
resetFormAndCloseDrawer();
|
|
173
171
|
}
|
|
@@ -247,7 +245,6 @@ export const useCourseModule = () => {
|
|
|
247
245
|
}
|
|
248
246
|
if (data) {
|
|
249
247
|
showToast(t("messagesCourseDeleted"), TOAST_VARIANT.SUCCESS);
|
|
250
|
-
invalidateCoursesCache();
|
|
251
248
|
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
252
249
|
}
|
|
253
250
|
}, [showToast, t]);
|
|
@@ -456,44 +453,13 @@ export const useCourseModule = () => {
|
|
|
456
453
|
// ==========================================================================
|
|
457
454
|
// 1.4.9 EFFECTS
|
|
458
455
|
// ==========================================================================
|
|
459
|
-
// Keep the latest fetch function in a ref so the fetch effect can call it
|
|
460
|
-
// without depending on listFetchNow's unstable identity.
|
|
461
456
|
useEffect(() => {
|
|
462
457
|
listFetchNowRef.current = listFetchNow;
|
|
463
|
-
});
|
|
464
|
-
// Initial load via cache; re-fetch directly from API on page/pageLimit/filter/search changes.
|
|
458
|
+
}, [listFetchNow]);
|
|
465
459
|
useEffect(() => {
|
|
466
460
|
var _a;
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
const currentPage = Number(listParams.currentPage) || 1;
|
|
470
|
-
const currentPageLimit = Number(listParams.pageLimit) || pageLimit;
|
|
471
|
-
const isDefaultLoad = currentPage === 1 &&
|
|
472
|
-
currentPageLimit === pageLimit &&
|
|
473
|
-
!listParams.searchQuery &&
|
|
474
|
-
listParams.filterEnabled === undefined;
|
|
475
|
-
if (isDefaultLoad) {
|
|
476
|
-
(async () => {
|
|
477
|
-
try {
|
|
478
|
-
const { count, items } = await getCachedCourses({
|
|
479
|
-
params: listParams,
|
|
480
|
-
});
|
|
481
|
-
dispatch({
|
|
482
|
-
type: COURSE_ACTION_TYPES.SET_ITEMS,
|
|
483
|
-
payload: { items: items || [], count: count || 0 },
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
catch (_a) {
|
|
487
|
-
showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
|
|
488
|
-
}
|
|
489
|
-
})();
|
|
490
|
-
}
|
|
491
|
-
else {
|
|
492
|
-
// Bypass cache for pagination, pageLimit, filter and search changes.
|
|
493
|
-
// Use ref to avoid the infinite-loop caused by listFetchNow's unstable identity.
|
|
494
|
-
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
495
|
-
}
|
|
496
|
-
}, [listParams, dispatch, showToast, schoolId, t]);
|
|
461
|
+
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
462
|
+
}, [listParams]);
|
|
497
463
|
// ==========================================================================
|
|
498
464
|
// 1.4.10 RETURN
|
|
499
465
|
// ==========================================================================
|