@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.
Files changed (24) hide show
  1. package/base-modules/expense/context/expense-api-provider.d.ts +16 -0
  2. package/base-modules/expense/context/expense-api-provider.js +229 -0
  3. package/base-modules/expense/context/index.d.ts +3 -0
  4. package/base-modules/expense/context/index.js +3 -0
  5. package/base-modules/expense/{context.d.ts → context/shared.d.ts} +7 -67
  6. package/base-modules/expense/context/shared.js +63 -0
  7. package/base-modules/expense/context/use-expense-module.d.ts +66 -0
  8. package/base-modules/expense/{context.js → context/use-expense-module.js} +23 -236
  9. package/base-modules/expense/page.d.ts +7 -1
  10. package/base-modules/expense/page.js +5 -2
  11. package/base-modules/fee-structure/context/fee-structure-api-provider.d.ts +16 -0
  12. package/base-modules/fee-structure/context/fee-structure-api-provider.js +193 -0
  13. package/base-modules/fee-structure/context/index.d.ts +3 -0
  14. package/base-modules/fee-structure/context/index.js +3 -0
  15. package/base-modules/fee-structure/{context.d.ts → context/shared.d.ts} +7 -54
  16. package/base-modules/fee-structure/context/shared.js +47 -0
  17. package/base-modules/fee-structure/context/use-fee-structure-module.d.ts +54 -0
  18. package/base-modules/fee-structure/{context.js → context/use-fee-structure-module.js} +15 -196
  19. package/base-modules/fee-structure/page.d.ts +7 -1
  20. package/base-modules/fee-structure/page.js +5 -2
  21. package/base-modules/student-fee/page.d.ts +8 -1
  22. package/base-modules/student-fee/page.js +23 -20
  23. package/package.json +1 -1
  24. package/tsconfig.build.tsbuildinfo +1 -1
