@appcorp/fusion-storybook 0.1.63 → 0.1.64

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 (61) hide show
  1. package/base-modules/discount-code/context.d.ts +53 -43
  2. package/base-modules/discount-code/context.js +179 -135
  3. package/base-modules/discount-code/page.d.ts +13 -7
  4. package/base-modules/discount-code/page.js +17 -13
  5. package/base-modules/rbac/assign-permissions.d.ts +1 -0
  6. package/base-modules/rbac/assign-permissions.js +53 -0
  7. package/base-modules/rbac/cache.d.ts +27 -0
  8. package/base-modules/rbac/cache.js +46 -0
  9. package/base-modules/rbac/constants.d.ts +17 -0
  10. package/base-modules/rbac/constants.js +28 -0
  11. package/base-modules/rbac/context.d.ts +190 -0
  12. package/base-modules/rbac/context.js +539 -0
  13. package/base-modules/rbac/filter.d.ts +1 -0
  14. package/base-modules/rbac/filter.js +18 -0
  15. package/base-modules/rbac/form.d.ts +1 -0
  16. package/base-modules/rbac/form.js +13 -0
  17. package/base-modules/rbac/more-actions.d.ts +6 -0
  18. package/base-modules/rbac/more-actions.js +10 -0
  19. package/base-modules/rbac/page.d.ts +35 -0
  20. package/base-modules/rbac/page.js +142 -0
  21. package/base-modules/rbac/validate.d.ts +10 -0
  22. package/base-modules/rbac/validate.js +13 -0
  23. package/base-modules/rbac/view.d.ts +1 -0
  24. package/base-modules/rbac/view.js +33 -0
  25. package/base-modules/school/cache.d.ts +9 -0
  26. package/base-modules/school/cache.js +28 -0
  27. package/base-modules/school/constants.d.ts +9 -0
  28. package/base-modules/school/constants.js +17 -0
  29. package/base-modules/school/context.d.ts +157 -0
  30. package/base-modules/school/context.js +285 -0
  31. package/base-modules/school/drawer.d.ts +1 -0
  32. package/base-modules/school/drawer.js +24 -0
  33. package/base-modules/school/filter.d.ts +1 -0
  34. package/base-modules/school/filter.js +13 -0
  35. package/base-modules/school/form.d.ts +1 -0
  36. package/base-modules/school/form.js +30 -0
  37. package/base-modules/school/more-actions.d.ts +1 -0
  38. package/base-modules/school/more-actions.js +13 -0
  39. package/base-modules/school/page.d.ts +24 -0
  40. package/base-modules/school/page.js +41 -0
  41. package/base-modules/school/validate.d.ts +23 -0
  42. package/base-modules/school/validate.js +26 -0
  43. package/base-modules/school/view.d.ts +1 -0
  44. package/base-modules/school/view.js +24 -0
  45. package/base-modules/user/context.d.ts +4 -3
  46. package/base-modules/user/context.js +251 -229
  47. package/base-modules/user/page.d.ts +15 -9
  48. package/base-modules/user/page.js +19 -14
  49. package/base-modules/workspace/context.d.ts +14 -13
  50. package/base-modules/workspace/context.js +100 -98
  51. package/base-modules/workspace/drawer.js +3 -1
  52. package/base-modules/workspace/form.js +4 -4
  53. package/base-modules/workspace/page.d.ts +4 -2
  54. package/base-modules/workspace/page.js +15 -1
  55. package/base-modules/workspace-user/constants.js +1 -0
  56. package/base-modules/workspace-user/context.d.ts +19 -0
  57. package/base-modules/workspace-user/context.js +44 -27
  58. package/base-modules/workspace-user/page.d.ts +1 -1
  59. package/base-modules/workspace-user/page.js +22 -11
  60. package/package.json +1 -1
  61. package/tsconfig.build.tsbuildinfo +1 -1
@@ -1,35 +1,37 @@
1
1
  "use client";
