@appcorp/fusion-storybook 0.1.68 → 0.1.72

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.
@@ -0,0 +1,459 @@
1
+ "use client";
2
+ /**
3
+ * Campus Context
4
+ *
5
+ * Wires the generic module state (created by `createGenericModule`) to network
6
+ * actions using `useModuleEntityV2`. Contains domain-specific handlers for
7
+ * CRUD operations.
8
+ *
9
+ * Exported utilities:
10
+ * - `CampusProvider` — provider component used by the page
11
+ * - `CAMPUS_ACTION_TYPES` — action type constants (from factory)
12
+ * - `CAMPUS_DRAWER` — drawer type constants
13
+ * - `useCampusModule()` — hook that returns state, dispatch, and handlers
14
+ */
15
+ import { useCallback, useEffect, useMemo, useRef } from "react";
16
+ import { useTheme } from "next-themes";
17
+ import { useTranslations } from "next-intl";
18
+ import { isCreatedOrUpdated, validateForm, } from "@react-pakistan/util-functions";
19
+ import { useModuleEntityV2, } from "@react-pakistan/util-functions/hooks/use-module-entity-v2";
20
+ import { useDebounce } from "@react-pakistan/util-functions/hooks/use-debounce";
21
+ import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
22
+ import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
23
+ import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
24
+ import { CAMPUS_API_ROUTES, pageLimit } from "./constants";
25
+ import { campusFormValidation } from "./validate";
26
+ import { getCachedCampuses, invalidateCampusesCache } from "./cache";
27
+ import { getCachedWorkspaceSync } from "../workspace/cache";
28
+ // ============================================================================
29
+ // 1.1 DRAWER TYPES
30
+ // ============================================================================
31
+ export const CAMPUS_DRAWER = {
32
+ FILTER_DRAWER: DRAWER_TYPES.FILTER_DRAWER,
33
+ FORM_DRAWER: DRAWER_TYPES.FORM_DRAWER,
34
+ MORE_ACTIONS_DRAWER: DRAWER_TYPES.MORE_ACTIONS_DRAWER,
35
+ VIEW_DRAWER: DRAWER_TYPES.VIEW_DRAWER,
36
+ };
37
+ const campusConfig = {
38
+ name: "Campus",
39
+ displayName: "Campus",
40
+ drawerTypes: DRAWER_TYPES,
41
+ initialState: {
42
+ // List data
43
+ items: [],
44
+ count: 0,
45
+ // Search & Pagination
46
+ currentPage: 1,
47
+ pageLimit,
48
+ searchQuery: "",
49
+ // UI State
50
+ disableSaveButton: false,
51
+ drawer: null,
52
+ errors: {},
53
+ // Form State
54
+ address: null,
55
+ city: null,
56
+ code: "",
57
+ country: null,
58
+ enabled: true,
59
+ id: "",
60
+ name: "",
61
+ phone: null,
62
+ schoolId: "",
63
+ state: null,
64
+ // Filter State
65
+ filterEnabled: undefined,
66
+ },
67
+ };
68
+ // ============================================================================
69
+ // 1.3 CREATE CAMPUS MODULE
70
+ // ============================================================================
71
+ export const { actionTypes: CAMPUS_ACTION_TYPES, config: campusModuleConfig, initialState: initialCampusState, Provider: CampusProvider, reducer: campusReducer, useContext: useCampusContext, } = createGenericModule(campusConfig);
72
+ // ============================================================================
73
+ // 1.4 ENHANCED CAMPUS HOOK WITH API INTEGRATION
74
+ // ============================================================================
75
+ export const useCampusModule = () => {
76
+ var _a;
77
+ // ============================================================================
78
+ // 1.4.1 STATE & CORE HOOKS
79
+ // ============================================================================
80
+ const context = useCampusContext();
81
+ const { dispatch } = context;
82
+ const state = context.state;
83
+ const t = useTranslations("campus");
84
+ const { theme } = useTheme();
85
+ const workspace = getCachedWorkspaceSync();
86
+ const schoolId = ((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "";
87
+ const listFetchNowRef = useRef(null);
88
+ const debouncedQuery = useDebounce(state.searchQuery, 800);
89
+ // ============================================================================
90
+ // 1.4.2 API PARAMETERS
91
+ // ============================================================================
92
+ const listParams = useMemo(() => (Object.assign(Object.assign({ currentPage: state.currentPage, pageLimit: state.pageLimit, schoolId }, (debouncedQuery ? { searchQuery: debouncedQuery } : {})), (state.filterEnabled !== undefined
93
+ ? { filterEnabled: String(state.filterEnabled) }
94
+ : {}))), [
95
+ state.currentPage,
96
+ state.filterEnabled,
97
+ state.pageLimit,
98
+ debouncedQuery,
99
+ schoolId,
100
+ ]);
101
+ const updateParams = useMemo(() => ({
102
+ address: state.address,
103
+ city: state.city,
104
+ code: state.code,
105
+ country: state.country,
106
+ enabled: state.enabled,
107
+ id: state.id,
108
+ name: state.name,
109
+ phone: state.phone,
110
+ schoolId: state.schoolId || schoolId,
111
+ state: state.state,
112
+ }), [state, schoolId]);
113
+ const byIdParams = useMemo(() => ({ id: state.id }), [state.id]);
114
+ const deleteParams = useMemo(() => ({ id: state.id }), [state.id]);
115
+ // ============================================================================
116
+ // 1.4.3 UTILITIES
117
+ // ============================================================================
118
+ const showToast = useCallback((description, variant) => {
119
+ generateThemeToast({
120
+ description,
121
+ theme: theme,
122
+ variant,
123
+ });
124
+ }, [theme]);
125
+ const resetFormAndCloseDrawer = useCallback(() => {
126
+ dispatch({
127
+ type: CAMPUS_ACTION_TYPES.SET_ERRORS,
128
+ payload: { errors: {} },
129
+ });
130
+ dispatch({
131
+ type: CAMPUS_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
132
+ payload: { disabled: false },
133
+ });
134
+ dispatch({
135
+ type: CAMPUS_ACTION_TYPES.SET_DRAWER,
136
+ payload: { drawer: null },
137
+ });
138
+ }, [dispatch]);
139
+ // ============================================================================
140
+ // 1.4.4 API CALLBACKS
141
+ // ============================================================================
142
+ const listCallback = useCallback(({ data, error }) => {
143
+ var _a, _b;
144
+ if (error) {
145
+ showToast(t("messagesFetchFailed"), TOAST_VARIANT.ERROR);
146
+ return;
147
+ }
148
+ if (data) {
149
+ const response = data;
150
+ dispatch({
151
+ type: CAMPUS_ACTION_TYPES.SET_ITEMS,
152
+ payload: { items: (_a = response.items) !== null && _a !== void 0 ? _a : [], count: (_b = response.count) !== null && _b !== void 0 ? _b : 0 },
153
+ });
154
+ }
155
+ }, [dispatch, showToast, t]);
156
+ const updateCallback = useCallback(({ data, error }) => {
157
+ var _a;
158
+ if (error) {
159
+ showToast(t("messagesUpdateFailed"), TOAST_VARIANT.ERROR);
160
+ return;
161
+ }
162
+ if (data) {
163
+ const isCreated = isCreatedOrUpdated(data);
164
+ invalidateCampusesCache();
165
+ showToast(isCreated ? t("messagesCreateSuccess") : t("messagesSaveSuccess"), TOAST_VARIANT.SUCCESS);
166
+ resetFormAndCloseDrawer();
167
+ (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
168
+ }
169
+ }, [resetFormAndCloseDrawer, showToast, t]);
170
+ const byIdCallback = useCallback(({ data, error }) => {
171
+ if (error) {
172
+ showToast(t("messagesDetailsFetchFailed"), TOAST_VARIANT.ERROR);
173
+ return;
174
+ }
175
+ if (data) {
176
+ dispatch({
177
+ type: CAMPUS_ACTION_TYPES.SET_FORM_DATA,
178
+ payload: { form: Object.assign(Object.assign({}, data), { filterEnabled: undefined }) },
179
+ });
180
+ }
181
+ }, [dispatch, showToast, t]);
182
+ const deleteCallback = useCallback(({ data, error }) => {
183
+ var _a;
184
+ if (error) {
185
+ showToast(t("messagesDeleteFailed"), TOAST_VARIANT.ERROR);
186
+ return;
187
+ }
188
+ if (data) {
189
+ invalidateCampusesCache();
190
+ showToast(t("messagesDeleteSuccess"), TOAST_VARIANT.SUCCESS);
191
+ (_a = listFetchNowRef.current) === null || _a === void 0 ? void 0 : _a.call(listFetchNowRef);
192
+ }
193
+ }, [showToast, t]);
194
+ // ============================================================================
195
+ // 1.4.5 API HOOKS
196
+ // ============================================================================
197
+ const { byIdFetchNow, byIdLoading, deleteFetchNow, deleteLoading, listFetchNow, listLoading, updateFetchNow, updateLoading, } = useModuleEntityV2({
198
+ byIdCallback,
199
+ byIdParams,
200
+ deleteCallback,
201
+ deleteParams,
202
+ listCallback,
203
+ listParams,
204
+ listUrl: CAMPUS_API_ROUTES.UNIT,
205
+ searchQuery: debouncedQuery,
206
+ unitByIdUrl: CAMPUS_API_ROUTES.UNIT,
207
+ unitUrl: CAMPUS_API_ROUTES.UNIT,
208
+ updateCallback,
209
+ updateParams,
210
+ headers: {
211
+ "Content-Type": "application/json",
212
+ "x-api-token": process.env.NEXT_PUBLIC_API_KEY,
213
+ },
214
+ });
215
+ // ============================================================================
216
+ // 1.4.6 HANDLERS
217
+ // ============================================================================
218
+ const handleChange = useCallback((field, value) => {
219
+ let formatted = value;
220
+ if (field === "code" && typeof value === "string") {
221
+ formatted = value.toUpperCase();
222
+ }
223
+ dispatch({
224
+ type: CAMPUS_ACTION_TYPES.SET_ERRORS,
225
+ payload: { errors: {} },
226
+ });
227
+ dispatch({
228
+ type: CAMPUS_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
229
+ payload: { disabled: false },
230
+ });
231
+ dispatch({
232
+ type: CAMPUS_ACTION_TYPES.SET_INPUT_FIELD,
233
+ payload: { key: field, value: formatted !== null && formatted !== void 0 ? formatted : value },
234
+ });
235
+ }, [dispatch]);
236
+ const closeDrawer = useCallback(() => {
237
+ resetFormAndCloseDrawer();
238
+ }, [resetFormAndCloseDrawer]);
239
+ const handleCreate = useCallback(() => {
240
+ dispatch({
241
+ type: CAMPUS_ACTION_TYPES.SET_DRAWER,
242
+ payload: { drawer: CAMPUS_DRAWER.FORM_DRAWER },
243
+ });
244
+ }, [dispatch]);
245
+ const handleView = useCallback((row) => {
246
+ byIdFetchNow === null || byIdFetchNow === void 0 ? void 0 : byIdFetchNow(undefined, { params: { id: row === null || row === void 0 ? void 0 : row.id } });
247
+ dispatch({
248
+ type: CAMPUS_ACTION_TYPES.SET_DRAWER,
249
+ payload: { drawer: CAMPUS_DRAWER.VIEW_DRAWER },
250
+ });
251
+ }, [byIdFetchNow, dispatch]);
252
+ const handleEdit = useCallback((row) => {
253
+ byIdFetchNow === null || byIdFetchNow === void 0 ? void 0 : byIdFetchNow(undefined, { params: { id: row === null || row === void 0 ? void 0 : row.id } });
254
+ dispatch({
255
+ type: CAMPUS_ACTION_TYPES.SET_DRAWER,
256
+ payload: { drawer: CAMPUS_DRAWER.FORM_DRAWER },
257
+ });
258
+ }, [byIdFetchNow, dispatch]);
259
+ const handleDelete = useCallback((row) => {
260
+ if (!confirm(t("messagesDeleteConfirmation")))
261
+ return;
262
+ deleteFetchNow === null || deleteFetchNow === void 0 ? void 0 : deleteFetchNow(undefined, {
263
+ body: JSON.stringify({ id: row === null || row === void 0 ? void 0 : row.id }),
264
+ });
265
+ }, [deleteFetchNow, t]);
266
+ const handleFilters = useCallback(() => {
267
+ dispatch({
268
+ type: CAMPUS_ACTION_TYPES.SET_DRAWER,
269
+ payload: { drawer: CAMPUS_DRAWER.FILTER_DRAWER },
270
+ });
271
+ }, [dispatch]);
272
+ const handleMoreActions = useCallback(() => {
273
+ dispatch({
274
+ type: CAMPUS_ACTION_TYPES.SET_DRAWER,
275
+ payload: { drawer: CAMPUS_DRAWER.MORE_ACTIONS_DRAWER },
276
+ });
277
+ }, [dispatch]);
278
+ const handlePageChange = useCallback((page) => {
279
+ dispatch({
280
+ type: CAMPUS_ACTION_TYPES.SET_CURRENT_PAGE,
281
+ payload: { currentPage: page },
282
+ });
283
+ }, [dispatch]);
284
+ const handlePageLimitChange = useCallback((k, value) => {
285
+ const val = Object.assign({}, value);
286
+ dispatch({
287
+ type: CAMPUS_ACTION_TYPES.SET_PAGE_LIMIT,
288
+ payload: { pageLimit: Number(val.option) },
289
+ });
290
+ dispatch({
291
+ type: CAMPUS_ACTION_TYPES.SET_CURRENT_PAGE,
292
+ payload: { currentPage: 1 },
293
+ });
294
+ }, [dispatch]);
295
+ const handleSearch = useCallback((query) => {
296
+ dispatch({
297
+ type: CAMPUS_ACTION_TYPES.SET_SEARCH_QUERY,
298
+ payload: { searchQuery: query },
299
+ });
300
+ }, [dispatch]);
301
+ const clearSearch = useCallback(() => {
302
+ dispatch({
303
+ type: CAMPUS_ACTION_TYPES.SET_SEARCH_QUERY,
304
+ payload: { searchQuery: "" },
305
+ });
306
+ }, [dispatch]);
307
+ const applyFilters = useCallback(() => {
308
+ dispatch({
309
+ type: CAMPUS_ACTION_TYPES.SET_CURRENT_PAGE,
310
+ payload: { currentPage: 1 },
311
+ });
312
+ listFetchNow();
313
+ closeDrawer();
314
+ }, [dispatch, listFetchNow, closeDrawer]);
315
+ const clearFilters = useCallback(() => {
316
+ dispatch({
317
+ type: CAMPUS_ACTION_TYPES.SET_FILTERS,
318
+ payload: { filters: { filterEnabled: undefined } },
319
+ });
320
+ dispatch({
321
+ type: CAMPUS_ACTION_TYPES.SET_CURRENT_PAGE,
322
+ payload: { currentPage: 1 },
323
+ });
324
+ }, [dispatch]);
325
+ const toggleStatus = useCallback((row) => {
326
+ updateFetchNow(undefined, {
327
+ body: JSON.stringify(Object.assign(Object.assign({}, row), { enabled: !(row === null || row === void 0 ? void 0 : row.enabled) })),
328
+ });
329
+ }, [updateFetchNow]);
330
+ // ============================================================================
331
+ // 1.4.7 SUBMIT
332
+ // ============================================================================
333
+ const handleSubmit = useCallback(() => {
334
+ dispatch({
335
+ type: CAMPUS_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
336
+ payload: { disabled: true },
337
+ });
338
+ validateForm({
339
+ params: updateParams,
340
+ schema: campusFormValidation,
341
+ successCallback: () => {
342
+ updateFetchNow(undefined, {
343
+ body: JSON.stringify(updateParams),
344
+ });
345
+ },
346
+ errorCallback: (errors) => {
347
+ dispatch({
348
+ type: CAMPUS_ACTION_TYPES.SET_ERRORS,
349
+ payload: { errors },
350
+ });
351
+ dispatch({
352
+ type: CAMPUS_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
353
+ payload: { disabled: false },
354
+ });
355
+ showToast(t("messagesFormErrors"), TOAST_VARIANT.ERROR);
356
+ },
357
+ });
358
+ }, [dispatch, updateParams, t, showToast, updateFetchNow]);
359
+ // ============================================================================
360
+ // 1.4.8 HEADER & ROW ACTIONS
361
+ // ============================================================================
362
+ const headerActions = useMemo(() => [
363
+ {
364
+ enabled: false,
365
+ handleOnClick: handleMoreActions,
366
+ label: t("headerActionsMoreActions"),
367
+ order: 0,
368
+ },
369
+ {
370
+ enabled: true,
371
+ handleOnClick: handleFilters,
372
+ label: t("headerActionsFilters"),
373
+ order: 1,
374
+ },
375
+ {
376
+ enabled: true,
377
+ handleOnClick: handleCreate,
378
+ label: t("headerActionsAdd"),
379
+ order: 2,
380
+ },
381
+ ], [handleCreate, handleFilters, handleMoreActions, t]);
382
+ const rowActions = useMemo(() => [
383
+ {
384
+ enabled: true,
385
+ handleOnClick: handleView,
386
+ label: t("rowActionsView"),
387
+ order: 1,
388
+ },
389
+ {
390
+ enabled: (row) => (row === null || row === void 0 ? void 0 : row.enabled) === true,
391
+ handleOnClick: handleEdit,
392
+ label: t("rowActionsEdit"),
393
+ order: 2,
394
+ },
395
+ {
396
+ enabled: (row) => (row === null || row === void 0 ? void 0 : row.enabled) === false,
397
+ handleOnClick: handleDelete,
398
+ label: t("rowActionsDelete"),
399
+ order: 3,
400
+ variant: "destructive",
401
+ },
402
+ {
403
+ enabled: false,
404
+ handleOnClick: toggleStatus,
405
+ label: t("rowActionsToggleStatus"),
406
+ order: 4,
407
+ },
408
+ ], [handleDelete, handleEdit, handleView, t, toggleStatus]);
409
+ // ============================================================================
410
+ // 1.4.9 EFFECTS
411
+ // ============================================================================
412
+ useEffect(() => {
413
+ if (!schoolId)
414
+ return;
415
+ (async () => {
416
+ try {
417
+ const { count, items } = await getCachedCampuses({
418
+ params: listParams,
419
+ });
420
+ dispatch({
421
+ type: CAMPUS_ACTION_TYPES.SET_ITEMS,
422
+ payload: { items: items || [], count: count || 0 },
423
+ });
424
+ }
425
+ catch (_a) {
426
+ showToast(t("messagesFetchFailed"), TOAST_VARIANT.ERROR);
427
+ }
428
+ })();
429
+ }, [dispatch, listParams, schoolId, showToast, t]);
430
+ useEffect(() => {
431
+ listFetchNowRef.current = listFetchNow;
432
+ });
433
+ // ============================================================================
434
+ // 1.4.10 RETURN
435
+ // ============================================================================
436
+ return Object.assign(Object.assign({}, context), { applyFilters,
437
+ byIdLoading,
438
+ clearFilters,
439
+ clearSearch,
440
+ closeDrawer,
441
+ deleteLoading,
442
+ handleChange,
443
+ handleCreate,
444
+ handleDelete,
445
+ handleEdit,
446
+ handleFilters,
447
+ handleMoreActions,
448
+ handlePageChange,
449
+ handlePageLimitChange,
450
+ handleSearch,
451
+ handleSubmit,
452
+ handleView,
453
+ headerActions,
454
+ listFetchNow,
455
+ listLoading,
456
+ rowActions,
457
+ toggleStatus,
458
+ updateLoading });
459
+ };
@@ -0,0 +1 @@
1
+ export declare const CampusFilter: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * Campus Filter Component
5
+ *
6
+ * Renders filter controls for the campus list view.
7
+ */
8
+ import { EnhancedRadio } from "@appcorp/shadcn/components/enhanced-radio";
9
+ import { useCampusModule } from "./context";
10
+ import { useTranslations } from "next-intl";
11
+ export const CampusFilter = () => {
12
+ const { state, handleChange } = useCampusModule();
13
+ const { filterEnabled } = state;
14
+ const t = useTranslations("campus");
15
+ const filterEnabledValue = filterEnabled === undefined
16
+ ? "undefined"
17
+ : filterEnabled
18
+ ? "true"
19
+ : "false";
20
+ return (_jsx("div", { className: "space-y-4", children: _jsx("div", { className: "grid grid-cols-1 gap-4", children: _jsx(EnhancedRadio, { label: t("enabled"), name: "filterEnabled", value: filterEnabledValue, options: [
21
+ { label: t("all"), value: "undefined" },
22
+ { label: t("enabled"), value: "true" },
23
+ { label: t("disabled"), value: "false" },
24
+ ], onValueChange: (next) => {
25
+ const parsed = next === "true" ? true : next === "false" ? false : undefined;
26
+ handleChange("filterEnabled", parsed);
27
+ } }) }) }));
28
+ };
@@ -0,0 +1 @@
1
+ export declare const CampusForm: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ /**
4
+ * Campus Form Component
5
+ *
6
+ * Renders the create/edit form for a campus record.
7
+ */
8
+ import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
9
+ import { EnhancedCheckbox } from "@appcorp/shadcn/components/enhanced-checkbox";
10
+ import { useCampusModule } from "./context";
11
+ import { useTranslations } from "next-intl";
12
+ export const CampusForm = () => {
13
+ const { state, handleChange } = useCampusModule();
14
+ const { address, city, code, country, enabled, errors, name, phone, state: campusState, } = state;
15
+ const t = useTranslations("campus");
16
+ return (_jsx("div", { className: "space-y-4", children: _jsxs("div", { className: "grid grid-cols-1 gap-4", children: [_jsx(EnhancedInput, { error: errors.name, id: "name", info: t("campusNameInfo"), label: t("campusName"), onChange: (e) => handleChange("name", e.target.value), placeholder: t("campusNamePlaceholder"), required: true, value: name }), _jsx(EnhancedInput, { error: errors.code, id: "code", info: t("campusCodeInfo"), label: t("campusCode"), onChange: (e) => handleChange("code", e.target.value), placeholder: t("campusCodePlaceholder"), required: true, value: code }), _jsx(EnhancedInput, { error: errors.address, id: "address", label: t("address"), onChange: (e) => handleChange("address", e.target.value), placeholder: t("addressPlaceholder"), value: address || "" }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(EnhancedInput, { error: errors.city, id: "city", label: t("city"), onChange: (e) => handleChange("city", e.target.value), placeholder: t("cityPlaceholder"), value: city || "" }), _jsx(EnhancedInput, { error: errors.state, id: "state", label: t("state"), onChange: (e) => handleChange("state", e.target.value), placeholder: t("statePlaceholder"), value: campusState || "" })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsx(EnhancedInput, { error: errors.country, id: "country", label: t("country"), onChange: (e) => handleChange("country", e.target.value), placeholder: t("countryPlaceholder"), value: country || "" }), _jsx(EnhancedInput, { error: errors.phone, id: "phone", label: t("phone"), onChange: (e) => handleChange("phone", e.target.value), placeholder: t("phonePlaceholder"), value: phone || "" })] }), _jsx(EnhancedCheckbox, { label: t("activeCampus"), defaultChecked: enabled, onCheckedChange: (checked) => handleChange("enabled", checked) })] }) }));
17
+ };
@@ -0,0 +1 @@
1
+ export declare const CampusMoreActions: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * Campus More Actions Component
5
+ *
6
+ * Provides bulk CSV import/export actions for the campus module.
7
+ */
8
+ import { API_METHODS, downloadFromUrl } from "@react-pakistan/util-functions";
9
+ import { getCachedWorkspaceSync } from "../workspace/cache";
10
+ import converter from "json-2-csv";
11
+ import { Timeline } from "../../components/timeline";
12
+ import { useTranslations } from "next-intl";
13
+ export const CampusMoreActions = () => {
14
+ const t = useTranslations("campus");
15
+ const workspace = getCachedWorkspaceSync();
16
+ const handleGetAllRecords = async (schoolId) => {
17
+ const response = await fetch(`/api/v1/campus?pageLimit=1000&currentPage=1&schoolId=${schoolId}`, { method: API_METHODS.GET });
18
+ const result = await response.json();
19
+ const csv = await converter.json2csv(result.items || [], {});
20
+ const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
21
+ await downloadFromUrl(blob, "campus.csv");
22
+ };
23
+ const update = [
24
+ {
25
+ id: "1",
26
+ title: t("downloadPopulatedCsvTemplate"),
27
+ handleOnClick: async () => {
28
+ var _a;
29
+ await handleGetAllRecords(((_a = workspace === null || workspace === void 0 ? void 0 : workspace.school) === null || _a === void 0 ? void 0 : _a.id) || "");
30
+ },
31
+ },
32
+ { id: "2", title: t("updateYourDataInTheCsv") },
33
+ {
34
+ id: "3",
35
+ title: t("uploadTheCompletedCsvToTheSystem"),
36
+ handleOnClick: () => console.log("clicked"),
37
+ },
38
+ ];
39
+ return (_jsx("div", { className: "space-y-4", children: _jsx(Timeline, { events: update, heading: t("bulkUpdate") }) }));
40
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Campus Page Component
3
+ *
4
+ * Uses the generic component factory pattern with campus-specific configuration.
5
+ * Receives all UI label strings as pre-translated props from the caller,
6
+ * so this component is translation-agnostic.
7
+ *
8
+ * Exported utilities:
9
+ * - `CampusPage` — root component that wraps with CampusProvider
10
+ */
11
+ import { FC } from "react";
12
+ import { USER_ROLE } from "../../type";
13
+ interface Props {
14
+ cancelLabel: string;
15
+ drawerTitle: string;
16
+ labelActions: string;
17
+ labelCity: string;
18
+ labelCode: string;
19
+ labelEnabled: string;
20
+ labelId: string;
21
+ labelName: string;
22
+ saveLabel: string;
23
+ searchPlaceholder: string;
24
+ tableDescription: string;
25
+ tableTitle: string;
26
+ userRole: USER_ROLE;
27
+ }
28
+ export declare const CampusPage: FC<Props>;
29
+ export {};