@@ -0,0 +1,16 @@
1
+ import type { FetchConfig } from "@react-pakistan/util-functions/hooks/use-fetch";
2
+ export interface ExpenseApiContextType {
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 useExpenseApiContext: () => ExpenseApiContextType;
14
+ export declare const ExpenseApiProvider: ({ children, }: {
15
+ children: React.ReactNode;
16
+ }) => import("react").JSX.Element;
@@ -0,0 +1,229 @@
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 { EXPENSE_API_ROUTES } from "../../../constants";
11
+ import { getCachedWorkspaceSync } from "../../workspace/cache";
12
+ import { EXPENSE_ACTION_TYPES, useExpenseContext, } from "./shared";
13
+ // ============================================================================
14
+ // CONTEXT
15
+ // ============================================================================
16
+ const ExpenseApiContext = createContext(null);
17
+ export const useExpenseApiContext = () => {
18
+ const ctx = useContext(ExpenseApiContext);
19
+ if (!ctx) {
20
+ throw new Error("useExpenseApiContext must be used within ExpenseApiProvider");
21
+ }
22
+ return ctx;
23
+ };
24
+ // ============================================================================
25
+ // PROVIDER
26
+ // ============================================================================
27
+ const normalizeDate = (date) => {
28
+ if (!date)
29
+ return "";
30
+ try {
31
+ return new Date(date).toISOString().split("T")[0];
32
+ }
33
+ catch (_a) {
34
+ return "";
35
+ }
36
+ };
37
+ export const ExpenseApiProvider = ({ children, }) => {
38
+ var _a;
39
+ const context = useExpenseContext();
40
+ const { dispatch } = context;
41
+ const state = context.state;
42
+ const t = useTranslations("expense");
43
+ const { theme } = useTheme();
44
+ const workspace = getCachedWorkspaceSync();
45
+ const debouncedQuery = useDebounce(state.searchQuery, 800);
46
+ const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
47
+ // ==========================================================================
48
+ // UTILITIES
49
+ // ==========================================================================
50
+ const showToast = useCallback((description, variant) => {
51
+ generateThemeToast({
52
+ description,
53
+ theme: theme,
54
+ variant,
55
+ });
56
+ }, [theme]);
57
+ const resetFormAndCloseDrawer = useCallback(() => {
58
+ dispatch({ type: EXPENSE_ACTION_TYPES.RESET_FORM });
59
+ dispatch({
60
+ type: EXPENSE_ACTION_TYPES.SET_ERRORS,
61
+ payload: { errors: {} },
62
+ });
63
+ dispatch({
64
+ type: EXPENSE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
65
+ payload: { disabled: false },
66
+ });
67
+ dispatch({
68
+ type: EXPENSE_ACTION_TYPES.SET_DRAWER,
69
+ payload: { drawer: null },
70
+ });
71
+ }, [dispatch]);
72
+ // ==========================================================================
73
+ // API PARAMETERS
74
+ // ==========================================================================
75
+ 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
76
+ ? { filterEnabled: state.filterEnabled }
77
+ : {}))), [
78
+ state.currentPage,
79
+ state.filterCategory,
80
+ state.filterEnabled,
81
+ state.filterStatus,
82
+ state.pageLimit,
83
+ debouncedQuery,
84
+ schoolId,
85
+ ]);
86
+ const updateParams = useMemo(() => ({
87
+ amount: state.amount,
88
+ approvedBy: state.approvedBy || null,
89
+ attachments: state.attachments,
90
+ category: state.category,
91
+ description: state.description || null,
92
+ enabled: state.enabled,
93
+ expenseDate: state.expenseDate,
94
+ id: state.id,
95
+ invoiceNumber: state.invoiceNumber || null,
96
+ paidBy: state.paidBy || null,
97
+ paymentDate: state.paymentDate || null,
98
+ paymentMethod: state.paymentMethod || null,
99
+ receiptNumber: state.receiptNumber || null,
100
+ remarks: state.remarks || null,
101
+ schoolId,
102
+ status: state.status,
103
+ title: state.title,
104
+ transactionId: state.transactionId || null,
105
+ vendorContact: state.vendorContact || null,
106
+ vendorName: state.vendorName || null,
107
+ }), [state, schoolId]);
108
+ const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
109
+ const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
110
+ // ==========================================================================
111
+ // API CALLBACKS
112
+ // ==========================================================================
113
+ const listCallback = useCallback(({ data, error }) => {
114
+ var _a;
115
+ if (error) {
116
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
117
+ return;
118
+ }
119
+ if (data) {
120
+ const response = data;
121
+ const items = (_a = response.items) !== null && _a !== void 0 ? _a : [];
122
+ const count = typeof response.count === "number" ? response.count : 0;
123
+ dispatch({
124
+ type: EXPENSE_ACTION_TYPES.SET_ITEMS,
125
+ payload: { items, count },
126
+ });
127
+ }
128
+ }, [dispatch, showToast, t]);
129
+ const listFetchNowRef = useRef(null);
130
+ const updateCallback = useCallback(({ data, error }) => {
131
+ var _a;
132
+ if (error) {
133
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
134
+ return;
135
+ }
136
+ if (data) {
137
+ const isCreated = isCreatedOrUpdated(data);
138
+ showToast(isCreated ? t("messagesExpenseCreated") : t("messagesExpenseUpdated"), TOAST_VARIANT.SUCCESS);
139
+ resetFormAndCloseDrawer();
140
+ (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
141
+ }
142
+ }, [showToast, t, resetFormAndCloseDrawer]);
143
+ const byIdCallback = useCallback(({ data, error }) => {
144
+ if (error) {
145
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
146
+ return;
147
+ }
148
+ if (data) {
149
+ const expense = data;
150
+ dispatch({
151
+ type: EXPENSE_ACTION_TYPES.SET_FORM_DATA,
152
+ payload: {
153
+ form: Object.assign(Object.assign({}, expense), { expenseDate: normalizeDate(expense.expenseDate), paymentDate: normalizeDate(expense.paymentDate), paymentMethod: expense.paymentMethod || "", filterEnabled: undefined, filterCategory: "", filterStatus: "" }),
154
+ },
155
+ });
156
+ }
157
+ }, [dispatch, showToast, t]);
158
+ const deleteCallback = useCallback(({ data, error }) => {
159
+ var _a;
160
+ if (error) {
161
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
162
+ return;
163
+ }
164
+ if (data) {
165
+ showToast(t("messagesExpenseDeleted"), TOAST_VARIANT.SUCCESS);
166
+ (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
167
+ }
168
+ }, [showToast, t]);
169
+ // ==========================================================================
170
+ // SINGLE API HOOK INSTANCE
171
+ // ==========================================================================
172
+ const { listFetchNow, listLoading, updateFetchNow, updateLoading, byIdFetchNow, deleteFetchNow, deleteLoading, byIdLoading, } = useModuleEntityV2({
173
+ byIdCallback,
174
+ byIdParams,
175
+ deleteCallback,
176
+ deleteParams,
177
+ headers: {
178
+ "Content-Type": "application/json",
179
+ },
180
+ listCallback,
181
+ listParams,
182
+ listUrl: EXPENSE_API_ROUTES.UNIT,
183
+ searchQuery: debouncedQuery,
184
+ unitByIdUrl: EXPENSE_API_ROUTES.UNIT,
185
+ unitUrl: EXPENSE_API_ROUTES.UNIT,
186
+ updateCallback,
187
+ updateParams,
188
+ });
189
+ // ==========================================================================
190
+ // REF SYNC (for callbacks to always call the latest fetch)
191
+ // ==========================================================================
192
+ useEffect(() => {
193
+ listFetchNowRef.current = listFetchNow;
194
+ }, [listFetchNow]);
195
+ // ==========================================================================
196
+ // AUTO-FETCH EFFECT (runs once, not per child mount)
197
+ // ==========================================================================
198
+ useEffect(() => {
199
+ var _a;
200
+ if (!schoolId)
201
+ return;
202
+ (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
203
+ }, [listParams, schoolId]);
204
+ // ==========================================================================
205
+ // CONTEXT VALUE
206
+ // ==========================================================================
207
+ const value = useMemo(() => ({
208
+ listFetchNow,
209
+ listLoading,
210
+ updateFetchNow,
211
+ updateLoading,
212
+ byIdFetchNow,
213
+ byIdLoading,
214
+ deleteFetchNow,
215
+ deleteLoading,
216
+ resetFormAndCloseDrawer,
217
+ }), [
218
+ listFetchNow,
219
+ listLoading,
220
+ updateFetchNow,
221
+ updateLoading,
222
+ byIdFetchNow,
223
+ byIdLoading,
224
+ deleteFetchNow,
225
+ deleteLoading,
226
+ resetFormAndCloseDrawer,
227
+ ]);
228
+ return (_jsx(ExpenseApiContext.Provider, { value: value, children: children }));
229
+ };
@@ -0,0 +1,3 @@
1
+ export { EXPENSE_DRAWER, EXPENSE_ACTION_TYPES, expenseModuleConfig, initialExpenseState, ExpenseProvider, expenseReducer, useExpenseContext, } from "./shared";
2
+ export { ExpenseApiProvider, useExpenseApiContext, } from "./expense-api-provider";
3
+ export { useExpenseModule } from "./use-expense-module";
@@ -0,0 +1,3 @@
1
+ export { EXPENSE_DRAWER, EXPENSE_ACTION_TYPES, expenseModuleConfig, initialExpenseState, ExpenseProvider, expenseReducer, useExpenseContext, } from "./shared";
2
+ export { ExpenseApiProvider, useExpenseApiContext, } from "./expense-api-provider";
3
+ export { useExpenseModule } from "./use-expense-module";
@@ -1,11 +1,16 @@
1
- import { type RowAction, type TableRow } from "@appcorp/shadcn/components/enhanced-table";
2
- import { EXPENSE_CATEGORY, EXPENSE_STATUS, ExpenseBE, PAYMENT_METHOD, SchoolBE } from "../../type";
1
+ import { EXPENSE_CATEGORY, EXPENSE_STATUS, ExpenseBE, PAYMENT_METHOD, SchoolBE } from "../../../type";
3
2
  export declare const EXPENSE_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 ExpensesListResponse {
9
+ items: ExpenseBE[];
10
+ count: number;
11
+ currentPage: number;
12
+ pageLimit: number;
13
+ }
9
14
  export declare const EXPENSE_ACTION_TYPES: {
10
15
  readonly RESET_FORM: "RESET_FORM";
11
16
  readonly SET_CURRENT_PAGE: "SET_CURRENT_PAGE";
@@ -186,68 +191,3 @@ export declare const EXPENSE_ACTION_TYPES: {
186
191
  filterStatus: EXPENSE_STATUS | "";
187
192
  school: SchoolBE | undefined;
188
193
  }>;
189
- export declare const useExpenseModule: () => {
190
- applyFilters: () => void;
191
- byIdLoading: boolean;
192
- clearFilters: () => void;
193
- clearSearch: () => void;
194
- closeDrawer: () => void;
195
- deleteLoading: boolean;
196
- handleChange: (field: string, value: string | number | boolean | string[] | undefined) => void;
197
- handleCreate: () => void;
198
- handleDelete: (row?: TableRow) => void;
199
- handleEdit: (row?: TableRow) => void;
200
- handleFilters: () => void;
201
- handleMoreActions: () => void;
202
- handlePageChange: (page: number | unknown) => void;
203
- handlePageLimitChange: (k: string, value: object) => void;
204
- handleSearch: (query: string) => void;
205
- handleSubmit: () => void;
206
- handleView: (row?: TableRow) => void;
207
- headerActions: {
208
- enabled: boolean;
209
- handleOnClick: () => void;
210
- label: string;
211
- order: number;
212
- }[];
213
- listFetchNow: (url?: string, config?: import("@react-pakistan/util-functions/hooks/use-fetch").FetchConfig) => void;
214
- listLoading: boolean;
215
- rowActions: RowAction[];
216
- updateLoading: boolean;
217
- handleCloseDrawer?: () => void;
218
- state: {
219
- items: ExpenseBE[];
220
- count: number;
221
- currentPage: number;
222
- pageLimit: number;
223
- searchQuery: string;
224
- disableSaveButton: boolean;
225
- drawer: string | null;
226
- errors: Record<string, string>;
227
- amount: number;
228
- approvedBy: string;
229
- attachments: string[];
230
- category: EXPENSE_CATEGORY | "";
231
- description: string;
232
- enabled: boolean;
233
- expenseDate: string;
234
- id: string;
235
- invoiceNumber: string;
236
- paidBy: string;
237
- paymentDate: string;
238
- paymentMethod: PAYMENT_METHOD | "";
239
- receiptNumber: string;
240
- remarks: string;
241
- schoolId: string;
242
- status: EXPENSE_STATUS | "";
243
- title: string;
244
- transactionId: string;
245
- vendorContact: string;
246
- vendorName: string;
247
- filterCategory: EXPENSE_CATEGORY | "";
248
- filterEnabled: boolean | undefined;
249
- filterStatus: EXPENSE_STATUS | "";
250
- school: SchoolBE | undefined;
251
- };
252
- dispatch: React.Dispatch<any>;
253
- };
@@ -0,0 +1,63 @@
1
+ "use client";
2
+ import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
3
+ import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
4
+ import { PAYMENT_METHOD, } from "../../../type";
5
+ import { pageLimit } from "../constants";
6
+ // ============================================================================
7
+ // 1.1 DRAWER TYPES
8
+ // ============================================================================
9
+ export const EXPENSE_DRAWER = {
10
+ FILTER_DRAWER: DRAWER_TYPES.FILTER_DRAWER,
11
+ FORM_DRAWER: DRAWER_TYPES.FORM_DRAWER,
12
+ MORE_ACTIONS_DRAWER: DRAWER_TYPES.MORE_ACTIONS_DRAWER,
13
+ VIEW_DRAWER: DRAWER_TYPES.VIEW_DRAWER,
14
+ };
15
+ const expenseConfig = {
16
+ name: "Expense",
17
+ displayName: "Expense",
18
+ drawerTypes: DRAWER_TYPES,
19
+ initialState: {
20
+ // List Data
21
+ items: [],
22
+ count: 0,
23
+ // Search & Pagination
24
+ currentPage: 1,
25
+ pageLimit,
26
+ searchQuery: "",
27
+ // UI State
28
+ disableSaveButton: false,
29
+ drawer: null,
30
+ errors: {},
31
+ // Form fields
32
+ amount: 0,
33
+ approvedBy: "",
34
+ attachments: [],
35
+ category: "",
36
+ description: "",
37
+ enabled: true,
38
+ expenseDate: new Date().toISOString().slice(0, 10),
39
+ id: "",
40
+ invoiceNumber: "",
41
+ paidBy: "",
42
+ paymentDate: new Date().toISOString().slice(0, 10),
43
+ paymentMethod: PAYMENT_METHOD.CASH,
44
+ receiptNumber: "",
45
+ remarks: "",
46
+ schoolId: "",
47
+ status: "",
48
+ title: "",
49
+ transactionId: "",
50
+ vendorContact: "",
51
+ vendorName: "",
52
+ // Filters
53
+ filterCategory: "",
54
+ filterEnabled: undefined,
55
+ filterStatus: "",
56
+ // Relations
57
+ school: undefined,
58
+ },
59
+ };
60
+ // ============================================================================
61
+ // 1.3 CREATE EXPENSE MODULE
62
+ // ============================================================================
63
+ export const { actionTypes: EXPENSE_ACTION_TYPES, config: expenseModuleConfig, initialState: initialExpenseState, Provider: ExpenseProvider, reducer: expenseReducer, useContext: useExpenseContext, } = createGenericModule(expenseConfig);
@@ -0,0 +1,66 @@
1
+ import { type RowAction, type TableRow } from "@appcorp/shadcn/components/enhanced-table";
2
+ export declare const useExpenseModule: () => {
3
+ applyFilters: () => void;
4
+ byIdLoading: boolean;
5
+ clearFilters: () => void;
6
+ clearSearch: () => void;
7
+ closeDrawer: () => void;
8
+ deleteLoading: boolean;
9
+ handleChange: (field: string, value: string | number | boolean | string[] | undefined) => void;
10
+ handleCreate: () => void;
11
+ handleDelete: (row?: TableRow) => void;
12
+ handleEdit: (row?: TableRow) => void;
13
+ handleFilters: () => void;
14
+ handleMoreActions: () => void;
15
+ handlePageChange: (page: number | unknown) => void;
16
+ handlePageLimitChange: (k: string, value: object) => void;
17
+ handleSearch: (query: string) => void;
18
+ handleSubmit: () => void;
19
+ handleView: (row?: TableRow) => void;
20
+ headerActions: {
21
+ enabled: boolean;
22
+ handleOnClick: () => void;
23
+ label: string;
24
+ order: number;
25
+ }[];
26
+ listFetchNow: (url?: string, config?: import("@react-pakistan/util-functions/hooks/use-fetch").FetchConfig) => void;
27
+ listLoading: boolean;
28
+ rowActions: RowAction[];
29
+ updateLoading: boolean;
30
+ handleCloseDrawer?: () => void;
31
+ state: {
32
+ items: import("../../../types").ExpenseBE[];
33
+ count: number;
34
+ currentPage: number;
35
+ pageLimit: number;
36
+ searchQuery: string;
37
+ disableSaveButton: boolean;
38
+ drawer: string | null;
39
+ errors: Record<string, string>;
40
+ amount: number;
41
+ approvedBy: string;
42
+ attachments: string[];
43
+ category: import("../../../types").EXPENSE_CATEGORY | "";
44
+ description: string;
45
+ enabled: boolean;
46
+ expenseDate: string;
47
+ id: string;
48
+ invoiceNumber: string;
49
+ paidBy: string;
50
+ paymentDate: string;
51
+ paymentMethod: import("../../../types").PAYMENT_METHOD | "";
52
+ receiptNumber: string;
53
+ remarks: string;
54
+ schoolId: string;
55
+ status: import("../../../types").EXPENSE_STATUS | "";
56
+ title: string;
57
+ transactionId: string;
58
+ vendorContact: string;
59
+ vendorName: string;
60
+ filterCategory: import("../../../types").EXPENSE_CATEGORY | "";
61
+ filterEnabled: boolean | undefined;
62
+ filterStatus: import("../../../types").EXPENSE_STATUS | "";
63
+ school: import("../../../types").SchoolBE | undefined;
64
+ };
65
+ dispatch: React.Dispatch<any>;
66
+ };