@appcorp/fusion-storybook 0.1.35 → 0.1.37
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/attendance/cache.d.ts +14 -0
- package/base-modules/attendance/cache.js +31 -0
- package/base-modules/attendance/constants.d.ts +17 -0
- package/base-modules/attendance/constants.js +29 -0
- package/base-modules/attendance/context.d.ts +167 -0
- package/base-modules/attendance/context.js +412 -0
- package/base-modules/attendance/filter.d.ts +8 -0
- package/base-modules/attendance/filter.js +21 -0
- package/base-modules/attendance/form.d.ts +1 -0
- package/base-modules/attendance/form.js +22 -0
- package/base-modules/attendance/more-actions.d.ts +19 -0
- package/base-modules/attendance/more-actions.js +40 -0
- package/base-modules/attendance/page.d.ts +46 -0
- package/base-modules/attendance/page.js +179 -0
- package/base-modules/attendance/validate.d.ts +9 -0
- package/base-modules/attendance/validate.js +9 -0
- package/base-modules/attendance/view.d.ts +4 -0
- package/base-modules/attendance/view.js +29 -0
- package/base-modules/course/cache.d.ts +14 -0
- package/base-modules/course/cache.js +31 -0
- package/base-modules/course/constants.d.ts +11 -0
- package/base-modules/course/constants.js +17 -0
- package/base-modules/course/context.d.ts +155 -0
- package/base-modules/course/context.js +432 -0
- package/base-modules/course/filter.d.ts +1 -0
- package/base-modules/course/filter.js +27 -0
- package/base-modules/course/form.d.ts +1 -0
- package/base-modules/course/form.js +36 -0
- package/base-modules/course/more-actions.d.ts +1 -0
- package/base-modules/course/more-actions.js +59 -0
- package/base-modules/course/page.d.ts +31 -0
- package/base-modules/course/page.js +138 -0
- package/base-modules/course/validate.d.ts +13 -0
- package/base-modules/course/validate.js +16 -0
- package/base-modules/course/view.d.ts +1 -0
- package/base-modules/course/view.js +40 -0
- package/base-modules/enrollment/cache.d.ts +14 -0
- package/base-modules/enrollment/cache.js +31 -0
- package/base-modules/enrollment/constants.d.ts +11 -0
- package/base-modules/enrollment/constants.js +17 -0
- package/base-modules/enrollment/context.d.ts +167 -0
- package/base-modules/enrollment/context.js +416 -0
- package/base-modules/enrollment/filter.d.ts +1 -0
- package/base-modules/enrollment/filter.js +30 -0
- package/base-modules/enrollment/form.d.ts +1 -0
- package/base-modules/enrollment/form.js +43 -0
- package/base-modules/enrollment/more-actions.d.ts +1 -0
- package/base-modules/enrollment/more-actions.js +62 -0
- package/base-modules/enrollment/page.d.ts +32 -0
- package/base-modules/enrollment/page.js +145 -0
- package/base-modules/enrollment/validate.d.ts +13 -0
- package/base-modules/enrollment/validate.js +19 -0
- package/base-modules/enrollment/view.d.ts +1 -0
- package/base-modules/enrollment/view.js +44 -0
- package/package.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attendance Module Cache Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides localStorage-based caching for attendances using generic cache system.
|
|
5
|
+
*/
|
|
6
|
+
import { AttendanceBE } from "../../type";
|
|
7
|
+
export declare const getCachedAttendancesSync: () => import("@react-pakistan/util-functions").ListResponse<AttendanceBE>;
|
|
8
|
+
export declare const getCachedAttendances: ({ params, }: {
|
|
9
|
+
params: Record<string, unknown>;
|
|
10
|
+
}) => Promise<import("@react-pakistan/util-functions").ListResponse<AttendanceBE>>;
|
|
11
|
+
export declare const getCachedAttendanceById: (attendanceId: string) => AttendanceBE | null;
|
|
12
|
+
export declare const invalidateAttendancesCache: () => void;
|
|
13
|
+
export declare const preloadAttendances: () => Promise<import("@react-pakistan/util-functions").ListResponse<AttendanceBE>>;
|
|
14
|
+
export declare const isAttendancesCacheStale: () => boolean;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attendance Module Cache Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides localStorage-based caching for attendances using generic cache system.
|
|
5
|
+
*/
|
|
6
|
+
import { LS_KEYS } from "../../constants";
|
|
7
|
+
import { ATTENDANCE_API_ROUTES } from "./constants";
|
|
8
|
+
import { getCachedData, getCachedDataSync, getCachedItemById, invalidateCache, isCacheStale, preloadCache, } from "@react-pakistan/util-functions";
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// CACHE CONFIGURATION
|
|
11
|
+
// ============================================================================
|
|
12
|
+
const ATTENDANCE_CACHE_CONFIG = {
|
|
13
|
+
cacheKey: LS_KEYS.ATTENDANCES,
|
|
14
|
+
apiUrl: ATTENDANCE_API_ROUTES.UNIT,
|
|
15
|
+
};
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// ATTENDANCE-SPECIFIC CACHE FUNCTIONS
|
|
18
|
+
// ============================================================================
|
|
19
|
+
export const getCachedAttendancesSync = () => getCachedDataSync(LS_KEYS.ATTENDANCES);
|
|
20
|
+
export const getCachedAttendances = ({ params, }) => getCachedData({
|
|
21
|
+
config: ATTENDANCE_CACHE_CONFIG,
|
|
22
|
+
params,
|
|
23
|
+
headers: {
|
|
24
|
+
"Content-Type": "application/json",
|
|
25
|
+
"x-api-token": process.env.NEXT_PUBLIC_API_KEY,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
export const getCachedAttendanceById = (attendanceId) => getCachedItemById(LS_KEYS.ATTENDANCES, attendanceId);
|
|
29
|
+
export const invalidateAttendancesCache = () => invalidateCache(LS_KEYS.ATTENDANCES);
|
|
30
|
+
export const preloadAttendances = () => preloadCache(ATTENDANCE_CACHE_CONFIG);
|
|
31
|
+
export const isAttendancesCacheStale = () => isCacheStale(LS_KEYS.ATTENDANCES);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attendance Constants
|
|
3
|
+
*
|
|
4
|
+
* Organization:
|
|
5
|
+
* - Page Configuration
|
|
6
|
+
* - API Routes
|
|
7
|
+
* - Status Options
|
|
8
|
+
*/
|
|
9
|
+
import { ATTENDANCE_STATUS } from "../../type";
|
|
10
|
+
export declare const pageLimit: number;
|
|
11
|
+
export declare const ATTENDANCE_API_ROUTES: {
|
|
12
|
+
readonly UNIT: "/api/v1/attendance";
|
|
13
|
+
};
|
|
14
|
+
export declare const ATTENDANCE_STATUS_OPTIONS: {
|
|
15
|
+
label: string;
|
|
16
|
+
value: ATTENDANCE_STATUS;
|
|
17
|
+
}[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Attendance Constants
|
|
3
|
+
*
|
|
4
|
+
* Organization:
|
|
5
|
+
* - Page Configuration
|
|
6
|
+
* - API Routes
|
|
7
|
+
* - Status Options
|
|
8
|
+
*/
|
|
9
|
+
import { ATTENDANCE_STATUS } from "../../type";
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// PAGE CONFIGURATION
|
|
12
|
+
// ============================================================================
|
|
13
|
+
export const pageLimit = Number(process.env.NEXT_PUBLIC_PAGE_LIMIT) || 10;
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// API ROUTES
|
|
16
|
+
// ============================================================================
|
|
17
|
+
export const ATTENDANCE_API_ROUTES = {
|
|
18
|
+
UNIT: "/api/v1/attendance",
|
|
19
|
+
};
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// STATUS OPTIONS
|
|
22
|
+
// ============================================================================
|
|
23
|
+
export const ATTENDANCE_STATUS_OPTIONS = [
|
|
24
|
+
{ label: "Present", value: ATTENDANCE_STATUS.PRESENT },
|
|
25
|
+
{ label: "Absent", value: ATTENDANCE_STATUS.ABSENT },
|
|
26
|
+
{ label: "Late", value: ATTENDANCE_STATUS.LATE },
|
|
27
|
+
{ label: "Excused", value: ATTENDANCE_STATUS.EXCUSED },
|
|
28
|
+
{ label: "Half Day", value: ATTENDANCE_STATUS.HALF_DAY },
|
|
29
|
+
];
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { RowAction, TableRow } from "@appcorp/shadcn/components/enhanced-table";
|
|
2
|
+
import { AttendanceBE, ATTENDANCE_STATUS, SchoolBE, StudentProfileBE } from "../../type";
|
|
3
|
+
export declare const ATTENDANCE_DRAWER: {
|
|
4
|
+
readonly FILTER_DRAWER: string;
|
|
5
|
+
readonly FORM_DRAWER: string;
|
|
6
|
+
readonly MORE_ACTIONS_DRAWER: string;
|
|
7
|
+
readonly VIEW_DRAWER: string;
|
|
8
|
+
};
|
|
9
|
+
export declare const ATTENDANCE_ACTION_TYPES: {
|
|
10
|
+
readonly RESET_FORM: "RESET_FORM";
|
|
11
|
+
readonly SET_CURRENT_PAGE: "SET_CURRENT_PAGE";
|
|
12
|
+
readonly SET_PAGE_LIMIT: "SET_PAGE_LIMIT";
|
|
13
|
+
readonly SET_SEARCH_QUERY: "SET_SEARCH_QUERY";
|
|
14
|
+
readonly SET_DRAWER: "SET_DRAWER";
|
|
15
|
+
readonly SET_ITEMS: "SET_ITEMS";
|
|
16
|
+
readonly SET_FORM_DATA: "SET_FORM_DATA";
|
|
17
|
+
readonly SET_DISABLE_SAVE_BUTTON: "SET_DISABLE_SAVE_BUTTON";
|
|
18
|
+
readonly SET_INPUT_FIELD: "SET_INPUT_FIELD";
|
|
19
|
+
readonly SET_ERRORS: "SET_ERRORS";
|
|
20
|
+
readonly SET_FILTERS: "SET_FILTERS";
|
|
21
|
+
}, attendanceModuleConfig: import("@react-pakistan/util-functions/factory/generic-module-factory").ModuleConfig<{
|
|
22
|
+
items: AttendanceBE[];
|
|
23
|
+
count: number;
|
|
24
|
+
currentPage: number;
|
|
25
|
+
pageLimit: number;
|
|
26
|
+
searchQuery: string;
|
|
27
|
+
disableSaveButton: boolean;
|
|
28
|
+
drawer: string | null;
|
|
29
|
+
date: string;
|
|
30
|
+
enabled: boolean;
|
|
31
|
+
errors: Record<string, string>;
|
|
32
|
+
filterEnabled: boolean | undefined;
|
|
33
|
+
id: string;
|
|
34
|
+
remarks: string;
|
|
35
|
+
schoolId: string;
|
|
36
|
+
status: ATTENDANCE_STATUS;
|
|
37
|
+
studentProfileId: string;
|
|
38
|
+
school: SchoolBE | undefined;
|
|
39
|
+
studentProfile: StudentProfileBE | undefined;
|
|
40
|
+
}>, initialAttendanceState: {
|
|
41
|
+
items: AttendanceBE[];
|
|
42
|
+
count: number;
|
|
43
|
+
currentPage: number;
|
|
44
|
+
pageLimit: number;
|
|
45
|
+
searchQuery: string;
|
|
46
|
+
disableSaveButton: boolean;
|
|
47
|
+
drawer: string | null;
|
|
48
|
+
date: string;
|
|
49
|
+
enabled: boolean;
|
|
50
|
+
errors: Record<string, string>;
|
|
51
|
+
filterEnabled: boolean | undefined;
|
|
52
|
+
id: string;
|
|
53
|
+
remarks: string;
|
|
54
|
+
schoolId: string;
|
|
55
|
+
status: ATTENDANCE_STATUS;
|
|
56
|
+
studentProfileId: string;
|
|
57
|
+
school: SchoolBE | undefined;
|
|
58
|
+
studentProfile: StudentProfileBE | undefined;
|
|
59
|
+
}, AttendanceProvider: import("react").FC<{
|
|
60
|
+
children: React.ReactNode;
|
|
61
|
+
}>, attendanceReducer: (state: {
|
|
62
|
+
items: AttendanceBE[];
|
|
63
|
+
count: number;
|
|
64
|
+
currentPage: number;
|
|
65
|
+
pageLimit: number;
|
|
66
|
+
searchQuery: string;
|
|
67
|
+
disableSaveButton: boolean;
|
|
68
|
+
drawer: string | null;
|
|
69
|
+
date: string;
|
|
70
|
+
enabled: boolean;
|
|
71
|
+
errors: Record<string, string>;
|
|
72
|
+
filterEnabled: boolean | undefined;
|
|
73
|
+
id: string;
|
|
74
|
+
remarks: string;
|
|
75
|
+
schoolId: string;
|
|
76
|
+
status: ATTENDANCE_STATUS;
|
|
77
|
+
studentProfileId: string;
|
|
78
|
+
school: SchoolBE | undefined;
|
|
79
|
+
studentProfile: StudentProfileBE | undefined;
|
|
80
|
+
}, action: any) => {
|
|
81
|
+
items: AttendanceBE[];
|
|
82
|
+
count: number;
|
|
83
|
+
currentPage: number;
|
|
84
|
+
pageLimit: number;
|
|
85
|
+
searchQuery: string;
|
|
86
|
+
disableSaveButton: boolean;
|
|
87
|
+
drawer: string | null;
|
|
88
|
+
date: string;
|
|
89
|
+
enabled: boolean;
|
|
90
|
+
errors: Record<string, string>;
|
|
91
|
+
filterEnabled: boolean | undefined;
|
|
92
|
+
id: string;
|
|
93
|
+
remarks: string;
|
|
94
|
+
schoolId: string;
|
|
95
|
+
status: ATTENDANCE_STATUS;
|
|
96
|
+
studentProfileId: string;
|
|
97
|
+
school: SchoolBE | undefined;
|
|
98
|
+
studentProfile: StudentProfileBE | undefined;
|
|
99
|
+
}, useAttendanceContext: () => import("@react-pakistan/util-functions/factory/generic-module-factory").GenericModuleContext<{
|
|
100
|
+
items: AttendanceBE[];
|
|
101
|
+
count: number;
|
|
102
|
+
currentPage: number;
|
|
103
|
+
pageLimit: number;
|
|
104
|
+
searchQuery: string;
|
|
105
|
+
disableSaveButton: boolean;
|
|
106
|
+
drawer: string | null;
|
|
107
|
+
date: string;
|
|
108
|
+
enabled: boolean;
|
|
109
|
+
errors: Record<string, string>;
|
|
110
|
+
filterEnabled: boolean | undefined;
|
|
111
|
+
id: string;
|
|
112
|
+
remarks: string;
|
|
113
|
+
schoolId: string;
|
|
114
|
+
status: ATTENDANCE_STATUS;
|
|
115
|
+
studentProfileId: string;
|
|
116
|
+
school: SchoolBE | undefined;
|
|
117
|
+
studentProfile: StudentProfileBE | undefined;
|
|
118
|
+
}>;
|
|
119
|
+
export declare const useAttendanceModule: () => {
|
|
120
|
+
applyFilters: () => void;
|
|
121
|
+
byIdLoading: boolean;
|
|
122
|
+
clearFilters: () => void;
|
|
123
|
+
deleteLoading: boolean;
|
|
124
|
+
handleChange: (field: string, value: string | number | boolean | undefined) => void;
|
|
125
|
+
handleCloseDrawer: () => void;
|
|
126
|
+
handleCreate: () => void;
|
|
127
|
+
handleDelete: (row?: TableRow) => void;
|
|
128
|
+
handleEdit: (row?: TableRow) => void;
|
|
129
|
+
handleFilters: () => void;
|
|
130
|
+
handleMoreActions: () => void;
|
|
131
|
+
handlePageChange: (page: number) => void;
|
|
132
|
+
handlePageLimitChange: (limit: number) => void;
|
|
133
|
+
handleSearch: (query: string) => void;
|
|
134
|
+
handleSubmit: () => void;
|
|
135
|
+
handleView: (row?: TableRow) => void;
|
|
136
|
+
headerActions: {
|
|
137
|
+
enabled: boolean;
|
|
138
|
+
handleOnClick: () => void;
|
|
139
|
+
icon: import("react").ForwardRefExoticComponent<Omit<import("lucide-react").LucideProps, "ref"> & import("react").RefAttributes<SVGSVGElement>>;
|
|
140
|
+
label: string;
|
|
141
|
+
order: number;
|
|
142
|
+
}[];
|
|
143
|
+
listLoading: boolean;
|
|
144
|
+
rowActions: RowAction[];
|
|
145
|
+
updateLoading: boolean;
|
|
146
|
+
state: {
|
|
147
|
+
items: AttendanceBE[];
|
|
148
|
+
count: number;
|
|
149
|
+
currentPage: number;
|
|
150
|
+
pageLimit: number;
|
|
151
|
+
searchQuery: string;
|
|
152
|
+
disableSaveButton: boolean;
|
|
153
|
+
drawer: string | null;
|
|
154
|
+
date: string;
|
|
155
|
+
enabled: boolean;
|
|
156
|
+
errors: Record<string, string>;
|
|
157
|
+
filterEnabled: boolean | undefined;
|
|
158
|
+
id: string;
|
|
159
|
+
remarks: string;
|
|
160
|
+
schoolId: string;
|
|
161
|
+
status: ATTENDANCE_STATUS;
|
|
162
|
+
studentProfileId: string;
|
|
163
|
+
school: SchoolBE | undefined;
|
|
164
|
+
studentProfile: StudentProfileBE | undefined;
|
|
165
|
+
};
|
|
166
|
+
dispatch: React.Dispatch<any>;
|
|
167
|
+
};
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
/**
|
|
3
|
+
* Attendance Module — business logic + API integration
|
|
4
|
+
*
|
|
5
|
+
* This module wires the generic module state (created by
|
|
6
|
+
* `createGenericModule`) to network actions using `useModuleEntityV2`.
|
|
7
|
+
* It contains the domain-specific handlers (create/view/edit/delete),
|
|
8
|
+
* local validation wiring, and optimistic UI helpers.
|
|
9
|
+
*
|
|
10
|
+
* Key responsibilities:
|
|
11
|
+
* - expose `useAttendanceModule()` which UI components call for actions
|
|
12
|
+
* - keep the module-specific `apiParams` and callbacks in one place
|
|
13
|
+
* - ensure cache invalidation and toast notifications on mutation
|
|
14
|
+
*
|
|
15
|
+
* Exported utilities:
|
|
16
|
+
* - `AttendanceProvider` — provider component used by the page
|
|
17
|
+
* - `useAttendanceModule()` — hook that returns handlers and state
|
|
18
|
+
*/
|
|
19
|
+
import { useCallback, useEffect, useMemo } from "react";
|
|
20
|
+
import { isCreatedOrUpdated, validateForm, } from "@react-pakistan/util-functions";
|
|
21
|
+
import { useModuleEntityV2, } from "@react-pakistan/util-functions/hooks/use-module-entity-v2";
|
|
22
|
+
import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
|
|
23
|
+
import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
|
|
24
|
+
import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
|
|
25
|
+
import { ATTENDANCE_API_ROUTES, pageLimit } from "./constants";
|
|
26
|
+
import { getCachedAttendances, invalidateAttendancesCache } from "./cache";
|
|
27
|
+
import { attendanceFormValidation } from "./validate";
|
|
28
|
+
import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
|
|
29
|
+
import { Edit, Eye, Filter, MoreHorizontal, Plus } from "lucide-react";
|
|
30
|
+
import { ATTENDANCE_STATUS, } from "../../type";
|
|
31
|
+
import { getCachedWorkspaceSync } from "../workspace/cache";
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// DRAWER TYPES
|
|
34
|
+
// ============================================================================
|
|
35
|
+
export const ATTENDANCE_DRAWER = {
|
|
36
|
+
FILTER_DRAWER: DRAWER_TYPES.FILTER_DRAWER,
|
|
37
|
+
FORM_DRAWER: DRAWER_TYPES.FORM_DRAWER,
|
|
38
|
+
MORE_ACTIONS_DRAWER: "MORE_ACTIONS_DRAWER",
|
|
39
|
+
VIEW_DRAWER: DRAWER_TYPES.VIEW_DRAWER,
|
|
40
|
+
};
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// CONFIGURATION
|
|
43
|
+
// ============================================================================
|
|
44
|
+
const attendanceConfig = {
|
|
45
|
+
name: "Attendance",
|
|
46
|
+
displayName: "Attendance",
|
|
47
|
+
initialState: {
|
|
48
|
+
// List Data
|
|
49
|
+
items: [],
|
|
50
|
+
count: 0,
|
|
51
|
+
// Search & Pagination
|
|
52
|
+
currentPage: 1,
|
|
53
|
+
pageLimit,
|
|
54
|
+
searchQuery: "",
|
|
55
|
+
// UI State
|
|
56
|
+
disableSaveButton: false,
|
|
57
|
+
drawer: null,
|
|
58
|
+
// Form State
|
|
59
|
+
date: new Date().toISOString().split("T")[0],
|
|
60
|
+
enabled: true,
|
|
61
|
+
errors: {},
|
|
62
|
+
filterEnabled: undefined,
|
|
63
|
+
id: "",
|
|
64
|
+
remarks: "",
|
|
65
|
+
schoolId: "",
|
|
66
|
+
status: ATTENDANCE_STATUS.PRESENT,
|
|
67
|
+
studentProfileId: "",
|
|
68
|
+
// Relations (populated from byId fetch)
|
|
69
|
+
school: undefined,
|
|
70
|
+
studentProfile: undefined,
|
|
71
|
+
},
|
|
72
|
+
drawerTypes: DRAWER_TYPES,
|
|
73
|
+
};
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// CREATE ATTENDANCE MODULE
|
|
76
|
+
// ============================================================================
|
|
77
|
+
export const { actionTypes: ATTENDANCE_ACTION_TYPES, config: attendanceModuleConfig, initialState: initialAttendanceState, Provider: AttendanceProvider, reducer: attendanceReducer, useContext: useAttendanceContext, } = createGenericModule(attendanceConfig);
|
|
78
|
+
// ============================================================================
|
|
79
|
+
// ENHANCED ATTENDANCE HOOK WITH API INTEGRATION
|
|
80
|
+
// ============================================================================
|
|
81
|
+
export const useAttendanceModule = () => {
|
|
82
|
+
var _a;
|
|
83
|
+
const context = useAttendanceContext();
|
|
84
|
+
const { state, dispatch } = context;
|
|
85
|
+
const debouncedQuery = useDebounce(state.searchQuery, 800);
|
|
86
|
+
const workspace = getCachedWorkspaceSync();
|
|
87
|
+
const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
|
|
88
|
+
// ============================================================================
|
|
89
|
+
// API PARAMETERS
|
|
90
|
+
// ============================================================================
|
|
91
|
+
const listParams = useMemo(() => (Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterEnabled !== undefined
|
|
92
|
+
? { filterEnabled: String(state.filterEnabled) }
|
|
93
|
+
: {}))), [
|
|
94
|
+
state.currentPage,
|
|
95
|
+
state.filterEnabled,
|
|
96
|
+
state.pageLimit,
|
|
97
|
+
debouncedQuery,
|
|
98
|
+
schoolId,
|
|
99
|
+
]);
|
|
100
|
+
const updateParams = useMemo(() => ({
|
|
101
|
+
date: state.date,
|
|
102
|
+
enabled: state.enabled,
|
|
103
|
+
id: state.id,
|
|
104
|
+
remarks: state.remarks,
|
|
105
|
+
schoolId,
|
|
106
|
+
status: state.status,
|
|
107
|
+
studentProfileId: state.studentProfileId,
|
|
108
|
+
}), [state, schoolId]);
|
|
109
|
+
const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
|
|
110
|
+
const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// TOAST UTILITY
|
|
113
|
+
// ============================================================================
|
|
114
|
+
const showToast = useCallback((message, variant) => {
|
|
115
|
+
generateThemeToast({ description: message, variant });
|
|
116
|
+
}, []);
|
|
117
|
+
const resetFormAndCloseDrawer = useCallback(() => {
|
|
118
|
+
dispatch({
|
|
119
|
+
type: ATTENDANCE_ACTION_TYPES.SET_ERRORS,
|
|
120
|
+
payload: { errors: {} },
|
|
121
|
+
});
|
|
122
|
+
dispatch({
|
|
123
|
+
type: ATTENDANCE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
|
|
124
|
+
payload: { disabled: false },
|
|
125
|
+
});
|
|
126
|
+
dispatch({
|
|
127
|
+
type: ATTENDANCE_ACTION_TYPES.SET_DRAWER,
|
|
128
|
+
payload: { drawer: null },
|
|
129
|
+
});
|
|
130
|
+
}, [dispatch]);
|
|
131
|
+
// ============================================================================
|
|
132
|
+
// API CALLBACKS
|
|
133
|
+
// ============================================================================
|
|
134
|
+
const listCallback = ({ data, error }) => {
|
|
135
|
+
var _a;
|
|
136
|
+
if (error) {
|
|
137
|
+
showToast("Failed to fetch attendance records", TOAST_VARIANT.ERROR);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (data) {
|
|
141
|
+
const response = data;
|
|
142
|
+
const items = (_a = response.items) !== null && _a !== void 0 ? _a : [];
|
|
143
|
+
const count = typeof response.count === "number" ? response.count : 0;
|
|
144
|
+
dispatch({
|
|
145
|
+
type: ATTENDANCE_ACTION_TYPES.SET_ITEMS,
|
|
146
|
+
payload: { items, count },
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const updateCallback = ({ data, error }) => {
|
|
151
|
+
const isCreated = isCreatedOrUpdated(data);
|
|
152
|
+
if (error) {
|
|
153
|
+
showToast(isCreated
|
|
154
|
+
? "Failed to create attendance record"
|
|
155
|
+
: "Failed to update attendance record", TOAST_VARIANT.ERROR);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
if (data) {
|
|
159
|
+
showToast("Attendance record saved successfully", TOAST_VARIANT.SUCCESS);
|
|
160
|
+
invalidateAttendancesCache();
|
|
161
|
+
listFetchNow();
|
|
162
|
+
resetFormAndCloseDrawer();
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const byIdCallback = ({ data, error }) => {
|
|
166
|
+
if (error) {
|
|
167
|
+
showToast("Failed to fetch attendance details", TOAST_VARIANT.ERROR);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (data) {
|
|
171
|
+
dispatch({
|
|
172
|
+
type: ATTENDANCE_ACTION_TYPES.SET_FORM_DATA,
|
|
173
|
+
payload: { form: Object.assign(Object.assign({}, data), { filterEnabled: undefined }) },
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
const deleteCallback = ({ data, error }) => {
|
|
178
|
+
if (error) {
|
|
179
|
+
showToast("Failed to delete attendance record", TOAST_VARIANT.ERROR);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (data) {
|
|
183
|
+
showToast("Attendance record deleted successfully", TOAST_VARIANT.SUCCESS);
|
|
184
|
+
invalidateAttendancesCache();
|
|
185
|
+
listFetchNow();
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
// ============================================================================
|
|
189
|
+
// HANDLERS
|
|
190
|
+
// ============================================================================
|
|
191
|
+
const handleChange = useCallback((field, value) => {
|
|
192
|
+
dispatch({
|
|
193
|
+
type: ATTENDANCE_ACTION_TYPES.SET_ERRORS,
|
|
194
|
+
payload: { errors: {} },
|
|
195
|
+
});
|
|
196
|
+
dispatch({
|
|
197
|
+
type: ATTENDANCE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
|
|
198
|
+
payload: { disabled: false },
|
|
199
|
+
});
|
|
200
|
+
dispatch({
|
|
201
|
+
type: ATTENDANCE_ACTION_TYPES.SET_INPUT_FIELD,
|
|
202
|
+
payload: { key: field, value },
|
|
203
|
+
});
|
|
204
|
+
}, [dispatch]);
|
|
205
|
+
const handlePageChange = useCallback((page) => {
|
|
206
|
+
dispatch({
|
|
207
|
+
type: ATTENDANCE_ACTION_TYPES.SET_CURRENT_PAGE,
|
|
208
|
+
payload: { currentPage: page },
|
|
209
|
+
});
|
|
210
|
+
}, [dispatch]);
|
|
211
|
+
const handlePageLimitChange = useCallback((limit) => {
|
|
212
|
+
dispatch({
|
|
213
|
+
type: ATTENDANCE_ACTION_TYPES.SET_PAGE_LIMIT,
|
|
214
|
+
payload: { pageLimit: limit },
|
|
215
|
+
});
|
|
216
|
+
}, [dispatch]);
|
|
217
|
+
const handleCloseDrawer = useCallback(() => {
|
|
218
|
+
resetFormAndCloseDrawer();
|
|
219
|
+
}, [resetFormAndCloseDrawer]);
|
|
220
|
+
const handleCreate = useCallback(() => {
|
|
221
|
+
dispatch({
|
|
222
|
+
type: ATTENDANCE_ACTION_TYPES.SET_DRAWER,
|
|
223
|
+
payload: { drawer: ATTENDANCE_DRAWER.FORM_DRAWER },
|
|
224
|
+
});
|
|
225
|
+
}, [dispatch]);
|
|
226
|
+
const handleFilters = useCallback(() => {
|
|
227
|
+
dispatch({
|
|
228
|
+
type: ATTENDANCE_ACTION_TYPES.SET_DRAWER,
|
|
229
|
+
payload: { drawer: ATTENDANCE_DRAWER.FILTER_DRAWER },
|
|
230
|
+
});
|
|
231
|
+
}, [dispatch]);
|
|
232
|
+
const handleMoreActions = useCallback(() => {
|
|
233
|
+
dispatch({
|
|
234
|
+
type: ATTENDANCE_ACTION_TYPES.SET_DRAWER,
|
|
235
|
+
payload: { drawer: ATTENDANCE_DRAWER.MORE_ACTIONS_DRAWER },
|
|
236
|
+
});
|
|
237
|
+
}, [dispatch]);
|
|
238
|
+
const handleSearch = useCallback((query) => {
|
|
239
|
+
dispatch({
|
|
240
|
+
type: ATTENDANCE_ACTION_TYPES.SET_SEARCH_QUERY,
|
|
241
|
+
payload: { searchQuery: query },
|
|
242
|
+
});
|
|
243
|
+
}, [dispatch]);
|
|
244
|
+
const clearFilters = useCallback(() => {
|
|
245
|
+
dispatch({
|
|
246
|
+
type: ATTENDANCE_ACTION_TYPES.RESET_FORM,
|
|
247
|
+
});
|
|
248
|
+
}, [dispatch]);
|
|
249
|
+
// ============================================================================
|
|
250
|
+
// API HOOKS
|
|
251
|
+
// ============================================================================
|
|
252
|
+
const { listFetchNow, listLoading, updateFetchNow, updateLoading, byIdFetchNow, deleteFetchNow, deleteLoading, byIdLoading, } = useModuleEntityV2({
|
|
253
|
+
byIdCallback,
|
|
254
|
+
byIdParams,
|
|
255
|
+
deleteCallback,
|
|
256
|
+
deleteParams,
|
|
257
|
+
listCallback,
|
|
258
|
+
listParams,
|
|
259
|
+
listUrl: ATTENDANCE_API_ROUTES.UNIT,
|
|
260
|
+
searchQuery: debouncedQuery,
|
|
261
|
+
unitByIdUrl: ATTENDANCE_API_ROUTES.UNIT,
|
|
262
|
+
unitUrl: ATTENDANCE_API_ROUTES.UNIT,
|
|
263
|
+
updateCallback,
|
|
264
|
+
updateParams,
|
|
265
|
+
headers: {
|
|
266
|
+
"Content-Type": "application/json",
|
|
267
|
+
"x-api-token": process.env.NEXT_PUBLIC_API_KEY,
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
// ============================================================================
|
|
271
|
+
// HANDLERS THAT USE API HOOKS (moved after API hooks)
|
|
272
|
+
// ============================================================================
|
|
273
|
+
const handleView = useCallback((row) => {
|
|
274
|
+
byIdFetchNow === null || byIdFetchNow === void 0 ? void 0 : byIdFetchNow(undefined, { params: { id: row === null || row === void 0 ? void 0 : row.id } });
|
|
275
|
+
dispatch({
|
|
276
|
+
type: ATTENDANCE_ACTION_TYPES.SET_DRAWER,
|
|
277
|
+
payload: { drawer: ATTENDANCE_DRAWER.VIEW_DRAWER },
|
|
278
|
+
});
|
|
279
|
+
}, [byIdFetchNow, dispatch]);
|
|
280
|
+
const handleEdit = useCallback((row) => {
|
|
281
|
+
byIdFetchNow === null || byIdFetchNow === void 0 ? void 0 : byIdFetchNow(undefined, { params: { id: row === null || row === void 0 ? void 0 : row.id } });
|
|
282
|
+
dispatch({
|
|
283
|
+
type: ATTENDANCE_ACTION_TYPES.SET_DRAWER,
|
|
284
|
+
payload: { drawer: ATTENDANCE_DRAWER.FORM_DRAWER },
|
|
285
|
+
});
|
|
286
|
+
}, [byIdFetchNow, dispatch]);
|
|
287
|
+
const handleDelete = useCallback((row) => {
|
|
288
|
+
if (!confirm("Are you sure you want to delete this attendance record?"))
|
|
289
|
+
return;
|
|
290
|
+
deleteFetchNow === null || deleteFetchNow === void 0 ? void 0 : deleteFetchNow(undefined, {
|
|
291
|
+
body: JSON.stringify({ id: row === null || row === void 0 ? void 0 : row.id }),
|
|
292
|
+
});
|
|
293
|
+
}, [deleteFetchNow]);
|
|
294
|
+
const handleSubmit = useCallback(() => {
|
|
295
|
+
dispatch({
|
|
296
|
+
type: ATTENDANCE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
|
|
297
|
+
payload: { disabled: true },
|
|
298
|
+
});
|
|
299
|
+
validateForm({
|
|
300
|
+
params: updateParams,
|
|
301
|
+
schema: attendanceFormValidation,
|
|
302
|
+
successCallback: () => {
|
|
303
|
+
updateFetchNow(undefined, {
|
|
304
|
+
body: JSON.stringify(Object.assign(Object.assign({}, updateParams), { markedBy: "" })),
|
|
305
|
+
});
|
|
306
|
+
},
|
|
307
|
+
errorCallback: (errors) => {
|
|
308
|
+
dispatch({
|
|
309
|
+
type: ATTENDANCE_ACTION_TYPES.SET_ERRORS,
|
|
310
|
+
payload: { errors },
|
|
311
|
+
});
|
|
312
|
+
dispatch({
|
|
313
|
+
type: ATTENDANCE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
|
|
314
|
+
payload: { disabled: false },
|
|
315
|
+
});
|
|
316
|
+
showToast("Please fix the form errors", TOAST_VARIANT.ERROR);
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
}, [dispatch, updateParams, updateFetchNow, showToast]);
|
|
320
|
+
// ============================================================================
|
|
321
|
+
// HEADER / ROW ACTIONS
|
|
322
|
+
// ============================================================================
|
|
323
|
+
const headerActions = useMemo(() => [
|
|
324
|
+
{
|
|
325
|
+
enabled: false,
|
|
326
|
+
handleOnClick: handleMoreActions,
|
|
327
|
+
icon: MoreHorizontal,
|
|
328
|
+
label: "More Actions",
|
|
329
|
+
order: 1,
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
enabled: true,
|
|
333
|
+
handleOnClick: handleFilters,
|
|
334
|
+
icon: Filter,
|
|
335
|
+
label: "Filters",
|
|
336
|
+
order: 2,
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
enabled: true,
|
|
340
|
+
handleOnClick: handleCreate,
|
|
341
|
+
icon: Plus,
|
|
342
|
+
label: "Add Attendance",
|
|
343
|
+
order: 3,
|
|
344
|
+
},
|
|
345
|
+
], [handleMoreActions, handleFilters, handleCreate]);
|
|
346
|
+
const rowActions = useMemo(() => [
|
|
347
|
+
{
|
|
348
|
+
enabled: true,
|
|
349
|
+
handleOnClick: handleView,
|
|
350
|
+
icon: Eye,
|
|
351
|
+
label: "View",
|
|
352
|
+
order: 1,
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
enabled: true,
|
|
356
|
+
handleOnClick: handleEdit,
|
|
357
|
+
icon: Edit,
|
|
358
|
+
label: "Edit",
|
|
359
|
+
order: 2,
|
|
360
|
+
},
|
|
361
|
+
], [handleView, handleEdit]);
|
|
362
|
+
const applyFilters = useCallback(() => {
|
|
363
|
+
dispatch({
|
|
364
|
+
type: ATTENDANCE_ACTION_TYPES.SET_CURRENT_PAGE,
|
|
365
|
+
payload: { currentPage: 1 },
|
|
366
|
+
});
|
|
367
|
+
listFetchNow();
|
|
368
|
+
handleCloseDrawer();
|
|
369
|
+
}, [dispatch, listFetchNow, handleCloseDrawer]);
|
|
370
|
+
// ============================================================================
|
|
371
|
+
// EFFECTS
|
|
372
|
+
// ============================================================================
|
|
373
|
+
useEffect(() => {
|
|
374
|
+
(async () => {
|
|
375
|
+
try {
|
|
376
|
+
const { count, items } = await getCachedAttendances({
|
|
377
|
+
params: listParams,
|
|
378
|
+
});
|
|
379
|
+
dispatch({
|
|
380
|
+
type: ATTENDANCE_ACTION_TYPES.SET_ITEMS,
|
|
381
|
+
payload: { items: items || [], count: count || 0 },
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
catch (_a) {
|
|
385
|
+
showToast("Failed to fetch attendance records", TOAST_VARIANT.ERROR);
|
|
386
|
+
}
|
|
387
|
+
})();
|
|
388
|
+
}, [listParams, dispatch, showToast]);
|
|
389
|
+
// ============================================================================
|
|
390
|
+
// RETURN
|
|
391
|
+
// ============================================================================
|
|
392
|
+
return Object.assign(Object.assign({}, context), { applyFilters,
|
|
393
|
+
byIdLoading,
|
|
394
|
+
clearFilters,
|
|
395
|
+
deleteLoading,
|
|
396
|
+
handleChange,
|
|
397
|
+
handleCloseDrawer,
|
|
398
|
+
handleCreate,
|
|
399
|
+
handleDelete,
|
|
400
|
+
handleEdit,
|
|
401
|
+
handleFilters,
|
|
402
|
+
handleMoreActions,
|
|
403
|
+
handlePageChange,
|
|
404
|
+
handlePageLimitChange,
|
|
405
|
+
handleSearch,
|
|
406
|
+
handleSubmit,
|
|
407
|
+
handleView,
|
|
408
|
+
headerActions,
|
|
409
|
+
listLoading,
|
|
410
|
+
rowActions,
|
|
411
|
+
updateLoading });
|
|
412
|
+
};
|