@appcorp/fusion-storybook 0.3.90 → 0.3.92

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.
@@ -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 { PAYMENT_METHOD, } from "../../type";
32
- import { pageLimit } from "./constants";
33
- import { EXPENSE_API_ROUTES } from "../../constants";
34
- import { getCachedWorkspaceSync } from "../workspace/cache";
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
- // 1.1 DRAWER TYPES
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 & CORE HOOKS
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 API PARAMETERS
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.3 UTILITIES
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({
@@ -350,12 +149,38 @@ export const useExpenseModule = () => {
350
149
  });
351
150
  }, [dispatch]);
352
151
  const applyFilters = useCallback(() => {
152
+ closeDrawer();
153
+ dispatch({
154
+ type: EXPENSE_ACTION_TYPES.SET_INPUT_FIELD,
155
+ payload: { key: "filterCategory", value: state.filterCategory },
156
+ });
157
+ dispatch({
158
+ type: EXPENSE_ACTION_TYPES.SET_INPUT_FIELD,
159
+ payload: { key: "filterStatus", value: state.filterStatus },
160
+ });
161
+ dispatch({
162
+ type: EXPENSE_ACTION_TYPES.SET_INPUT_FIELD,
163
+ payload: { key: "filterEnabled", value: state.filterEnabled },
164
+ });
353
165
  dispatch({
354
166
  type: EXPENSE_ACTION_TYPES.SET_CURRENT_PAGE,
355
167
  payload: { currentPage: 1 },
356
168
  });
357
- closeDrawer();
358
- }, [dispatch, closeDrawer]);
169
+ listFetchNow === null || listFetchNow === void 0 ? void 0 : listFetchNow(undefined, {
170
+ params: Object.assign(Object.assign(Object.assign({ currentPage: 1, pageLimit: state.pageLimit, schoolId }, (state.filterCategory && { filterCategory: state.filterCategory })), (state.filterStatus && { filterStatus: state.filterStatus })), (state.filterEnabled !== undefined && {
171
+ filterEnabled: state.filterEnabled,
172
+ })),
173
+ });
174
+ }, [
175
+ closeDrawer,
176
+ dispatch,
177
+ listFetchNow,
178
+ schoolId,
179
+ state.filterCategory,
180
+ state.filterEnabled,
181
+ state.filterStatus,
182
+ state.pageLimit,
183
+ ]);
359
184
  const clearFilters = useCallback(() => {
360
185
  dispatch({
361
186
  type: EXPENSE_ACTION_TYPES.SET_CURRENT_PAGE,
@@ -371,9 +196,16 @@ export const useExpenseModule = () => {
371
196
  },
372
197
  },
373
198
  });
374
- }, [dispatch]);
199
+ listFetchNow(undefined, {
200
+ params: {
201
+ currentPage: 1,
202
+ pageLimit: state.pageLimit,
203
+ schoolId,
204
+ },
205
+ });
206
+ }, [dispatch, listFetchNow, state.pageLimit, schoolId]);
375
207
  // ============================================================================
376
- // 1.4.7 NETWORK ACTIONS
208
+ // 1.4.5 NETWORK ACTIONS
377
209
  // ============================================================================