2
2
  /**
3
- * Discount Code Module — business logic + API integration
3
+ * Discount Code Context
4
4
  *
5
5
  * Wires the generic module state (created by `createGenericModule`) to network
6
6
  * actions using `useModuleEntityV2`. Contains domain-specific handlers for
7
- * create/view/edit/delete operations.
7
+ * CRUD operations, pagination, and search.
8
8
  *
9
9
  * Key responsibilities:
10
- * - expose `useDiscountCodeModule()` which UI components call for actions
11
- * - keep module-specific `apiParams` and callbacks in one place
12
- * - ensure cache invalidation and toast notifications on mutation
10
+ * - Expose `useDiscountCodeModule()` which UI components call for actions
11
+ * - Keep module-specific `apiParams` and callbacks in one place
12
+ * - Ensure cache invalidation and toast notifications on mutation
13
13
  *
14
14
  * Exported utilities:
15
15
  * - `DiscountCodeProvider` — provider component used by the page
16
+ * - `DISCOUNT_CODE_ACTION_TYPES` — action type constants (from factory)
17
+ * - `DISCOUNT_CODE_DRAWER` — drawer type constants
16
18
  * - `useDiscountCodeModule()` — hook that returns state, dispatch, and handlers
17
19
  */
18
- import { useCallback, useEffect, useMemo } from "react";
20
+ import { useCallback, useEffect, useMemo, useRef } from "react";
21
+ import { useTheme } from "next-themes";
22
+ import { useTranslations } from "next-intl";
19
23
  import { isCreatedOrUpdated, validateForm, } from "@react-pakistan/util-functions";
20
24
  import { useModuleEntityV2, } from "@react-pakistan/util-functions/hooks/use-module-entity-v2";
21
25
  import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
22
26
  import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
23
27
  import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
28
+ import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
24
29
  import { DISCOUNT_CODE_API_ROUTES, pageLimit } from "./constants";
25
- import { getCachedDiscountCodes, invalidateDiscountCodeCache } from "./cache";
26
30
  import { accountDiscountCodeFormValidation } from "./validate";
27
- import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
28
- import { useTranslations } from "next-intl";
31
+ import { getCachedDiscountCodes, invalidateDiscountCodeCache } from "./cache";
29
32
  import { getCachedWorkspaceSync } from "../workspace/cache";
30
- import { Filter, Plus } from "lucide-react";
31
33
  // ============================================================================
32
- // DRAWER TYPES
34
+ // 1.1 DRAWER TYPES
33
35
  // ============================================================================
