@appcorp/fusion-storybook 0.3.89 → 0.3.91
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/expense/context/expense-api-provider.d.ts +16 -0
- package/base-modules/expense/context/expense-api-provider.js +229 -0
- package/base-modules/expense/context/index.d.ts +3 -0
- package/base-modules/expense/context/index.js +3 -0
- package/base-modules/expense/{context.d.ts → context/shared.d.ts} +7 -67
- package/base-modules/expense/context/shared.js +63 -0
- package/base-modules/expense/context/use-expense-module.d.ts +66 -0
- package/base-modules/expense/{context.js → context/use-expense-module.js} +23 -236
- package/base-modules/expense/page.d.ts +7 -1
- package/base-modules/expense/page.js +5 -2
- package/base-modules/fee-structure/context/fee-structure-api-provider.d.ts +16 -0
- package/base-modules/fee-structure/context/fee-structure-api-provider.js +193 -0
- package/base-modules/fee-structure/context/index.d.ts +3 -0
- package/base-modules/fee-structure/context/index.js +3 -0
- package/base-modules/fee-structure/{context.d.ts → context/shared.d.ts} +7 -54
- package/base-modules/fee-structure/context/shared.js +47 -0
- package/base-modules/fee-structure/context/use-fee-structure-module.d.ts +54 -0
- package/base-modules/fee-structure/{context.js → context/use-fee-structure-module.js} +15 -196
- package/base-modules/fee-structure/page.d.ts +7 -1
- package/base-modules/fee-structure/page.js +5 -2
- package/base-modules/student-fee/page.d.ts +8 -1
- package/base-modules/student-fee/page.js +23 -20
- package/package.json +1 -1
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -1,137 +1,42 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
|
|
3
|
-
* Expense 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 toast notifications.
|
|
9
|
-
*
|
|
10
|
-
* Key responsibilities:
|
|
11
|
-
* - expose `useExpenseModule()` 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
|
-
* - `ExpenseProvider` — provider component used by the page
|
|
17
|
-
* - `EXPENSE_ACTION_TYPES` — action type constants (from factory)
|
|
18
|
-
* - `EXPENSE_DRAWER` — drawer type constants
|
|
19
|
-
* - `useExpenseModule()` — hook that returns handlers and state
|
|
20
|
-
*/
|
|
21
|
-
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
|
+
import { useCallback, useMemo } from "react";
|
|
22
3
|
import { useTheme } from "next-themes";
|
|
23
4
|
import { useTranslations } from "next-intl";
|
|
24
|
-
import { isCreatedOrUpdated } from "@react-pakistan/util-functions/general/is-created-or-updated";
|
|
25
5
|
import { validateForm } from "@react-pakistan/util-functions/general/validate-form";
|
|
26
|
-
import { useModuleEntityV2, } from "@react-pakistan/util-functions/hooks/use-module-entity-v2";
|
|
27
|
-
import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
|
|
28
|
-
import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
|
|
29
|
-
import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
|
|
30
6
|
import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import { expenseFormValidation } from "./validate";
|
|
7
|
+
import { getCachedWorkspaceSync } from "../../workspace/cache";
|
|
8
|
+
import { expenseFormValidation } from "../validate";
|
|
9
|
+
import { EXPENSE_ACTION_TYPES, EXPENSE_DRAWER, useExpenseContext, } from "./shared";
|
|
10
|
+
import { useExpenseApiContext } from "./expense-api-provider";
|
|
36
11
|
// ============================================================================
|
|
37
|
-
//
|
|
38
|
-
// ============================================================================
|
|
39
|
-
export const EXPENSE_DRAWER = {
|
|
40
|
-
FILTER_DRAWER: DRAWER_TYPES.FILTER_DRAWER,
|
|
41
|
-
FORM_DRAWER: DRAWER_TYPES.FORM_DRAWER,
|
|
42
|
-
MORE_ACTIONS_DRAWER: DRAWER_TYPES.MORE_ACTIONS_DRAWER,
|
|
43
|
-
VIEW_DRAWER: DRAWER_TYPES.VIEW_DRAWER,
|
|
44
|
-
};
|
|
45
|
-
const normalizeDate = (date) => {
|
|
46
|
-
if (!date)
|
|
47
|
-
return "";
|
|
48
|
-
try {
|
|
49
|
-
return new Date(date).toISOString().split("T")[0];
|
|
50
|
-
}
|
|
51
|
-
catch (_a) {
|
|
52
|
-
return "";
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
const expenseConfig = {
|
|
56
|
-
name: "Expense",
|
|
57
|
-
displayName: "Expense",
|
|
58
|
-
drawerTypes: DRAWER_TYPES,
|
|
59
|
-
initialState: {
|
|
60
|
-
// List Data
|
|
61
|
-
items: [],
|
|
62
|
-
count: 0,
|
|
63
|
-
// Search & Pagination
|
|
64
|
-
currentPage: 1,
|
|
65
|
-
pageLimit,
|
|
66
|
-
searchQuery: "",
|
|
67
|
-
// UI State
|
|
68
|
-
disableSaveButton: false,
|
|
69
|
-
drawer: null,
|
|
70
|
-
errors: {},
|
|
71
|
-
// Form fields
|
|
72
|
-
amount: 0,
|
|
73
|
-
approvedBy: "",
|
|
74
|
-
attachments: [],
|
|
75
|
-
category: "",
|
|
76
|
-
description: "",
|
|
77
|
-
enabled: true,
|
|
78
|
-
expenseDate: new Date().toISOString().slice(0, 10),
|
|
79
|
-
id: "",
|
|
80
|
-
invoiceNumber: "",
|
|
81
|
-
paidBy: "",
|
|
82
|
-
paymentDate: new Date().toISOString().slice(0, 10),
|
|
83
|
-
paymentMethod: PAYMENT_METHOD.CASH,
|
|
84
|
-
receiptNumber: "",
|
|
85
|
-
remarks: "",
|
|
86
|
-
schoolId: "",
|
|
87
|
-
status: "",
|
|
88
|
-
title: "",
|
|
89
|
-
transactionId: "",
|
|
90
|
-
vendorContact: "",
|
|
91
|
-
vendorName: "",
|
|
92
|
-
// Filters
|
|
93
|
-
filterCategory: "",
|
|
94
|
-
filterEnabled: undefined,
|
|
95
|
-
filterStatus: "",
|
|
96
|
-
// Relations
|
|
97
|
-
school: undefined,
|
|
98
|
-
},
|
|
99
|
-
};
|
|
100
|
-
// ============================================================================
|
|
101
|
-
// 1.3 CREATE EXPENSE MODULE
|
|
102
|
-
// ============================================================================
|
|
103
|
-
export const { actionTypes: EXPENSE_ACTION_TYPES, config: expenseModuleConfig, initialState: initialExpenseState, Provider: ExpenseProvider, reducer: expenseReducer, useContext: useExpenseContext, } = createGenericModule(expenseConfig);
|
|
104
|
-
// ============================================================================
|
|
105
|
-
// 1.4 ENHANCED EXPENSE HOOK WITH API INTEGRATION
|
|
12
|
+
// ENHANCED EXPENSE HOOK WITH API INTEGRATION
|
|
106
13
|
// ============================================================================
|
|
107
14
|
export const useExpenseModule = () => {
|
|
108
15
|
// ============================================================================
|
|
109
|
-
// 1.4.1 STATE &
|
|
16
|
+
// 1.4.1 STATE & API HOOKS
|
|
110
17
|
// ============================================================================
|
|
111
18
|
var _a;
|
|
112
19
|
const context = useExpenseContext();
|
|
113
20
|
const { dispatch } = context;
|
|
114
21
|
const state = context.state;
|
|
22
|
+
const { listFetchNow, listLoading, updateFetchNow, updateLoading, byIdFetchNow, byIdLoading, deleteFetchNow, deleteLoading, resetFormAndCloseDrawer, } = useExpenseApiContext();
|
|
115
23
|
const t = useTranslations("expense");
|
|
116
24
|
const { theme } = useTheme();
|
|
117
25
|
const workspace = getCachedWorkspaceSync();
|
|
118
26
|
const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
|
|
119
|
-
const listFetchNowRef = useRef(null);
|
|
120
|
-
const debouncedQuery = useDebounce(state.searchQuery, 800);
|
|
121
27
|
// ============================================================================
|
|
122
|
-
// 1.4.2
|
|
28
|
+
// 1.4.2 UTILITIES
|
|
29
|
+
// ============================================================================
|
|
30
|
+
const showToast = useCallback((description, variant) => {
|
|
31
|
+
generateThemeToast({
|
|
32
|
+
description,
|
|
33
|
+
theme: theme,
|
|
34
|
+
variant,
|
|
35
|
+
});
|
|
36
|
+
}, [theme]);
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// 1.4.3 UPDATE PARAMS (used by handleSubmit for validation + fetch body)
|
|
123
39
|
// ============================================================================
|
|
124
|
-
const listParams = useMemo(() => (Object.assign(Object.assign(Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterCategory ? { filterCategory: state.filterCategory } : {})), (state.filterStatus ? { filterStatus: state.filterStatus } : {})), (state.filterEnabled !== undefined
|
|
125
|
-
? { filterEnabled: state.filterEnabled }
|
|
126
|
-
: {}))), [
|
|
127
|
-
state.currentPage,
|
|
128
|
-
state.filterCategory,
|
|
129
|
-
state.filterEnabled,
|
|
130
|
-
state.filterStatus,
|
|
131
|
-
state.pageLimit,
|
|
132
|
-
debouncedQuery,
|
|
133
|
-
schoolId,
|
|
134
|
-
]);
|
|
135
40
|
const updateParams = useMemo(() => ({
|
|
136
41
|
amount: state.amount,
|
|
137
42
|
approvedBy: state.approvedBy || null,
|
|
@@ -154,114 +59,8 @@ export const useExpenseModule = () => {
|
|
|
154
59
|
vendorContact: state.vendorContact || null,
|
|
155
60
|
vendorName: state.vendorName || null,
|
|
156
61
|
}), [state, schoolId]);
|
|
157
|
-
const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
|
|
158
|
-
const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
|
|
159
62
|
// ============================================================================
|
|
160
|
-
// 1.4.
|
|
161
|
-
// ============================================================================
|
|
162
|
-
const showToast = useCallback((description, variant) => {
|
|
163
|
-
generateThemeToast({
|
|
164
|
-
description,
|
|
165
|
-
theme: theme,
|
|
166
|
-
variant,
|
|
167
|
-
});
|
|
168
|
-
}, [theme]);
|
|
169
|
-
const resetFormAndCloseDrawer = useCallback(() => {
|
|
170
|
-
dispatch({ type: EXPENSE_ACTION_TYPES.RESET_FORM });
|
|
171
|
-
dispatch({
|
|
172
|
-
type: EXPENSE_ACTION_TYPES.SET_ERRORS,
|
|
173
|
-
payload: { errors: {} },
|
|
174
|
-
});
|
|
175
|
-
dispatch({
|
|
176
|
-
type: EXPENSE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
|
|
177
|
-
payload: { disabled: false },
|
|
178
|
-
});
|
|
179
|
-
dispatch({
|
|
180
|
-
type: EXPENSE_ACTION_TYPES.SET_DRAWER,
|
|
181
|
-
payload: { drawer: null },
|
|
182
|
-
});
|
|
183
|
-
}, [dispatch]);
|
|
184
|
-
// ============================================================================
|
|
185
|
-
// 1.4.4 API CALLBACKS
|
|
186
|
-
// ============================================================================
|
|
187
|
-
const listCallback = useCallback(({ data, error }) => {
|
|
188
|
-
var _a;
|
|
189
|
-
if (error) {
|
|
190
|
-
showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
if (data) {
|
|
194
|
-
const response = data;
|
|
195
|
-
const items = (_a = response.items) !== null && _a !== void 0 ? _a : [];
|
|
196
|
-
const count = typeof response.count === "number" ? response.count : 0;
|
|
197
|
-
dispatch({
|
|
198
|
-
type: EXPENSE_ACTION_TYPES.SET_ITEMS,
|
|
199
|
-
payload: { items, count },
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
}, [dispatch, showToast, t]);
|
|
203
|
-
const updateCallback = useCallback(({ data, error }) => {
|
|
204
|
-
var _a;
|
|
205
|
-
if (error) {
|
|
206
|
-
showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
if (data) {
|
|
210
|
-
const isCreated = isCreatedOrUpdated(data);
|
|
211
|
-
showToast(isCreated ? t("messagesExpenseCreated") : t("messagesExpenseUpdated"), TOAST_VARIANT.SUCCESS);
|
|
212
|
-
resetFormAndCloseDrawer();
|
|
213
|
-
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
214
|
-
}
|
|
215
|
-
}, [showToast, t, resetFormAndCloseDrawer]);
|
|
216
|
-
const byIdCallback = useCallback(({ data, error }) => {
|
|
217
|
-
if (error) {
|
|
218
|
-
showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
if (data) {
|
|
222
|
-
const expense = data;
|
|
223
|
-
dispatch({
|
|
224
|
-
type: EXPENSE_ACTION_TYPES.SET_FORM_DATA,
|
|
225
|
-
payload: {
|
|
226
|
-
form: Object.assign(Object.assign({}, expense), { expenseDate: normalizeDate(expense.expenseDate), paymentDate: normalizeDate(expense.paymentDate), paymentMethod: expense.paymentMethod || "", filterEnabled: undefined, filterCategory: "", filterStatus: "" }),
|
|
227
|
-
},
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}, [dispatch, showToast, t]);
|
|
231
|
-
const deleteCallback = useCallback(({ data, error }) => {
|
|
232
|
-
var _a;
|
|
233
|
-
if (error) {
|
|
234
|
-
showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
if (data) {
|
|
238
|
-
showToast(t("messagesExpenseDeleted"), TOAST_VARIANT.SUCCESS);
|
|
239
|
-
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
240
|
-
}
|
|
241
|
-
}, [showToast, t]);
|
|
242
|
-
// ============================================================================
|
|
243
|
-
// 1.4.5 API HOOKS
|
|
244
|
-
// ============================================================================
|
|
245
|
-
const { byIdFetchNow, byIdLoading, deleteFetchNow, deleteLoading, listFetchNow, listLoading, updateFetchNow, updateLoading, } = useModuleEntityV2({
|
|
246
|
-
byIdCallback,
|
|
247
|
-
byIdParams,
|
|
248
|
-
deleteCallback,
|
|
249
|
-
deleteParams,
|
|
250
|
-
headers: {
|
|
251
|
-
"Content-Type": "application/json",
|
|
252
|
-
// "x-api-token": process.env.NEXT_PUBLIC_API_KEY!,
|
|
253
|
-
},
|
|
254
|
-
listCallback,
|
|
255
|
-
listParams,
|
|
256
|
-
listUrl: EXPENSE_API_ROUTES.UNIT,
|
|
257
|
-
searchQuery: debouncedQuery,
|
|
258
|
-
unitByIdUrl: EXPENSE_API_ROUTES.UNIT,
|
|
259
|
-
unitUrl: EXPENSE_API_ROUTES.UNIT,
|
|
260
|
-
updateCallback,
|
|
261
|
-
updateParams,
|
|
262
|
-
});
|
|
263
|
-
// ============================================================================
|
|
264
|
-
// 1.4.6 HANDLERS
|
|
63
|
+
// 1.4.4 HANDLERS
|
|
265
64
|
// ============================================================================
|
|
266
65
|
const handleChange = useCallback((field, value) => {
|
|
267
66
|
dispatch({
|
|
@@ -373,7 +172,7 @@ export const useExpenseModule = () => {
|
|
|
373
172
|
});
|
|
374
173
|
}, [dispatch]);
|
|
375
174
|
// ============================================================================
|
|
376
|
-
// 1.4.
|
|
175
|
+
// 1.4.5 NETWORK ACTIONS
|
|
377
176
|
// ============================================================================
|
|
378
177
|
const handleSubmit = useCallback(() => {
|
|
379
178
|
dispatch({
|
|
@@ -402,7 +201,7 @@ export const useExpenseModule = () => {
|
|
|
402
201
|
});
|
|
403
202
|
}, [dispatch, updateParams, updateFetchNow, t, showToast]);
|
|
404
203
|
// ============================================================================
|
|
405
|
-
// 1.4.
|
|
204
|
+
// 1.4.6 HEADER & ROW ACTIONS
|
|
406
205
|
// ============================================================================
|
|
407
206
|
const headerActions = useMemo(() => [
|
|
408
207
|
{
|
|
@@ -445,19 +244,7 @@ export const useExpenseModule = () => {
|
|
|
445
244
|
},
|
|
446
245
|
], [handleDelete, handleEdit, handleView, t]);
|
|
447
246
|
// ============================================================================
|
|
448
|
-
// 1.4.
|
|
449
|
-
// ============================================================================
|
|
450
|
-
useEffect(() => {
|
|
451
|
-
listFetchNowRef.current = listFetchNow;
|
|
452
|
-
}, [listFetchNow]);
|
|
453
|
-
useEffect(() => {
|
|
454
|
-
var _a;
|
|
455
|
-
if (!schoolId)
|
|
456
|
-
return;
|
|
457
|
-
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
458
|
-
}, [listParams, schoolId]);
|
|
459
|
-
// ============================================================================
|
|
460
|
-
// 1.4.10 RETURN
|
|
247
|
+
// 1.4.7 RETURN
|
|
461
248
|
// ============================================================================
|
|
462
249
|
return Object.assign(Object.assign({}, context), { applyFilters,
|
|
463
250
|
byIdLoading,
|
|
@@ -14,7 +14,11 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { FC } from "react";
|
|
16
16
|
import { USER_ROLE } from "../../type";
|
|
17
|
-
interface
|
|
17
|
+
interface ConfigProps {
|
|
18
|
+
dispatch: React.Dispatch<{
|
|
19
|
+
type: string;
|
|
20
|
+
payload?: unknown;
|
|
21
|
+
}>;
|
|
18
22
|
drawerButtonCancel: string;
|
|
19
23
|
drawerButtonSave: string;
|
|
20
24
|
drawerFilterDescription: string;
|
|
@@ -36,6 +40,8 @@ interface Props {
|
|
|
36
40
|
tableDescription: string;
|
|
37
41
|
tableSearchPlaceholder: string;
|
|
38
42
|
tableTitle: string;
|
|
43
|
+
}
|
|
44
|
+
interface Props extends ConfigProps {
|
|
39
45
|
userRole: USER_ROLE;
|
|
40
46
|
}
|
|
41
47
|
export declare const ExpensePage: FC<Props>;
|
|
@@ -18,7 +18,7 @@ import { useMemo } from "react";
|
|
|
18
18
|
import { COMPONENT_TYPE } from "@appcorp/shadcn/components/enhanced-table";
|
|
19
19
|
import { createGenericModulePage, } from "@react-pakistan/util-functions/factory/generic-component-factory";
|
|
20
20
|
import { DATE_FORMATS, formatDate, } from "@react-pakistan/util-functions/general/format-date";
|
|
21
|
-
import { useExpenseModule, ExpenseProvider, EXPENSE_ACTION_TYPES, } from "./context";
|
|
21
|
+
import { useExpenseModule, ExpenseProvider, ExpenseApiProvider, EXPENSE_ACTION_TYPES, } from "./context";
|
|
22
22
|
import { ExpenseFilter } from "./filter";
|
|
23
23
|
import { ExpenseForm } from "./form";
|
|
24
24
|
import { ExpenseMoreActions } from "./more-actions";
|
|
@@ -104,6 +104,9 @@ const createExpenseConfig = ({ dispatch, drawerButtonCancel, drawerButtonSave, d
|
|
|
104
104
|
// STABLE PAGE COMPONENT (created once, outside render)
|
|
105
105
|
// ============================================================================
|
|
106
106
|
const GenericExpensePage = createGenericModulePage();
|
|
107
|
+
// ============================================================================
|
|
108
|
+
// INNER PAGE (requires ExpenseProvider context)
|
|
109
|
+
// ============================================================================
|
|
107
110
|
const ExpensePageInner = (props) => {
|
|
108
111
|
const context = useExpenseModule();
|
|
109
112
|
// Memoize config creation - destructure props to avoid object reference changes
|
|
@@ -166,4 +169,4 @@ const ExpensePageInner = (props) => {
|
|
|
166
169
|
// ============================================================================
|
|
167
170
|
// PAGE EXPORTS
|
|
168
171
|
// ============================================================================
|
|
169
|
-
export const ExpensePage = (props) => (_jsx(ExpenseProvider, { children: _jsx(ExpensePageInner, Object.assign({}, props)) }));
|
|
172
|
+
export const ExpensePage = (props) => (_jsx(ExpenseProvider, { children: _jsx(ExpenseApiProvider, { children: _jsx(ExpensePageInner, Object.assign({}, props)) }) }));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FetchConfig } from "@react-pakistan/util-functions/hooks/use-fetch";
|
|
2
|
+
export interface FeeStructureApiContextType {
|
|
3
|
+
listFetchNow: (url?: string, config?: FetchConfig) => void;
|
|
4
|
+
listLoading: boolean;
|
|
5
|
+
updateFetchNow: (url?: string, config?: FetchConfig) => void;
|
|
6
|
+
updateLoading: boolean;
|
|
7
|
+
byIdFetchNow: (url?: string, config?: FetchConfig) => void;
|
|
8
|
+
byIdLoading: boolean;
|
|
9
|
+
deleteFetchNow?: (url?: string, config?: FetchConfig) => void;
|
|
10
|
+
deleteLoading: boolean;
|
|
11
|
+
resetFormAndCloseDrawer: () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare const useFeeStructureApiContext: () => FeeStructureApiContextType;
|
|
14
|
+
export declare const FeeStructureApiProvider: ({ children, }: {
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
}) => import("react").JSX.Element;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef } from "react";
|
|
4
|
+
import { useTheme } from "next-themes";
|
|
5
|
+
import { useTranslations } from "next-intl";
|
|
6
|
+
import { isCreatedOrUpdated } from "@react-pakistan/util-functions/general/is-created-or-updated";
|
|
7
|
+
import { useModuleEntityV2, } from "@react-pakistan/util-functions/hooks/use-module-entity-v2";
|
|
8
|
+
import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
|
|
9
|
+
import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
|
|
10
|
+
import { FEE_STRUCTURE_API_ROUTES } from "../../../constants";
|
|
11
|
+
import { getCachedWorkspaceSync } from "../../workspace/cache";
|
|
12
|
+
import { FEE_STRUCTURE_ACTION_TYPES, useFeeStructureContext, } from "./shared";
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// CONTEXT
|
|
15
|
+
// ============================================================================
|
|
16
|
+
const FeeStructureApiContext = createContext(null);
|
|
17
|
+
export const useFeeStructureApiContext = () => {
|
|
18
|
+
const ctx = useContext(FeeStructureApiContext);
|
|
19
|
+
if (!ctx) {
|
|
20
|
+
throw new Error("useFeeStructureApiContext must be used within FeeStructureApiProvider");
|
|
21
|
+
}
|
|
22
|
+
return ctx;
|
|
23
|
+
};
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// PROVIDER
|
|
26
|
+
// ============================================================================
|
|
27
|
+
export const FeeStructureApiProvider = ({ children, }) => {
|
|
28
|
+
var _a;
|
|
29
|
+
const context = useFeeStructureContext();
|
|
30
|
+
const { dispatch } = context;
|
|
31
|
+
const state = context.state;
|
|
32
|
+
const t = useTranslations("feeStructure");
|
|
33
|
+
const { theme } = useTheme();
|
|
34
|
+
const workspace = getCachedWorkspaceSync();
|
|
35
|
+
const debouncedQuery = useDebounce(state.searchQuery, 800);
|
|
36
|
+
const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
|
|
37
|
+
// ==========================================================================
|
|
38
|
+
// UTILITIES
|
|
39
|
+
// ==========================================================================
|
|
40
|
+
const showToast = useCallback((description, variant) => {
|
|
41
|
+
generateThemeToast({
|
|
42
|
+
description,
|
|
43
|
+
theme: theme,
|
|
44
|
+
variant,
|
|
45
|
+
});
|
|
46
|
+
}, [theme]);
|
|
47
|
+
const resetFormAndCloseDrawer = useCallback(() => {
|
|
48
|
+
dispatch({ type: FEE_STRUCTURE_ACTION_TYPES.RESET_FORM });
|
|
49
|
+
dispatch({
|
|
50
|
+
type: FEE_STRUCTURE_ACTION_TYPES.SET_ERRORS,
|
|
51
|
+
payload: { errors: {} },
|
|
52
|
+
});
|
|
53
|
+
dispatch({
|
|
54
|
+
type: FEE_STRUCTURE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
|
|
55
|
+
payload: { disabled: false },
|
|
56
|
+
});
|
|
57
|
+
dispatch({
|
|
58
|
+
type: FEE_STRUCTURE_ACTION_TYPES.SET_DRAWER,
|
|
59
|
+
payload: { drawer: null },
|
|
60
|
+
});
|
|
61
|
+
}, [dispatch]);
|
|
62
|
+
// ==========================================================================
|
|
63
|
+
// API PARAMETERS
|
|
64
|
+
// ==========================================================================
|
|
65
|
+
const listParams = useMemo(() => (Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterEnabled !== undefined
|
|
66
|
+
? { filterEnabled: String(state.filterEnabled) }
|
|
67
|
+
: {}))), [
|
|
68
|
+
state.currentPage,
|
|
69
|
+
state.filterEnabled,
|
|
70
|
+
state.pageLimit,
|
|
71
|
+
debouncedQuery,
|
|
72
|
+
schoolId,
|
|
73
|
+
]);
|
|
74
|
+
const updateParams = useMemo(() => (Object.assign(Object.assign(Object.assign({}, (state.id ? { id: state.id } : {})), (!state.id ? { schoolId } : {})), { amount: Number(state.amount), classId: state.classId || null, description: state.description || null, enabled: state.enabled, feeType: state.feeType, frequency: state.frequency || null, name: state.name })), [state, schoolId]);
|
|
75
|
+
const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
|
|
76
|
+
const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
|
|
77
|
+
// ==========================================================================
|
|
78
|
+
// API CALLBACKS
|
|
79
|
+
// ==========================================================================
|
|
80
|
+
const listCallback = useCallback(({ data, error }) => {
|
|
81
|
+
var _a, _b;
|
|
82
|
+
if (error) {
|
|
83
|
+
showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (data) {
|
|
87
|
+
const response = data;
|
|
88
|
+
dispatch({
|
|
89
|
+
type: FEE_STRUCTURE_ACTION_TYPES.SET_ITEMS,
|
|
90
|
+
payload: { items: (_a = response.items) !== null && _a !== void 0 ? _a : [], count: (_b = response.count) !== null && _b !== void 0 ? _b : 0 },
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}, [dispatch, showToast, t]);
|
|
94
|
+
const listFetchNowRef = useRef(null);
|
|
95
|
+
const updateCallback = useCallback(({ data, error }) => {
|
|
96
|
+
var _a;
|
|
97
|
+
if (error) {
|
|
98
|
+
showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (data) {
|
|
102
|
+
const isCreated = isCreatedOrUpdated(data);
|
|
103
|
+
showToast(isCreated
|
|
104
|
+
? t("messagesFeeStructureCreated")
|
|
105
|
+
: t("messagesFeeStructureUpdated"), TOAST_VARIANT.SUCCESS);
|
|
106
|
+
resetFormAndCloseDrawer();
|
|
107
|
+
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
108
|
+
}
|
|
109
|
+
}, [resetFormAndCloseDrawer, showToast, t]);
|
|
110
|
+
const byIdCallback = useCallback(({ data, error }) => {
|
|
111
|
+
if (error) {
|
|
112
|
+
showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (data) {
|
|
116
|
+
dispatch({
|
|
117
|
+
type: FEE_STRUCTURE_ACTION_TYPES.SET_FORM_DATA,
|
|
118
|
+
payload: { form: Object.assign(Object.assign({}, data), { filterEnabled: undefined }) },
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}, [dispatch, showToast, t]);
|
|
122
|
+
const deleteCallback = useCallback(({ data, error }) => {
|
|
123
|
+
var _a;
|
|
124
|
+
if (error) {
|
|
125
|
+
showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (data) {
|
|
129
|
+
showToast(t("messagesFeeStructureDeleted"), TOAST_VARIANT.SUCCESS);
|
|
130
|
+
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
131
|
+
}
|
|
132
|
+
}, [showToast, t]);
|
|
133
|
+
// ==========================================================================
|
|
134
|
+
// SINGLE API HOOK INSTANCE
|
|
135
|
+
// ==========================================================================
|
|
136
|
+
const { listFetchNow, listLoading, updateFetchNow, updateLoading, byIdFetchNow, deleteFetchNow, deleteLoading, byIdLoading, } = useModuleEntityV2({
|
|
137
|
+
byIdCallback,
|
|
138
|
+
byIdParams,
|
|
139
|
+
deleteCallback,
|
|
140
|
+
deleteParams,
|
|
141
|
+
listCallback,
|
|
142
|
+
listParams,
|
|
143
|
+
listUrl: FEE_STRUCTURE_API_ROUTES.UNIT,
|
|
144
|
+
searchQuery: debouncedQuery,
|
|
145
|
+
unitByIdUrl: FEE_STRUCTURE_API_ROUTES.UNIT,
|
|
146
|
+
unitUrl: FEE_STRUCTURE_API_ROUTES.UNIT,
|
|
147
|
+
updateCallback,
|
|
148
|
+
updateParams,
|
|
149
|
+
headers: {
|
|
150
|
+
"Content-Type": "application/json",
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
// ==========================================================================
|
|
154
|
+
// REF SYNC (for callbacks to always call the latest fetch)
|
|
155
|
+
// ==========================================================================
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
listFetchNowRef.current = listFetchNow;
|
|
158
|
+
}, [listFetchNow]);
|
|
159
|
+
// ==========================================================================
|
|
160
|
+
// AUTO-FETCH EFFECT (runs once, not per child mount)
|
|
161
|
+
// ==========================================================================
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
var _a;
|
|
164
|
+
if (!schoolId)
|
|
165
|
+
return;
|
|
166
|
+
(_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
|
|
167
|
+
}, [listParams, schoolId]);
|
|
168
|
+
// ==========================================================================
|
|
169
|
+
// CONTEXT VALUE
|
|
170
|
+
// ==========================================================================
|
|
171
|
+
const value = useMemo(() => ({
|
|
172
|
+
listFetchNow,
|
|
173
|
+
listLoading,
|
|
174
|
+
updateFetchNow,
|
|
175
|
+
updateLoading,
|
|
176
|
+
byIdFetchNow,
|
|
177
|
+
byIdLoading,
|
|
178
|
+
deleteFetchNow,
|
|
179
|
+
deleteLoading,
|
|
180
|
+
resetFormAndCloseDrawer,
|
|
181
|
+
}), [
|
|
182
|
+
listFetchNow,
|
|
183
|
+
listLoading,
|
|
184
|
+
updateFetchNow,
|
|
185
|
+
updateLoading,
|
|
186
|
+
byIdFetchNow,
|
|
187
|
+
byIdLoading,
|
|
188
|
+
deleteFetchNow,
|
|
189
|
+
deleteLoading,
|
|
190
|
+
resetFormAndCloseDrawer,
|
|
191
|
+
]);
|
|
192
|
+
return (_jsx(FeeStructureApiContext.Provider, { value: value, children: children }));
|
|
193
|
+
};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { FEE_STRUCTURE_DRAWER, FEE_STRUCTURE_ACTION_TYPES, feeStructureModuleConfig, initialFeeStructureState, FeeStructureProvider, feeStructureReducer, useFeeStructureContext, } from "./shared";
|
|
2
|
+
export { FeeStructureApiProvider, useFeeStructureApiContext, } from "./fee-structure-api-provider";
|
|
3
|
+
export { useFeeStructureModule } from "./use-fee-structure-module";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { FEE_STRUCTURE_DRAWER, FEE_STRUCTURE_ACTION_TYPES, feeStructureModuleConfig, initialFeeStructureState, FeeStructureProvider, feeStructureReducer, useFeeStructureContext, } from "./shared";
|
|
2
|
+
export { FeeStructureApiProvider, useFeeStructureApiContext, } from "./fee-structure-api-provider";
|
|
3
|
+
export { useFeeStructureModule } from "./use-fee-structure-module";
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { FeeStructureBE, FEE_TYPE } from "../../type";
|
|
1
|
+
import { FeeStructureBE, FEE_TYPE } from "../../../type";
|
|
3
2
|
export declare const FEE_STRUCTURE_DRAWER: {
|
|
4
3
|
readonly FILTER_DRAWER: string;
|
|
5
4
|
readonly FORM_DRAWER: string;
|
|
6
5
|
readonly MORE_ACTIONS_DRAWER: string;
|
|
7
6
|
readonly VIEW_DRAWER: string;
|
|
8
7
|
};
|
|
8
|
+
export interface FeeStructuresListResponse {
|
|
9
|
+
items: FeeStructureBE[];
|
|
10
|
+
count: number;
|
|
11
|
+
currentPage: number;
|
|
12
|
+
pageLimit: number;
|
|
13
|
+
}
|
|
9
14
|
export declare const FEE_STRUCTURE_ACTION_TYPES: {
|
|
10
15
|
readonly RESET_FORM: "RESET_FORM";
|
|
11
16
|
readonly SET_CURRENT_PAGE: "SET_CURRENT_PAGE";
|
|
@@ -116,55 +121,3 @@ export declare const FEE_STRUCTURE_ACTION_TYPES: {
|
|
|
116
121
|
name: string;
|
|
117
122
|
schoolId: string;
|
|
118
123
|
}>;
|
|
119
|
-
export declare const useFeeStructureModule: () => {
|
|
120
|
-
applyFilters: () => void;
|
|
121
|
-
byIdLoading: boolean;
|
|
122
|
-
clearFilters: () => void;
|
|
123
|
-
clearSearch: () => void;
|
|
124
|
-
closeDrawer: () => void;
|
|
125
|
-
deleteLoading: boolean;
|
|
126
|
-
handleChange: (field: string, value: string | number | boolean | FEE_TYPE | null | undefined) => void;
|
|
127
|
-
handleCreate: () => void;
|
|
128
|
-
handleDelete: (row?: TableRow) => void;
|
|
129
|
-
handleEdit: (row?: TableRow) => void;
|
|
130
|
-
handleFilters: () => void;
|
|
131
|
-
handleMoreActions: () => void;
|
|
132
|
-
handlePageChange: (page: number | unknown) => void;
|
|
133
|
-
handlePageLimitChange: (k: string, value: object) => void;
|
|
134
|
-
handleSearch: (query: string) => void;
|
|
135
|
-
handleSubmit: () => void;
|
|
136
|
-
handleView: (row?: TableRow) => void;
|
|
137
|
-
headerActions: {
|
|
138
|
-
enabled: boolean;
|
|
139
|
-
handleOnClick: () => void;
|
|
140
|
-
label: string;
|
|
141
|
-
order: number;
|
|
142
|
-
}[];
|
|
143
|
-
listFetchNow: (url?: string, config?: import("@react-pakistan/util-functions/hooks/use-fetch").FetchConfig) => void;
|
|
144
|
-
listLoading: boolean;
|
|
145
|
-
rowActions: RowAction[];
|
|
146
|
-
toggleStatus: (row?: TableRow) => void;
|
|
147
|
-
updateLoading: boolean;
|
|
148
|
-
handleCloseDrawer?: () => void;
|
|
149
|
-
state: {
|
|
150
|
-
items: FeeStructureBE[];
|
|
151
|
-
count: number;
|
|
152
|
-
currentPage: number;
|
|
153
|
-
pageLimit: number;
|
|
154
|
-
searchQuery: string;
|
|
155
|
-
disableSaveButton: boolean;
|
|
156
|
-
drawer: string | null;
|
|
157
|
-
amount: number;
|
|
158
|
-
classId: string | null;
|
|
159
|
-
description: string | null;
|
|
160
|
-
enabled: boolean;
|
|
161
|
-
errors: Record<string, string>;
|
|
162
|
-
feeType: FEE_TYPE;
|
|
163
|
-
filterEnabled: boolean | undefined;
|
|
164
|
-
frequency: string | null;
|
|
165
|
-
id: string;
|
|
166
|
-
name: string;
|
|
167
|
-
schoolId: string;
|
|
168
|
-
};
|
|
169
|
-
dispatch: React.Dispatch<any>;
|
|
170
|
-
};
|