378
210
  const handleSubmit = useCallback(() => {
379
211
  dispatch({
@@ -402,7 +234,7 @@ export const useExpenseModule = () => {
402
234
  });
403
235
  }, [dispatch, updateParams, updateFetchNow, t, showToast]);
404
236
  // ============================================================================
405
- // 1.4.8 HEADER & ROW ACTIONS
237
+ // 1.4.6 HEADER & ROW ACTIONS
406
238
  // ============================================================================
407
239
  const headerActions = useMemo(() => [
408
240
  {
@@ -445,19 +277,7 @@ export const useExpenseModule = () => {
445
277
  },
446
278
  ], [handleDelete, handleEdit, handleView, t]);
447
279
  // ============================================================================
448
- // 1.4.9 EFFECTS
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
280
+ // 1.4.7 RETURN
461
281
  // ============================================================================
462
282
  return Object.assign(Object.assign({}, context), { applyFilters,
463
283
  byIdLoading,
@@ -14,7 +14,11 @@
14
14
  */
15
15
  import { FC } from "react";
16
16
  import { USER_ROLE } from "../../type";
17
- interface Props {
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,185 @@
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({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId }, (debouncedQuery ? { searchQuery: debouncedQuery } : {}))), [state.currentPage, state.pageLimit, debouncedQuery, schoolId]);
66
+ 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]);
67
+ const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
68
+ const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
69
+ // ==========================================================================
70
+ // API CALLBACKS
71
+ // ==========================================================================
72
+ const listCallback = useCallback(({ data, error }) => {
73
+ var _a, _b;
74
+ if (error) {
75
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
76
+ return;
77
+ }
78
+ if (data) {
79
+ const response = data;
80
+ dispatch({
81
+ type: FEE_STRUCTURE_ACTION_TYPES.SET_ITEMS,
82
+ payload: { items: (_a = response.items) !== null && _a !== void 0 ? _a : [], count: (_b = response.count) !== null && _b !== void 0 ? _b : 0 },
83
+ });
84
+ }
85
+ }, [dispatch, showToast, t]);
86
+ const listFetchNowRef = useRef(null);
87
+ const updateCallback = useCallback(({ data, error }) => {
88
+ var _a;
89
+ if (error) {
90
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
91
+ return;
92
+ }
93
+ if (data) {
94
+ const isCreated = isCreatedOrUpdated(data);
95
+ showToast(isCreated
96
+ ? t("messagesFeeStructureCreated")
97
+ : t("messagesFeeStructureUpdated"), TOAST_VARIANT.SUCCESS);
98
+ resetFormAndCloseDrawer();
99
+ (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
100
+ }
101
+ }, [resetFormAndCloseDrawer, showToast, t]);
102
+ const byIdCallback = useCallback(({ data, error }) => {
103
+ if (error) {
104
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
105
+ return;
106
+ }
107
+ if (data) {
108
+ dispatch({
109
+ type: FEE_STRUCTURE_ACTION_TYPES.SET_FORM_DATA,
110
+ payload: { form: Object.assign(Object.assign({}, data), { filterEnabled: undefined }) },
111
+ });
112
+ }
113
+ }, [dispatch, showToast, t]);
114
+ const deleteCallback = useCallback(({ data, error }) => {
115
+ var _a;
116
+ if (error) {
117
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
118
+ return;
119
+ }
120
+ if (data) {
121
+ showToast(t("messagesFeeStructureDeleted"), TOAST_VARIANT.SUCCESS);
122
+ (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
123
+ }
124
+ }, [showToast, t]);
125
+ // ==========================================================================
126
+ // SINGLE API HOOK INSTANCE
127
+ // ==========================================================================
128
+ const { listFetchNow, listLoading, updateFetchNow, updateLoading, byIdFetchNow, deleteFetchNow, deleteLoading, byIdLoading, } = useModuleEntityV2({
129
+ byIdCallback,
130
+ byIdParams,
131
+ deleteCallback,
132
+ deleteParams,
133
+ listCallback,
134
+ listParams,
135
+ listUrl: FEE_STRUCTURE_API_ROUTES.UNIT,
136
+ searchQuery: debouncedQuery,
137
+ unitByIdUrl: FEE_STRUCTURE_API_ROUTES.UNIT,
138
+ unitUrl: FEE_STRUCTURE_API_ROUTES.UNIT,
139
+ updateCallback,
140
+ updateParams,
141
+ headers: {
142
+ "Content-Type": "application/json",
143
+ },
144
+ });
145
+ // ==========================================================================
146
+ // REF SYNC (for callbacks to always call the latest fetch)
147
+ // ==========================================================================
148
+ useEffect(() => {
149
+ listFetchNowRef.current = listFetchNow;
150
+ }, [listFetchNow]);
151
+ // ==========================================================================
152
+ // AUTO-FETCH EFFECT (runs once, not per child mount)
153
+ // ==========================================================================
154
+ useEffect(() => {
155
+ var _a;
156
+ if (!schoolId)
157
+ return;
158
+ (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
159
+ }, [listParams, schoolId]);
160
+ // ==========================================================================
161
+ // CONTEXT VALUE
162
+ // ==========================================================================
163
+ const value = useMemo(() => ({
164
+ listFetchNow,
165
+ listLoading,
166
+ updateFetchNow,
167
+ updateLoading,
168
+ byIdFetchNow,
169
+ byIdLoading,
170
+ deleteFetchNow,
171
+ deleteLoading,
172
+ resetFormAndCloseDrawer,
173
+ }), [
174
+ listFetchNow,
175
+ listLoading,
176
+ updateFetchNow,
177
+ updateLoading,
178
+ byIdFetchNow,
179
+ byIdLoading,
180
+ deleteFetchNow,
181
+ deleteLoading,
182
+ resetFormAndCloseDrawer,
183
+ ]);
184
+ return (_jsx(FeeStructureApiContext.Provider, { value: value, children: children }));
185
+ };
@@ -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";