34
36
  export const DISCOUNT_CODE_DRAWER = {
35
37
  FILTER_DRAWER: DRAWER_TYPES.FILTER_DRAWER,
@@ -38,15 +40,25 @@ export const DISCOUNT_CODE_DRAWER = {
38
40
  VIEW_DRAWER: DRAWER_TYPES.VIEW_DRAWER,
39
41
  };
40
42
  // ============================================================================
41
- // CONFIGURATION
43
+ // 1.2 MODULE CONFIGURATION
42
44
  // ============================================================================
43
45
  const discountCodeConfig = {
44
46
  name: "DiscountCode",
45
47
  displayName: "Discount Code",
48
+ drawerTypes: DRAWER_TYPES,
46
49
  initialState: {
50
+ // Form State
51
+ code: "",
52
+ description: "",
53
+ discountType: "",
54
+ discountValue: 0,
55
+ enabled: true,
56
+ errors: {},
57
+ filterEnabled: undefined,
58
+ id: "",
47
59
  // List Data
48
- items: [],
49
60
  count: 0,
61
+ items: [],
50
62
  // Search & Pagination
51
63
  currentPage: 1,
52
64
  pageLimit,
@@ -55,34 +67,31 @@ const discountCodeConfig = {
55
67
  disableSaveButton: false,
56
68
  drawer: null,
57
69
  modal: null,
58
- // Form State
59
- code: "",
60
- description: "",
61
- discountType: "",
62
- discountValue: 0,
63
- enabled: true,
64
- errors: {},
65
- filterEnabled: undefined,
66
- id: "",
67
70
  },
68
- drawerTypes: DRAWER_TYPES,
69
71
  };
70
72
  // ============================================================================
71
- // CREATE DISCOUNT CODE MODULE
73
+ // 1.3 CREATE DISCOUNT CODE MODULE
72
74
  // ============================================================================
73
75
  export const { actionTypes: DISCOUNT_CODE_ACTION_TYPES, config: discountCodeModuleConfig, initialState: initialDiscountCodeState, Provider: DiscountCodeProvider, reducer: discountCodeReducer, useContext: useDiscountCodeStateContext, } = createGenericModule(discountCodeConfig);
74
76
  // ============================================================================
75
- // ENHANCED DISCOUNT CODE HOOK WITH API INTEGRATION
77
+ // 1.4 ENHANCED DISCOUNT CODE HOOK WITH API INTEGRATION
76
78
  // ============================================================================
77
79
  export const useDiscountCodeModule = () => {
78
80
  var _a;
79
- const { state, dispatch } = useDiscountCodeStateContext();
81
+ // ============================================================================
82
+ // 1.4.1 STATE & CORE HOOKS
83
+ // ============================================================================
84
+ const context = useDiscountCodeStateContext();
85
+ const { dispatch } = context;
86
+ const state = context.state;
80
87
  const t = useTranslations("discountCode");
88
+ const { theme } = useTheme();
81
89
  const workspace = getCachedWorkspaceSync();
82
90
  const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
91
+ const listFetchNowRef = useRef(null);
83
92
  const debouncedQuery = useDebounce(state.searchQuery, 800);
84
93
  // ============================================================================
85
- // API PARAMETERS
94
+ // 1.4.2 API PARAMETERS
86
95
  // ============================================================================
87
96
  const listParams = useMemo(() => (Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterEnabled !== undefined
88
97
  ? { filterEnabled: String(state.filterEnabled) }
@@ -113,11 +122,32 @@ export const useDiscountCodeModule = () => {
113
122
  const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
114
123
  const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
115
124
  // ============================================================================
116
- // API CALLBACKS
125
+ // 1.4.3 UTILITIES
126
+ // ============================================================================
127
+ const showToast = useCallback((description, variant) => {
128
+ generateThemeToast({
129
+ description,
130
+ theme: theme,
131
+ variant,
132
+ });
133
+ }, [theme]);
134
+ const resetFormAndCloseDrawer = useCallback(() => {
135
+ dispatch({ type: DISCOUNT_CODE_ACTION_TYPES.RESET_FORM });
136
+ dispatch({
137
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_ERRORS,
138
+ payload: { errors: {} },
139
+ });
140
+ dispatch({
141
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_DRAWER,
142
+ payload: { drawer: null },
143
+ });
144
+ }, [dispatch]);
145
+ // ============================================================================
146
+ // 1.4.4 API CALLBACKS
117
147
  // ============================================================================
118
- const listCallback = ({ data, error }) => {
148
+ const listCallback = useCallback(({ data, error }) => {
119
149
  if (error) {
120
- showToast(t("messagesFetchFailed"), TOAST_VARIANT.ERROR);
150
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
121
151
  return;
122
152
  }
123
153
  if (data) {
@@ -126,56 +156,51 @@ export const useDiscountCodeModule = () => {
126
156
  payload: { items: data.items || [], count: data.count || 0 },
127
157
  });
128
158
  }
129
- };
130
- const updateCallback = ({ data, error }) => {
131
- const isCreated = isCreatedOrUpdated(data);
159
+ }, [dispatch, showToast, t]);
160
+ const updateCallback = useCallback(({ data, error }) => {
161
+ var _a;
132
162
  if (error) {
133
- showToast(isCreated ? t("messagesCreateFailed") : t("messagesUpdateFailed"), TOAST_VARIANT.ERROR);
163
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
134
164
  return;
135
165
  }
136
166
  if (data) {
137
- showToast(t("messagesSaveSuccess"), TOAST_VARIANT.SUCCESS);
167
+ const isCreated = isCreatedOrUpdated(data);
138
168
  invalidateDiscountCodeCache();
139
- listFetchNow();
169
+ showToast(isCreated
170
+ ? t("messagesDiscountCodeCreated")
171
+ : t("messagesDiscountCodeUpdated"), TOAST_VARIANT.SUCCESS);
140
172
  resetFormAndCloseDrawer();
173
+ (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
141
174
  }
142
- };
143
- const byIdCallback = ({ data, error }) => {
175
+ }, [resetFormAndCloseDrawer, showToast, t]);
176
+ const byIdCallback = useCallback(({ data, error }) => {
144
177
  if (error) {
145
- showToast(t("messagesDetailsFetchFailed"), TOAST_VARIANT.ERROR);
178
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
146
179
  return;
147
180
  }
148
181
  if (data) {
149
- const discountCode = data;
150
- // Batch field updates for better performance
151
- const fieldMappings = {
152
- id: discountCode.id,
153
- code: discountCode.code,
154
- description: discountCode.description,
155
- discountType: discountCode.discountType,
156
- discountValue: discountCode.discountValue,
157
- enabled: discountCode.enabled,
158
- };
159
- Object.entries(fieldMappings).forEach(([key, value]) => {
160
- setField(key, value !== null && value !== void 0 ? value : undefined);
182
+ dispatch({
183
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_FORM_DATA,
184
+ payload: { form: data },
161
185
  });
162
186
  }
163
- };
164
- const deleteCallback = ({ data, error }) => {
187
+ }, [dispatch, showToast, t]);
188
+ const deleteCallback = useCallback(({ data, error }) => {
189
+ var _a;
165
190
  if (error) {
166
- showToast(t("messagesDeleteFailed"), TOAST_VARIANT.ERROR);
191
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
167
192
  return;
168
193
  }
169
194
  if (data) {
170
- showToast(t("messagesDeleteSuccess"), TOAST_VARIANT.SUCCESS);
171
195
  invalidateDiscountCodeCache();
172
- listFetchNow();
196
+ showToast(t("messagesDiscountCodeDeleted"), TOAST_VARIANT.SUCCESS);
197
+ (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
173
198
  }
174
- };
199
+ }, [showToast, t]);
175
200
  // ============================================================================
176
- // API HOOKS
201
+ // 1.4.5 API HOOKS
177
202
  // ============================================================================
178
- const { listFetchNow, listLoading, updateFetchNow, updateLoading, byIdFetchNow, deleteFetchNow, deleteLoading, byIdLoading, } = useModuleEntityV2({
203
+ const { byIdFetchNow, byIdLoading, deleteFetchNow, deleteLoading, listError, listFetchNow, listLoading, updateFetchNow, updateLoading, } = useModuleEntityV2({
179
204
  byIdCallback,
180
205
  byIdParams,
181
206
  deleteCallback,
@@ -194,52 +219,52 @@ export const useDiscountCodeModule = () => {
194
219
  },
195
220
  });
196
221
  // ============================================================================
197
- // UTILITIES
222
+ // 1.4.6 HANDLERS
198
223
  // ============================================================================
199
- const showToast = useCallback((message, variant) => {
200
- generateThemeToast({ description: message, variant });
201
- }, []);
202
- const resetFormAndCloseDrawer = useCallback(() => {
224
+ const handleChange = useCallback((key, value) => {
203
225
  dispatch({
204
226
  type: DISCOUNT_CODE_ACTION_TYPES.SET_ERRORS,
205
227
  payload: { errors: {} },
206
228
  });
207
229
  dispatch({
208
230
  type: DISCOUNT_CODE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
209
- payload: { disabled: false },
231
+ payload: { disableSaveButton: false },
210
232
  });
211
233
  dispatch({
212
- type: DISCOUNT_CODE_ACTION_TYPES.SET_DRAWER,
213
- payload: { drawer: null },
234
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_INPUT_FIELD,
235
+ payload: { key, value },
214
236
  });
215
237
  }, [dispatch]);
216
- const setField = useCallback((key, value) => {
238
+ const closeDrawer = useCallback(() => {
239
+ resetFormAndCloseDrawer();
240
+ }, [resetFormAndCloseDrawer]);
241
+ const handleNextClick = useCallback(() => {
217
242
  dispatch({
218
- type: DISCOUNT_CODE_ACTION_TYPES.SET_INPUT_FIELD,
219
- payload: { field: key, value },
243
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_CURRENT_PAGE,
244
+ payload: { currentPage: state.currentPage + 1 },
220
245
  });
221
- }, [dispatch]);
222
- // ============================================================================
223
- // HANDLERS
224
- // ============================================================================
225
- const handleChange = useCallback((field, value) => {
246
+ }, [dispatch, state.currentPage]);
247
+ const handlePreviousClick = useCallback(() => {
226
248
  dispatch({
227
- type: DISCOUNT_CODE_ACTION_TYPES.SET_ERRORS,
228
- payload: { errors: {} },
249
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_CURRENT_PAGE,
250
+ payload: { currentPage: state.currentPage - 1 },
229
251
  });
252
+ }, [dispatch, state.currentPage]);
253
+ const handlePageChange = useCallback((page) => {
230
254
  dispatch({
231
- type: DISCOUNT_CODE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
232
- payload: { disabled: false },
255
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_CURRENT_PAGE,
256
+ payload: { currentPage: page },
233
257
  });
234
- setField(field, value);
235
- }, [setField, dispatch]);
236
- const handleCloseDrawer = useCallback(() => {
237
- resetFormAndCloseDrawer();
238
- }, [resetFormAndCloseDrawer]);
239
- const handleCreate = useCallback(() => {
258
+ }, [dispatch]);
259
+ const handlePageLimitChange = useCallback((k, value) => {
260
+ const val = Object.assign({}, value);
240
261
  dispatch({
241
- type: DISCOUNT_CODE_ACTION_TYPES.SET_DRAWER,
242
- payload: { drawer: DISCOUNT_CODE_DRAWER.FORM_DRAWER },
262
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_PAGE_LIMIT,
263
+ payload: { pageLimit: Number(val.option) },
264
+ });
265
+ dispatch({
266
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_CURRENT_PAGE,
267
+ payload: { currentPage: 1 },
243
268
  });
244
269
  }, [dispatch]);
245
270
  const handleView = useCallback((row) => {
@@ -257,28 +282,34 @@ export const useDiscountCodeModule = () => {
257
282
  });
258
283
  }, [byIdFetchNow, dispatch]);
259
284
  const handleDelete = useCallback((row) => {
260
- if (confirm(t("confirmDelete"))) {
285
+ if (confirm(t("messagesDeleteConfirmation"))) {
261
286
  deleteFetchNow === null || deleteFetchNow === void 0 ? void 0 : deleteFetchNow(undefined, {
262
287
  body: JSON.stringify({ id: row === null || row === void 0 ? void 0 : row.id }),
263
288
  });
264
289
  }
265
- }, [t, deleteFetchNow]);
290
+ }, [deleteFetchNow, t]);
291
+ const handleCreate = useCallback(() => {
292
+ dispatch({
293
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_DRAWER,
294
+ payload: { drawer: DISCOUNT_CODE_DRAWER.FORM_DRAWER },
295
+ });
296
+ }, [dispatch]);
266
297
  const handleFilters = useCallback(() => {
267
298
  dispatch({
268
299
  type: DISCOUNT_CODE_ACTION_TYPES.SET_DRAWER,
269
300
  payload: { drawer: DISCOUNT_CODE_DRAWER.FILTER_DRAWER },
270
301
  });
271
302
  }, [dispatch]);
272
- const handlePageChange = useCallback((page) => {
303
+ const handleMoreActions = useCallback(() => {
273
304
  dispatch({
274
- type: DISCOUNT_CODE_ACTION_TYPES.SET_CURRENT_PAGE,
275
- payload: { currentPage: page },
305
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_DRAWER,
306
+ payload: { drawer: DISCOUNT_CODE_DRAWER.MORE_ACTIONS_DRAWER },
276
307
  });
277
308
  }, [dispatch]);
278
- const handlePageLimitChange = useCallback((limit) => {
309
+ const clearSearch = useCallback(() => {
279
310
  dispatch({
280
- type: DISCOUNT_CODE_ACTION_TYPES.SET_PAGE_LIMIT,
281
- payload: { pageLimit: limit },
311
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_SEARCH_QUERY,
312
+ payload: { searchQuery: "" },
282
313
  });
283
314
  }, [dispatch]);
284
315
  const handleSearch = useCallback((query) => {
@@ -287,20 +318,31 @@ export const useDiscountCodeModule = () => {
287
318
  payload: { searchQuery: query },
288
319
  });
289
320
  }, [dispatch]);
290
- const clearFilters = useCallback(() => {
321
+ const applyFilters = useCallback(() => {
291
322
  dispatch({
292
- type: DISCOUNT_CODE_ACTION_TYPES.SET_FILTERS,
293
- payload: { filters: { filterEnabled: undefined } },
323
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_CURRENT_PAGE,
324
+ payload: { currentPage: 1 },
294
325
  });
326
+ listFetchNow === null || listFetchNow === void 0 ? void 0 : listFetchNow();
327
+ closeDrawer();
328
+ }, [dispatch, listFetchNow, closeDrawer]);
329
+ const clearFilters = useCallback(() => {
295
330
  dispatch({
296
331
  type: DISCOUNT_CODE_ACTION_TYPES.SET_CURRENT_PAGE,
297
332
  payload: { currentPage: 1 },
298
333
  });
334
+ dispatch({
335
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_FILTERS,
336
+ payload: { filters: { filterEnabled: undefined } },
337
+ });
299
338
  }, [dispatch]);
339
+ // ============================================================================
340
+ // 1.4.7 NETWORK ACTIONS
341
+ // ============================================================================
300
342
  const handleSubmit = useCallback(() => {
301
343
  dispatch({
302
344
  type: DISCOUNT_CODE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
303
- payload: { disabled: true },
345
+ payload: { disableSaveButton: true },
304
346
  });
305
347
  validateForm({
306
348
  params: updateParams,
@@ -312,68 +354,64 @@ export const useDiscountCodeModule = () => {
312
354
  },
313
355
  errorCallback: (errors) => {
314
356
  dispatch({
315
- type: DISCOUNT_CODE_ACTION_TYPES.SET_ERRORS,
316
- payload: { errors },
357
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
358
+ payload: { disableSaveButton: false },
317
359
  });
318
360
  dispatch({
319
- type: DISCOUNT_CODE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
320
- payload: { disabled: false },
361
+ type: DISCOUNT_CODE_ACTION_TYPES.SET_ERRORS,
362
+ payload: { errors },
321
363
  });
322
- showToast(t("messagesFormErrors"), TOAST_VARIANT.ERROR);
364
+ showToast(t("messagesValidationError"), TOAST_VARIANT.ERROR);
323
365
  },
324
366
  });
325
- }, [dispatch, updateParams, t, showToast, updateFetchNow]);
367
+ }, [dispatch, showToast, t, updateFetchNow, updateParams]);
326
368
  // ============================================================================
327
- // HEADER & ROW ACTIONS
369
+ // 1.4.8 HEADER & ROW ACTIONS
328
370
  // ============================================================================
329
371
  const headerActions = useMemo(() => [
372
+ {
373
+ enabled: true,
374
+ handleOnClick: handleMoreActions,
375
+ label: t("actionsButtonMoreActions"),
376
+ order: 0,
377
+ },
330
378
  {
331
379
  enabled: true,
332
380
  handleOnClick: handleFilters,
333
- label: t("headerActionsFilters"),
381
+ label: t("actionsButtonFilters"),
334
382
  order: 1,
335
- icon: Filter,
336
383
  },
337
384
  {
338
385
  enabled: true,
339
386
  handleOnClick: handleCreate,
340
- label: t("headerActionsAdd"),
387
+ label: t("actionsButtonAddItem"),
341
388
  order: 2,
342
- icon: Plus,
343
389
  },
344
- ], [handleFilters, handleCreate, t]);
390
+ ], [handleCreate, handleFilters, handleMoreActions, t]);
345
391
  const rowActions = useMemo(() => [
346
392
  {
347
393
  enabled: true,
348
394
  handleOnClick: handleView,
349
- label: t("rowActionsView"),
395
+ label: t("actionsButtonView"),
350
396
  order: 1,
351
397
  },
352
398
  {
353
399
  enabled: true,
354
400
  handleOnClick: handleEdit,
355
- label: t("rowActionsEdit"),
401
+ label: t("actionsButtonEdit"),
356
402
  order: 2,
357
403
  },
358
404
  {
359
405
  enabled: true,
360
406
  handleOnClick: handleDelete,
361
- label: t("rowActionsDelete"),
407
+ label: t("actionsButtonDelete"),
362
408
  order: 3,
363
- variant: "destructive",
364
409
  },
365
- ], [handleView, handleEdit, handleDelete, t]);
366
- const applyFilters = useCallback(() => {
367
- dispatch({
368
- type: DISCOUNT_CODE_ACTION_TYPES.SET_CURRENT_PAGE,
369
- payload: { currentPage: 1 },
370
- });
371
- listFetchNow();
372
- handleCloseDrawer();
373
- }, [dispatch, listFetchNow, handleCloseDrawer]);
410
+ ], [handleDelete, handleEdit, handleView, t]);
374
411
  // ============================================================================
375
- // EFFECTS
412
+ // 1.4.9 EFFECTS
376
413
  // ============================================================================
414
+ // Initial load + re-fetch on page/search/filter change via cache
377
415
  useEffect(() => {
378
416
  if (!(workspace === null || workspace === void 0 ? void 0 : workspace.id))
379
417
  return;
@@ -388,34 +426,40 @@ export const useDiscountCodeModule = () => {
388
426
  });
389
427
  }
390
428
  catch (_a) {
391
- showToast(t("messagesFetchFailed"), TOAST_VARIANT.ERROR);
429
+ showToast(t("messagesNetworkError"), TOAST_VARIANT.ERROR);
392
430
  }
393
431
  })();
394
- }, [listParams, showToast, t, workspace === null || workspace === void 0 ? void 0 : workspace.id, dispatch]);
432
+ }, [dispatch, listParams, showToast, t, workspace === null || workspace === void 0 ? void 0 : workspace.id]);
433
+ // Keep ref in sync with latest listFetchNow (avoids stale closure in callbacks)
434
+ useEffect(() => {
435
+ listFetchNowRef.current = listFetchNow;
436
+ });
395
437
  // ============================================================================
396
- // RETURN
438
+ // 1.4.10 RETURN
397
439
  // ============================================================================
398
- return {
399
- state,
400
- dispatch,
401
- applyFilters,
440
+ return Object.assign(Object.assign({}, context), { applyFilters,
402
441
  byIdLoading,
403
442
  clearFilters,
443
+ clearSearch,
444
+ closeDrawer,
404
445
  deleteLoading,
405
446
  handleChange,
406
- handleCloseDrawer,
407
447
  handleCreate,
408
448
  handleDelete,
409
449
  handleEdit,
410
450
  handleFilters,
451
+ handleMoreActions,
452
+ handleNextClick,
411
453
  handlePageChange,
412
454
  handlePageLimitChange,
455
+ handlePreviousClick,
413
456
  handleSearch,
414
457
  handleSubmit,
415
458
  handleView,
416
459
  headerActions,
460
+ listError,
461
+ listFetchNow,
417
462
  listLoading,
418
463
  rowActions,
419
- updateLoading,
420
- };
464
+ updateLoading });
421
465
  };
@@ -1,13 +1,19 @@
1
1
  /**
2
2
  * Discount Code Page Component
3
3
  *
4
- * Thin wrapper around GenericModulePage. All handlers, header actions, and row
5
- * actions live in context.tsx this file only owns:
6
- * - tableBodyCols (static, module-level constant)
7
- * - discountCodeConfig (memoised on locale change only; size fixed so the
8
- * component type produced by createGenericModulePage never changes at
9
- * runtime, preventing the infinite-remount re-render loop)
10
- * - permission guard
4
+ * Uses the generic component factory pattern with discount-code-specific configuration.
5
+ * Receives all UI label strings as pre-translated props from the caller,
6
+ * so this component is translation-agnostic.
7
+ *
8
+ * Key responsibilities:
9
+ * - Define table column layout and row body column types
10
+ * - Build the module config (via factory) wiring passed label strings and content slots
11
+ * - Delegate header/row actions and navigation to the context hook
12
+ * - Apply RBAC guard before rendering discount code content
13
+ * - Pass the self-contained context directly to the generic page factory
14
+ *
15
+ * Exported utilities:
16
+ * - `DiscountCodePage` — root component that wraps with DiscountCodeProvider
11
17
  */
12
18
  import { FC } from "react";
13
19
  import { USER_ROLE } from "../../type";
@@ -1,16 +1,22 @@
1
- "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
1
  /**
4
2
  * Discount Code Page Component
5
3
  *
6
- * Thin wrapper around GenericModulePage. All handlers, header actions, and row
7
- * actions live in context.tsx this file only owns:
8
- * - tableBodyCols (static, module-level constant)
9
- * - discountCodeConfig (memoised on locale change only; size fixed so the
10
- * component type produced by createGenericModulePage never changes at
11
- * runtime, preventing the infinite-remount re-render loop)
12
- * - permission guard
4
+ * Uses the generic component factory pattern with discount-code-specific configuration.
5
+ * Receives all UI label strings as pre-translated props from the caller,
6
+ * so this component is translation-agnostic.
7
+ *
8
+ * Key responsibilities:
9
+ * - Define table column layout and row body column types
10
+ * - Build the module config (via factory) wiring passed label strings and content slots
11
+ * - Delegate header/row actions and navigation to the context hook
12
+ * - Apply RBAC guard before rendering discount code content
13
+ * - Pass the self-contained context directly to the generic page factory
14
+ *
15
+ * Exported utilities:
16
+ * - `DiscountCodePage` — root component that wraps with DiscountCodeProvider
13
17
  */
18
+ "use client";
19
+ import { jsx as _jsx } from "react/jsx-runtime";
14
20
  import { useMemo } from "react";
15
21
  import { COMPONENT_TYPE } from "@appcorp/shadcn/components/enhanced-table";
16
22
  import { createGenericModulePage, } from "@react-pakistan/util-functions/factory/generic-component-factory";
@@ -82,7 +88,6 @@ const DiscountCodePageInner = (props) => {
82
88
  // Memoize config creation - destructure props to avoid object reference changes
83
89
  const discountCodeConfig = useMemo(() => createDiscountCodeConfig({
84
90
  dispatch: context.dispatch,
85
- drawer: context.state.drawer,
86
91
  cancelLabel: props.cancelLabel,
87
92
  drawerTitle: props.drawerTitle,
88
93
  labelActions: props.labelActions,
@@ -98,7 +103,6 @@ const DiscountCodePageInner = (props) => {
98
103
  tableTitle: props.tableTitle,
99
104
  }), [
100
105
  context.dispatch,
101
- context.state.drawer,
102
106
  props.cancelLabel,
103
107
  props.drawerTitle,
104
108
  props.labelActions,
@@ -115,10 +119,10 @@ const DiscountCodePageInner = (props) => {
115
119
  ]);
116
120
  const hasPermission = resolveRbacPermissions({
117
121
  userRole: props.userRole,
118
- moduleName: "DiscountCode",
122
+ moduleName: "Discount Codes",
119
123
  });
120
124
  if (!hasPermission) {
121
- return _jsx(RbacNoAccess, { moduleName: "DiscountCode" });
125
+ return _jsx(RbacNoAccess, { moduleName: "Discount Codes" });
122
126
  }
123
127
  return (_jsx("div", { className: "p-4", children: _jsx(GenericDiscountCodePage, { overrideConfig: discountCodeConfig, context: context, tableBodyCols: tableBodyCols }) }));
124
128
  };
@@ -0,0 +1 @@
1
+ export declare const AssignPermissions: () => import("react/jsx-runtime").JSX.Element;