@appcorp/fusion-storybook 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +147 -0
- package/base-modules/admission/cache.d.ts +14 -0
- package/base-modules/admission/cache.js +31 -0
- package/base-modules/admission/constants.d.ts +32 -0
- package/base-modules/admission/constants.js +37 -0
- package/base-modules/admission/context.d.ts +369 -0
- package/base-modules/admission/context.js +755 -0
- package/base-modules/admission/filter.d.ts +1 -0
- package/base-modules/admission/filter.js +31 -0
- package/base-modules/admission/form.d.ts +1 -0
- package/base-modules/admission/form.js +86 -0
- package/base-modules/admission/more-actions.d.ts +1 -0
- package/base-modules/admission/more-actions.js +5 -0
- package/base-modules/admission/page.d.ts +16 -0
- package/base-modules/admission/page.js +128 -0
- package/base-modules/admission/validate.d.ts +38 -0
- package/base-modules/admission/validate.js +70 -0
- package/base-modules/admission/view.d.ts +1 -0
- package/base-modules/admission/view.js +40 -0
- package/base-modules/discount-code/cache.d.ts +27 -0
- package/base-modules/discount-code/cache.js +46 -0
- package/base-modules/discount-code/constants.d.ts +19 -0
- package/base-modules/discount-code/constants.js +26 -0
- package/base-modules/discount-code/context.d.ts +154 -0
- package/base-modules/discount-code/context.js +416 -0
- package/base-modules/discount-code/filter.d.ts +9 -0
- package/base-modules/discount-code/filter.js +14 -0
- package/base-modules/discount-code/form.d.ts +1 -0
- package/base-modules/discount-code/form.js +44 -0
- package/base-modules/discount-code/more-actions.d.ts +9 -0
- package/base-modules/discount-code/more-actions.js +13 -0
- package/base-modules/discount-code/page.d.ts +16 -0
- package/base-modules/discount-code/page.js +120 -0
- package/base-modules/discount-code/validate.d.ts +19 -0
- package/base-modules/discount-code/validate.js +38 -0
- package/base-modules/discount-code/view.d.ts +1 -0
- package/base-modules/discount-code/view.js +26 -0
- package/base-modules/family/cache.d.ts +14 -0
- package/base-modules/family/cache.js +31 -0
- package/base-modules/family/constants.d.ts +22 -0
- package/base-modules/family/constants.js +26 -0
- package/base-modules/family/context.d.ts +173 -0
- package/base-modules/family/context.js +441 -0
- package/base-modules/family/filter.d.ts +1 -0
- package/base-modules/family/filter.js +28 -0
- package/base-modules/family/form.d.ts +1 -0
- package/base-modules/family/form.js +12 -0
- package/base-modules/family/more-actions.d.ts +1 -0
- package/base-modules/family/more-actions.js +5 -0
- package/base-modules/family/page.d.ts +16 -0
- package/base-modules/family/page.js +120 -0
- package/base-modules/family/validate.d.ts +15 -0
- package/base-modules/family/validate.js +18 -0
- package/base-modules/family/view.d.ts +1 -0
- package/base-modules/family/view.js +18 -0
- package/base-modules/family-member/cache.d.ts +14 -0
- package/base-modules/family-member/cache.js +31 -0
- package/base-modules/family-member/constants.d.ts +22 -0
- package/base-modules/family-member/constants.js +26 -0
- package/base-modules/family-member/context.d.ts +215 -0
- package/base-modules/family-member/context.js +486 -0
- package/base-modules/family-member/filter.d.ts +1 -0
- package/base-modules/family-member/filter.js +28 -0
- package/base-modules/family-member/form.d.ts +1 -0
- package/base-modules/family-member/form.js +17 -0
- package/base-modules/family-member/more-actions.d.ts +1 -0
- package/base-modules/family-member/more-actions.js +5 -0
- package/base-modules/family-member/page.d.ts +16 -0
- package/base-modules/family-member/page.js +122 -0
- package/base-modules/family-member/validate.d.ts +24 -0
- package/base-modules/family-member/validate.js +27 -0
- package/base-modules/family-member/view.d.ts +1 -0
- package/base-modules/family-member/view.js +40 -0
- package/base-modules/student-profile/cache.d.ts +14 -0
- package/base-modules/student-profile/cache.js +31 -0
- package/base-modules/student-profile/constants.d.ts +105 -0
- package/base-modules/student-profile/constants.js +132 -0
- package/base-modules/student-profile/context.d.ts +290 -0
- package/base-modules/student-profile/context.js +583 -0
- package/base-modules/student-profile/filter.d.ts +1 -0
- package/base-modules/student-profile/filter.js +26 -0
- package/base-modules/student-profile/form.d.ts +1 -0
- package/base-modules/student-profile/form.js +19 -0
- package/base-modules/student-profile/more-actions.d.ts +1 -0
- package/base-modules/student-profile/more-actions.js +5 -0
- package/base-modules/student-profile/page.d.ts +9 -0
- package/base-modules/student-profile/page.js +86 -0
- package/base-modules/student-profile/validate.d.ts +23 -0
- package/base-modules/student-profile/validate.js +34 -0
- package/base-modules/student-profile/view.d.ts +1 -0
- package/base-modules/student-profile/view.js +29 -0
- package/base-modules/workspace/cache.d.ts +9 -0
- package/base-modules/workspace/cache.js +28 -0
- package/base-modules/workspace/constants.d.ts +10 -0
- package/base-modules/workspace/constants.js +18 -0
- package/base-modules/workspace/context.d.ts +187 -0
- package/base-modules/workspace/context.js +293 -0
- package/base-modules/workspace/drawer.d.ts +1 -0
- package/base-modules/workspace/drawer.js +24 -0
- package/base-modules/workspace/filter.d.ts +1 -0
- package/base-modules/workspace/filter.js +13 -0
- package/base-modules/workspace/form.d.ts +1 -0
- package/base-modules/workspace/form.js +40 -0
- package/base-modules/workspace/more-actions.d.ts +1 -0
- package/base-modules/workspace/more-actions.js +13 -0
- package/base-modules/workspace/page.d.ts +1 -0
- package/base-modules/workspace/page.js +31 -0
- package/base-modules/workspace/validate.d.ts +9 -0
- package/base-modules/workspace/validate.js +8 -0
- package/base-modules/workspace/view.d.ts +1 -0
- package/base-modules/workspace/view.js +52 -0
- package/components/rbac-no-access.d.ts +6 -0
- package/components/rbac-no-access.js +4 -0
- package/constants.d.ts +81 -0
- package/constants.js +81 -0
- package/lib/utils.d.ts +2 -0
- package/lib/utils.js +5 -0
- package/package.json +104 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/type.d.ts +1141 -0
- package/type.js +427 -0
- package/utils/admission-pdf.d.ts +78 -0
- package/utils/admission-pdf.js +73 -0
- package/utils/clear-cache.d.ts +1 -0
- package/utils/clear-cache.js +8 -0
- package/utils/format-value.d.ts +1 -0
- package/utils/format-value.js +1 -0
- package/utils/pdf-generator.d.ts +41 -0
- package/utils/pdf-generator.js +107 -0
- package/utils/resolve-rbac-permissions.d.ts +11 -0
- package/utils/resolve-rbac-permissions.js +251 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
/**
|
|
3
|
+
* Workspace 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 optimistic UI helpers.
|
|
9
|
+
*
|
|
10
|
+
* Key responsibilities:
|
|
11
|
+
* - expose `useWorkspaceModule()` 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
|
+
* - `WorkspaceStateContextProvider` — provider component used by the page
|
|
17
|
+
* - `useWorkspaceModule()` — hook that returns handlers and state
|
|
18
|
+
*/
|
|
19
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
20
|
+
import { validateForm } from "@react-pakistan/util-functions";
|
|
21
|
+
import { useModuleEntityV2, } from "@react-pakistan/util-functions/hooks/use-module-entity-v2";
|
|
22
|
+
import { createGenericModule } from "@react-pakistan/util-functions/factory/generic-module-factory";
|
|
23
|
+
import { DRAWER_TYPES } from "@react-pakistan/util-functions/factory/generic-component-factory";
|
|
24
|
+
import { WORKSPACE_API_ROUTES } from "./constants";
|
|
25
|
+
import { getCachedWorkspaceSync, invalidateWorkspaceCache } from "./cache";
|
|
26
|
+
import { workspaceFormValidation } from "./validate";
|
|
27
|
+
import { generateThemeToast, TOAST_VARIANT, } from "@appcorp/shadcn/lib/toast-utils";
|
|
28
|
+
import { useTranslations } from "next-intl";
|
|
29
|
+
import { AUTH_API_ROUTES } from "@/constants";
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// CONFIGURATION
|
|
32
|
+
// ============================================================================
|
|
33
|
+
const workspaceConfig = {
|
|
34
|
+
name: "Workspace",
|
|
35
|
+
displayName: "Workspace",
|
|
36
|
+
initialState: {
|
|
37
|
+
// Form State
|
|
38
|
+
agreedCurrency: "",
|
|
39
|
+
agreedPrice: 0,
|
|
40
|
+
billingDate: null,
|
|
41
|
+
billingInterval: "",
|
|
42
|
+
classesCount: 0,
|
|
43
|
+
coursesCount: 0,
|
|
44
|
+
description: "",
|
|
45
|
+
dueDateLength: 0,
|
|
46
|
+
enabled: true,
|
|
47
|
+
familiesCount: 0,
|
|
48
|
+
id: "",
|
|
49
|
+
logo: "",
|
|
50
|
+
name: "",
|
|
51
|
+
planEndDate: null,
|
|
52
|
+
planId: "",
|
|
53
|
+
planStartDate: null,
|
|
54
|
+
secrets: {},
|
|
55
|
+
staffAccountsCount: 0,
|
|
56
|
+
storageUsedMB: 0,
|
|
57
|
+
studentsCount: 0,
|
|
58
|
+
subdomain: "",
|
|
59
|
+
teachersCount: 0,
|
|
60
|
+
// UI State
|
|
61
|
+
disableSaveButton: false,
|
|
62
|
+
drawer: null,
|
|
63
|
+
errors: {},
|
|
64
|
+
},
|
|
65
|
+
drawerTypes: DRAWER_TYPES,
|
|
66
|
+
// Custom actions
|
|
67
|
+
customActions: {
|
|
68
|
+
SET_WORKSPACE: "SET_WORKSPACE",
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// CREATE WORKSPACE MODULE
|
|
73
|
+
// ============================================================================
|
|
74
|
+
export const { actionTypes: WORKSPACE_ACTION_TYPES, config: workspaceModuleConfig, initialState: initialWorkspaceState, Provider: WorkspaceProvider, reducer: workspaceReducer, useContext: useWorkspaceContext, } = createGenericModule(workspaceConfig);
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// DRAWER TYPES
|
|
77
|
+
// ============================================================================
|
|
78
|
+
export const WORKSPACE_DRAWER = {
|
|
79
|
+
FORM_DRAWER: DRAWER_TYPES.FORM_DRAWER,
|
|
80
|
+
MORE_ACTIONS_DRAWER: "MORE_ACTIONS_DRAWER",
|
|
81
|
+
VIEW_DRAWER: DRAWER_TYPES.VIEW_DRAWER,
|
|
82
|
+
};
|
|
83
|
+
// ============================================================================
|
|
84
|
+
// ENHANCED WORKSPACE HOOK WITH API INTEGRATION
|
|
85
|
+
// ============================================================================
|
|
86
|
+
export const useWorkspaceModule = () => {
|
|
87
|
+
const context = useWorkspaceContext();
|
|
88
|
+
const [plans, setPlans] = useState([]);
|
|
89
|
+
const workspace = getCachedWorkspaceSync();
|
|
90
|
+
const t = useTranslations("workspace");
|
|
91
|
+
// ============================================================================
|
|
92
|
+
// UTILITIES
|
|
93
|
+
// ============================================================================
|
|
94
|
+
const showToast = useCallback((message, variant) => {
|
|
95
|
+
generateThemeToast({ description: message, variant });
|
|
96
|
+
}, []);
|
|
97
|
+
const resetFormAndCloseDrawer = useCallback(() => {
|
|
98
|
+
context.dispatch({
|
|
99
|
+
type: WORKSPACE_ACTION_TYPES.SET_ERRORS,
|
|
100
|
+
payload: { errors: {} },
|
|
101
|
+
});
|
|
102
|
+
context.dispatch({
|
|
103
|
+
type: WORKSPACE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
|
|
104
|
+
payload: { disabled: false },
|
|
105
|
+
});
|
|
106
|
+
context.dispatch({
|
|
107
|
+
type: WORKSPACE_ACTION_TYPES.SET_DRAWER,
|
|
108
|
+
payload: { drawer: null },
|
|
109
|
+
});
|
|
110
|
+
}, [context.dispatch]);
|
|
111
|
+
// ============================================================================
|
|
112
|
+
// API PARAMETERS
|
|
113
|
+
// ============================================================================
|
|
114
|
+
const apiParams = useMemo(() => ({
|
|
115
|
+
update: {
|
|
116
|
+
agreedCurrency: context.state.agreedCurrency,
|
|
117
|
+
agreedPrice: context.state.agreedPrice,
|
|
118
|
+
billingDate: context.state.billingDate,
|
|
119
|
+
billingInterval: context.state.billingInterval,
|
|
120
|
+
classesCount: context.state.classesCount,
|
|
121
|
+
coursesCount: context.state.coursesCount,
|
|
122
|
+
description: context.state.description,
|
|
123
|
+
dueDateLength: context.state.dueDateLength,
|
|
124
|
+
enabled: context.state.enabled,
|
|
125
|
+
familiesCount: context.state.familiesCount,
|
|
126
|
+
id: context.state.id,
|
|
127
|
+
logo: context.state.logo,
|
|
128
|
+
name: context.state.name,
|
|
129
|
+
planEndDate: context.state.planEndDate,
|
|
130
|
+
planId: context.state.planId,
|
|
131
|
+
planStartDate: context.state.planStartDate,
|
|
132
|
+
secrets: context.state.secrets,
|
|
133
|
+
staffAccountsCount: context.state.staffAccountsCount,
|
|
134
|
+
storageUsedMB: context.state.storageUsedMB,
|
|
135
|
+
studentsCount: context.state.studentsCount,
|
|
136
|
+
subdomain: context.state.subdomain,
|
|
137
|
+
teachersCount: context.state.teachersCount,
|
|
138
|
+
},
|
|
139
|
+
}), [
|
|
140
|
+
context.state.agreedCurrency,
|
|
141
|
+
context.state.agreedPrice,
|
|
142
|
+
context.state.billingDate,
|
|
143
|
+
context.state.billingInterval,
|
|
144
|
+
context.state.classesCount,
|
|
145
|
+
context.state.coursesCount,
|
|
146
|
+
context.state.description,
|
|
147
|
+
context.state.dueDateLength,
|
|
148
|
+
context.state.enabled,
|
|
149
|
+
context.state.familiesCount,
|
|
150
|
+
context.state.id,
|
|
151
|
+
context.state.logo,
|
|
152
|
+
context.state.name,
|
|
153
|
+
context.state.planEndDate,
|
|
154
|
+
context.state.planId,
|
|
155
|
+
context.state.planStartDate,
|
|
156
|
+
context.state.secrets,
|
|
157
|
+
context.state.staffAccountsCount,
|
|
158
|
+
context.state.storageUsedMB,
|
|
159
|
+
context.state.studentsCount,
|
|
160
|
+
context.state.subdomain,
|
|
161
|
+
context.state.teachersCount,
|
|
162
|
+
]);
|
|
163
|
+
// ============================================================================
|
|
164
|
+
// API CALLBACKS
|
|
165
|
+
// ============================================================================
|
|
166
|
+
const listCallback = useCallback(() => { }, []);
|
|
167
|
+
const updateCallback = ({ data, error }) => {
|
|
168
|
+
if (error) {
|
|
169
|
+
showToast(t("messagesUpdateFailed"), TOAST_VARIANT.ERROR);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (data) {
|
|
173
|
+
showToast(t("messagesSaveSuccess"), TOAST_VARIANT.SUCCESS);
|
|
174
|
+
invalidateWorkspaceCache();
|
|
175
|
+
resetFormAndCloseDrawer();
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
const byIdCallback = useCallback(() => { }, []);
|
|
179
|
+
const deleteCallback = useCallback(() => { }, []);
|
|
180
|
+
// ============================================================================
|
|
181
|
+
// HANDLERS
|
|
182
|
+
// ============================================================================
|
|
183
|
+
const handleChange = useCallback((field, value) => {
|
|
184
|
+
context.dispatch({
|
|
185
|
+
type: WORKSPACE_ACTION_TYPES.SET_INPUT_FIELD,
|
|
186
|
+
payload: { key: field, value },
|
|
187
|
+
});
|
|
188
|
+
}, [context.dispatch]);
|
|
189
|
+
const handleCloseDrawer = useCallback(() => {
|
|
190
|
+
resetFormAndCloseDrawer();
|
|
191
|
+
}, [resetFormAndCloseDrawer]);
|
|
192
|
+
const handleEdit = useCallback(() => {
|
|
193
|
+
context.dispatch({
|
|
194
|
+
type: WORKSPACE_ACTION_TYPES.SET_DRAWER,
|
|
195
|
+
payload: { drawer: WORKSPACE_DRAWER.FORM_DRAWER },
|
|
196
|
+
});
|
|
197
|
+
}, [context.dispatch]);
|
|
198
|
+
const handleView = useCallback(() => {
|
|
199
|
+
context.dispatch({
|
|
200
|
+
type: WORKSPACE_ACTION_TYPES.SET_DRAWER,
|
|
201
|
+
payload: { drawer: WORKSPACE_DRAWER.VIEW_DRAWER },
|
|
202
|
+
});
|
|
203
|
+
}, [context.dispatch]);
|
|
204
|
+
// ============================================================================
|
|
205
|
+
// NETWORK ACTIONS
|
|
206
|
+
// ============================================================================
|
|
207
|
+
const handleSubmit = useCallback(() => {
|
|
208
|
+
context.dispatch({
|
|
209
|
+
type: WORKSPACE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
|
|
210
|
+
payload: { disabled: true },
|
|
211
|
+
});
|
|
212
|
+
validateForm({
|
|
213
|
+
params: apiParams.update,
|
|
214
|
+
schema: workspaceFormValidation,
|
|
215
|
+
successCallback: () => {
|
|
216
|
+
updateFetchNow(undefined, {
|
|
217
|
+
body: JSON.stringify(apiParams.update),
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
errorCallback: (errors) => {
|
|
221
|
+
context.dispatch({
|
|
222
|
+
type: WORKSPACE_ACTION_TYPES.SET_ERRORS,
|
|
223
|
+
payload: { errors },
|
|
224
|
+
});
|
|
225
|
+
context.dispatch({
|
|
226
|
+
type: WORKSPACE_ACTION_TYPES.SET_DISABLE_SAVE_BUTTON,
|
|
227
|
+
payload: { disabled: false },
|
|
228
|
+
});
|
|
229
|
+
showToast(t("messagesFormErrors"), TOAST_VARIANT.ERROR);
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
}, [context.dispatch, apiParams.update, t, showToast]);
|
|
233
|
+
// ============================================================================
|
|
234
|
+
// API HOOKS
|
|
235
|
+
// ============================================================================
|
|
236
|
+
const { updateFetchNow, updateLoading } = useModuleEntityV2({
|
|
237
|
+
updateCallback,
|
|
238
|
+
updateParams: apiParams.update,
|
|
239
|
+
listCallback,
|
|
240
|
+
byIdCallback,
|
|
241
|
+
deleteCallback,
|
|
242
|
+
listParams: {},
|
|
243
|
+
byIdParams: {},
|
|
244
|
+
deleteParams: {},
|
|
245
|
+
searchQuery: "",
|
|
246
|
+
listUrl: WORKSPACE_API_ROUTES.UNIT,
|
|
247
|
+
unitUrl: WORKSPACE_API_ROUTES.UNIT,
|
|
248
|
+
unitByIdUrl: WORKSPACE_API_ROUTES.UNIT,
|
|
249
|
+
});
|
|
250
|
+
// ============================================================================
|
|
251
|
+
// EFFECTS
|
|
252
|
+
// ============================================================================
|
|
253
|
+
useEffect(() => {
|
|
254
|
+
if (workspace) {
|
|
255
|
+
context.dispatch({
|
|
256
|
+
type: WORKSPACE_ACTION_TYPES.SET_FORM_DATA,
|
|
257
|
+
payload: { form: workspace },
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}, []);
|
|
261
|
+
// Fetch plans for the combobox
|
|
262
|
+
useEffect(() => {
|
|
263
|
+
const fetchPlans = async () => {
|
|
264
|
+
try {
|
|
265
|
+
const response = await fetch(AUTH_API_ROUTES.PLAN, {
|
|
266
|
+
method: "GET",
|
|
267
|
+
headers: {
|
|
268
|
+
"Content-Type": "application/json",
|
|
269
|
+
"x-api-token": process.env.NEXT_PUBLIC_API_KEY,
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
if (response.ok) {
|
|
273
|
+
const data = await response.json();
|
|
274
|
+
setPlans(data.items || []);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
catch (_a) {
|
|
278
|
+
showToast(t("messagesFetchFailed"), TOAST_VARIANT.ERROR);
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
fetchPlans();
|
|
282
|
+
}, []);
|
|
283
|
+
// ============================================================================
|
|
284
|
+
// RETURN
|
|
285
|
+
// ============================================================================
|
|
286
|
+
return Object.assign(Object.assign({}, context), { plans,
|
|
287
|
+
handleChange,
|
|
288
|
+
handleCloseDrawer,
|
|
289
|
+
handleEdit,
|
|
290
|
+
handleSubmit,
|
|
291
|
+
handleView,
|
|
292
|
+
updateLoading });
|
|
293
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WorkspaceDrawer: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Workspace Drawer Component
|
|
5
|
+
*
|
|
6
|
+
* Renders form and view drawers for the workspace single-entity module.
|
|
7
|
+
*/
|
|
8
|
+
import { EnhancedDrawerHeader } from "@appcorp/shadcn/components/enhanced-drawer-header";
|
|
9
|
+
import { EnhancedDrawerFooter, DRAWER_FOOTER_COMPONENT_TYPE, } from "@appcorp/shadcn/components/enhanced-drawer-footer";
|
|
10
|
+
import { DrawerGeneric } from "@appcorp/shadcn/components/drawer-generic";
|
|
11
|
+
import { useWorkspaceModule, WORKSPACE_DRAWER } from "./context";
|
|
12
|
+
import { WorkspaceForm } from "./form";
|
|
13
|
+
import { WorkspaceView } from "./view";
|
|
14
|
+
import { WorkspaceMoreActions } from "./more-actions";
|
|
15
|
+
export const WorkspaceDrawer = () => {
|
|
16
|
+
const { handleCloseDrawer, handleSubmit, state, updateLoading } = useWorkspaceModule();
|
|
17
|
+
const { disableSaveButton, drawer, errors } = state;
|
|
18
|
+
const isFormDrawer = drawer === WORKSPACE_DRAWER.FORM_DRAWER;
|
|
19
|
+
const isViewDrawer = drawer === WORKSPACE_DRAWER.VIEW_DRAWER;
|
|
20
|
+
const isMoreActionsDrawer = drawer === WORKSPACE_DRAWER.MORE_ACTIONS_DRAWER;
|
|
21
|
+
const applyFilters = () => { };
|
|
22
|
+
const clearFilters = () => { };
|
|
23
|
+
return (_jsx(DrawerGeneric, { filterDrawer: null, filterDrawerHeader: null, filterDrawerFooter: null, formDrawer: isFormDrawer ? _jsx(WorkspaceForm, {}) : null, formDrawerHeader: isFormDrawer ? (_jsx(EnhancedDrawerHeader, { title: "Edit Workspace", description: "Update your workspace settings" })) : null, formDrawerFooter: isFormDrawer ? (_jsx(EnhancedDrawerFooter, { applyFilters: applyFilters, clearFilters: clearFilters, closeDrawer: handleCloseDrawer, disableSaveButton: disableSaveButton, drawerType: DRAWER_FOOTER_COMPONENT_TYPE.FORM_DRAWER, errors: errors, handleSubmit: handleSubmit, updateLoading: updateLoading })) : null, viewDrawer: isViewDrawer ? _jsx(WorkspaceView, {}) : null, viewDrawerHeader: isViewDrawer ? (_jsx(EnhancedDrawerHeader, { title: "Workspace Details", description: "View your workspace information" })) : null, viewDrawerFooter: isViewDrawer ? (_jsx(EnhancedDrawerFooter, { applyFilters: applyFilters, clearFilters: clearFilters, closeDrawer: handleCloseDrawer, disableSaveButton: disableSaveButton, drawerType: DRAWER_FOOTER_COMPONENT_TYPE.VIEW_DRAWER, errors: errors, handleSubmit: handleSubmit, updateLoading: updateLoading })) : null, moreActionsDrawer: isMoreActionsDrawer ? _jsx(WorkspaceMoreActions, {}) : null, moreActionsDrawerHeader: isMoreActionsDrawer ? (_jsx(EnhancedDrawerHeader, { title: "More Actions", description: "Additional workspace actions" })) : null, moreActionsDrawerFooter: isMoreActionsDrawer ? (_jsx(EnhancedDrawerFooter, { applyFilters: applyFilters, clearFilters: clearFilters, closeDrawer: handleCloseDrawer, disableSaveButton: disableSaveButton, drawerType: DRAWER_FOOTER_COMPONENT_TYPE.MORE_ACTIONS_DRAWER, errors: errors, handleSubmit: handleSubmit, updateLoading: updateLoading })) : null, onOpenChange: (open) => !open && handleCloseDrawer(), open: isFormDrawer || isViewDrawer || isMoreActionsDrawer }));
|
|
24
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WorkspaceFilter: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Workspace Filter
|
|
5
|
+
*
|
|
6
|
+
* Placeholder component for workspace filters.
|
|
7
|
+
* Currently no filters are available for workspaces.
|
|
8
|
+
*/
|
|
9
|
+
import { useTranslations } from "next-intl";
|
|
10
|
+
export const WorkspaceFilter = () => {
|
|
11
|
+
const t = useTranslations("workspace");
|
|
12
|
+
return (_jsx("div", { className: "p-6 text-center text-muted-foreground", children: _jsx("p", { children: t("filter") }) }));
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WorkspaceForm: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Workspace Form
|
|
5
|
+
*
|
|
6
|
+
* Form component for creating/editing workspace information.
|
|
7
|
+
*/
|
|
8
|
+
import { useState } from "react";
|
|
9
|
+
import { useWorkspaceModule } from "./context";
|
|
10
|
+
import { useTranslations } from "next-intl";
|
|
11
|
+
import { EnhancedInput } from "@appcorp/shadcn/components/enhanced-input";
|
|
12
|
+
import { EnhancedTextarea } from "@appcorp/shadcn/components/enhanced-textarea";
|
|
13
|
+
import { EnhancedCombobox } from "@appcorp/shadcn/components/enhanced-combobox";
|
|
14
|
+
import { Shield, Eye, EyeOff } from "lucide-react";
|
|
15
|
+
import { secretKeys } from "./constants";
|
|
16
|
+
const SecretsEditor = ({ secrets, errors, onChange }) => {
|
|
17
|
+
const [visibleMap, setVisibleMap] = useState(() => Object.fromEntries(secretKeys.map((k) => [k, false])));
|
|
18
|
+
const toggle = (key) => setVisibleMap((s) => (Object.assign(Object.assign({}, s), { [key]: !s[key] })));
|
|
19
|
+
return (_jsx("div", { className: "space-y-3", children: secretKeys.map((key) => {
|
|
20
|
+
const val = secrets[key] || "";
|
|
21
|
+
return (_jsxs("div", { className: "relative", children: [_jsx(EnhancedInput, { id: `secrets.${key}`, label: key, value: String(val), onChange: (e) => onChange(key, e.target.value), error: errors[`secrets.${key}`], placeholder: "Enter value (visible only to admins)", type: visibleMap[key] ? "text" : "password" }), _jsx("button", { type: "button", "aria-label": visibleMap[key] ? `Hide ${key}` : `Show ${key}`, onClick: () => toggle(key), className: "absolute inset-y-0 top-7 right-3 flex items-center justify-center p-1 text-sm text-muted-foreground hover:text-foreground", children: visibleMap[key] ? (_jsx(EyeOff, { className: "h-4 w-4" })) : (_jsx(Eye, { className: "h-4 w-4" })) })] }, key));
|
|
22
|
+
}) }));
|
|
23
|
+
};
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// WORKSPACE FORM
|
|
26
|
+
// ============================================================================
|
|
27
|
+
export const WorkspaceForm = () => {
|
|
28
|
+
const { state, handleChange, plans } = useWorkspaceModule();
|
|
29
|
+
const t = useTranslations("workspace");
|
|
30
|
+
const secrets = state.secrets || {};
|
|
31
|
+
const handleSecretChange = (key, value) => {
|
|
32
|
+
handleChange("secrets", Object.assign(Object.assign({}, secrets), { [key]: value }));
|
|
33
|
+
};
|
|
34
|
+
return (_jsxs("div", { className: "space-y-6", children: [_jsx(EnhancedInput, { id: "name", label: t("formNameLabel"), value: state.name, onChange: (e) => handleChange("name", e.target.value), error: state.errors.name, placeholder: t("formNamePlaceholder"), required: true, readOnly: true }), _jsx(EnhancedInput, { id: "subdomain", label: t("formSubdomainLabel"), value: state.subdomain, onChange: (e) => handleChange("subdomain", e.target.value), error: state.errors.subdomain, placeholder: t("formSubdomainPlaceholder"), required: true, info: `This will be your workspace URL: ${state.subdomain}.edupilotpro.com`, readOnly: true }), _jsx(EnhancedTextarea, { id: "description", label: t("formDescriptionLabel"), value: state.description || "", onChange: (e) => handleChange("description", e.target.value), error: state.errors.description, placeholder: t("formDescriptionPlaceholder"), rows: 3 }), _jsx(EnhancedInput, { id: "logo", label: "Logo URL", value: state.logo || "", onChange: (e) => handleChange("logo", e.target.value), error: state.errors.logo, placeholder: "Enter logo URL (optional)", type: "url", readOnly: true }), _jsx(EnhancedCombobox, { id: "planId", label: "Plan", value: state.planId || "", onValueChange: (value) => handleChange("planId", value), options: plans
|
|
35
|
+
.filter(({ name }) => name.match("PKR"))
|
|
36
|
+
.map((plan) => ({
|
|
37
|
+
label: plan.name,
|
|
38
|
+
value: plan.id,
|
|
39
|
+
})), error: state.errors.planId, placeholder: "Select a plan", info: "Choose the subscription plan for this workspace" }), _jsxs("div", { className: "border-t pt-6 mt-6", children: [_jsxs("div", { className: "flex items-center gap-2 mb-4", children: [_jsx(Shield, { className: "h-5 w-5 text-primary" }), _jsx("h3", { className: "text-lg font-semibold", children: "Secrets Configuration" })] }), _jsx("p", { className: "text-sm text-muted-foreground mb-4", children: "Configure encrypted secrets for external services like SMTP, API keys, etc." }), _jsx(SecretsEditor, { secrets: secrets, errors: state.errors, onChange: handleSecretChange })] })] }));
|
|
40
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WorkspaceMoreActions: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Workspace More Actions
|
|
5
|
+
*
|
|
6
|
+
* Placeholder component for additional workspace actions.
|
|
7
|
+
* Currently no additional actions are available for workspaces.
|
|
8
|
+
*/
|
|
9
|
+
import { useTranslations } from "next-intl";
|
|
10
|
+
export const WorkspaceMoreActions = () => {
|
|
11
|
+
const t = useTranslations("workspace");
|
|
12
|
+
return (_jsx("div", { className: "p-6 text-center text-muted-foreground", children: _jsx("p", { children: t("moreActions") }) }));
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WorkspacePage: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useWorkspaceModule, WorkspaceProvider } from "./context";
|
|
4
|
+
import { WorkspaceView } from "./view";
|
|
5
|
+
import { WorkspaceDrawer } from "./drawer";
|
|
6
|
+
import { Button } from "@appcorp/shadcn/components/ui/button";
|
|
7
|
+
import { Edit } from "lucide-react";
|
|
8
|
+
// import { useAuthStateContext } from "@/contexts/auth-context";
|
|
9
|
+
import { resolveRbacPermissions } from "@/utils/resolve-rbac-permissions";
|
|
10
|
+
import { USER_ROLE } from "@/type";
|
|
11
|
+
import { RbacNoAccess } from "@/components/rbac-no-access";
|
|
12
|
+
import { useTranslations } from "next-intl";
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// WORKSPACE PAGE COMPONENT
|
|
15
|
+
// ============================================================================
|
|
16
|
+
const WorkspaceInnerPage = () => {
|
|
17
|
+
// const { user } = useAuthStateContext();
|
|
18
|
+
// const userRole = user?.user_metadata?.role as USER_ROLE;
|
|
19
|
+
const userRole = USER_ROLE.SCHOOL_ADMIN; // Default for storybook
|
|
20
|
+
const { handleEdit } = useWorkspaceModule();
|
|
21
|
+
const t = useTranslations("workspace");
|
|
22
|
+
const hasPermission = resolveRbacPermissions({
|
|
23
|
+
userRole,
|
|
24
|
+
moduleName: "Workspace",
|
|
25
|
+
});
|
|
26
|
+
if (!hasPermission) {
|
|
27
|
+
return _jsx(RbacNoAccess, { moduleName: "Workspace" });
|
|
28
|
+
}
|
|
29
|
+
return (_jsx("div", { className: "container mx-auto px-4 py-8", children: _jsxs("div", { className: "mx-auto max-w-6xl", children: [_jsxs("div", { className: "mb-8", children: [_jsx("h1", { className: "text-3xl font-bold text-gray-900", children: t("tableTitle") }), _jsx("p", { className: "mt-2 text-gray-600", children: t("tableDescription") })] }), _jsx("div", { className: "mb-6 flex justify-end", children: _jsxs(Button, { onClick: handleEdit, className: "flex items-center space-x-2", children: [_jsx(Edit, { className: "h-4 w-4" }), _jsx("span", { children: t("headerActionsEdit") })] }) }), _jsx(WorkspaceView, {}), _jsx(WorkspaceDrawer, {})] }) }));
|
|
30
|
+
};
|
|
31
|
+
export const WorkspacePage = () => (_jsx(WorkspaceProvider, { children: _jsx(WorkspaceInnerPage, {}) }));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const workspaceFormValidation: z.ZodObject<{
|
|
3
|
+
id: z.ZodOptional<z.ZodString>;
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
subdomain: z.ZodString;
|
|
6
|
+
planId: z.ZodOptional<z.ZodString>;
|
|
7
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
export type WorkspaceForm = z.infer<typeof workspaceFormValidation>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const workspaceFormValidation = z.object({
|
|
3
|
+
id: z.string().optional(),
|
|
4
|
+
name: z.string().min(1, "Name is required"),
|
|
5
|
+
subdomain: z.string().min(1, "Subdomain is required"),
|
|
6
|
+
planId: z.string().optional(),
|
|
7
|
+
enabled: z.boolean().optional(),
|
|
8
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const WorkspaceView: () => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Workspace View
|
|
5
|
+
*
|
|
6
|
+
* Read-only view component for displaying workspace information.
|
|
7
|
+
*/
|
|
8
|
+
import { useWorkspaceModule } from "./context";
|
|
9
|
+
import { useTranslations } from "next-intl";
|
|
10
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@appcorp/shadcn/components/ui/card";
|
|
11
|
+
import { Badge } from "@appcorp/shadcn/components/ui/badge";
|
|
12
|
+
import { Separator } from "@appcorp/shadcn/components/ui/separator";
|
|
13
|
+
import { Building2, Globe, FileText, Image, CheckCircle2, XCircle, Calendar, CreditCard, Users, BookOpen, GraduationCap, Home, HardDrive, Clock, Shield, } from "lucide-react";
|
|
14
|
+
import { DATE_FORMATS, formatDate } from "@react-pakistan/util-functions";
|
|
15
|
+
import { formatValue } from "@/utils/format-value";
|
|
16
|
+
export const WorkspaceView = () => {
|
|
17
|
+
const { state } = useWorkspaceModule();
|
|
18
|
+
const t = useTranslations("workspace");
|
|
19
|
+
const formatCurrency = (amount, currency) => {
|
|
20
|
+
if (!amount)
|
|
21
|
+
return "—";
|
|
22
|
+
const numAmount = typeof amount === "string" ? parseFloat(amount) : amount;
|
|
23
|
+
if (isNaN(numAmount))
|
|
24
|
+
return "—";
|
|
25
|
+
return new Intl.NumberFormat("en-US", {
|
|
26
|
+
style: "currency",
|
|
27
|
+
currency: currency || "USD",
|
|
28
|
+
}).format(numAmount);
|
|
29
|
+
};
|
|
30
|
+
// Helper function to format billing interval
|
|
31
|
+
const formatBillingInterval = (interval) => {
|
|
32
|
+
if (!interval)
|
|
33
|
+
return "—";
|
|
34
|
+
return interval.charAt(0).toUpperCase() + interval.slice(1).toLowerCase();
|
|
35
|
+
};
|
|
36
|
+
// Helper function to format storage
|
|
37
|
+
const formatStorage = (mb) => {
|
|
38
|
+
if (mb < 1024)
|
|
39
|
+
return `${mb} MB`;
|
|
40
|
+
return `${(mb / 1024).toFixed(1)} GB`;
|
|
41
|
+
};
|
|
42
|
+
return (_jsxs("div", { className: "space-y-6", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Building2, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { className: "text-lg", children: t("basicInfoTitle") })] }), _jsx(CardDescription, { children: t("basicInfoDescription") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-2 md:grid-cols-2 gap-6", children: [_jsxs("div", { className: "space-y-1 md:col-span-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Building2, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewLabelsName") })] }), _jsx("p", { className: "text-base", children: formatValue(state.name) })] }), _jsxs("div", { className: "space-y-1 md:col-span-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Globe, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewLabelsSubdomain") })] }), _jsx("p", { className: "text-base", children: formatValue(state.subdomain) }), state.subdomain && (_jsxs("p", { className: "text-sm text-muted-foreground", children: [t("urlPrefix"), state.subdomain, ".edupilotpro.com"] }))] }), _jsxs("div", { className: "space-y-1 md:col-span-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FileText, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewLabelsDescription") })] }), _jsx("p", { className: "text-base", children: formatValue(state.description) === "—"
|
|
43
|
+
? t("noDescriptionProvided")
|
|
44
|
+
: state.description })] }), state.logo && (_jsxs("div", { className: "space-y-1 md:col-span-2", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Image, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewLabelsLogo") })] }), _jsx("div", { className: "mt-2", children: _jsx("img", { src: state.logo, alt: t("viewLabelsLogoAlt"), className: "h-16 w-16 object-contain rounded border", onError: (e) => {
|
|
45
|
+
e.currentTarget.style.display = "none";
|
|
46
|
+
} }) })] })), _jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("viewLabelsStatus") }), _jsxs(Badge, { variant: state.enabled ? "default" : "destructive", className: "gap-1", children: [state.enabled ? (_jsx(CheckCircle2, { className: "h-3 w-3" })) : (_jsx(XCircle, { className: "h-3 w-3" })), state.enabled
|
|
47
|
+
? t("viewStatusEnabled")
|
|
48
|
+
: t("viewStatusDisabled")] })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CreditCard, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { className: "text-lg", children: t("planBillingTitle") })] }), _jsx(CardDescription, { children: t("planBillingDescription") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-6", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CreditCard, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("planIdLabel") })] }), _jsx("p", { className: "font-mono text-sm", children: formatValue(state.planId) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Calendar, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("planStartDateLabel") })] }), _jsx("p", { className: "text-base", children: formatDate(state.planStartDate || "", DATE_FORMATS.LOCALE_DATE) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Calendar, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("planEndDateLabel") })] }), _jsx("p", { className: "text-base", children: formatDate(state.planEndDate || "", DATE_FORMATS.LOCALE_DATE) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Clock, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("billingIntervalLabel") })] }), _jsx("p", { className: "text-base", children: formatBillingInterval(state.billingInterval) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CreditCard, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("agreedPriceLabel") })] }), _jsx("p", { className: "text-base", children: formatCurrency(state.agreedPrice, state.agreedCurrency) })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Globe, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("currencyLabel") })] }), _jsx("p", { className: "text-base", children: formatValue(state.agreedCurrency) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Users, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { className: "text-lg", children: t("usageStatsTitle") })] }), _jsx(CardDescription, { children: t("usageStatsDescription") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "grid grid-cols-2 md:grid-cols-3 gap-6", children: [_jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(GraduationCap, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("studentsLabel") })] }), _jsx("p", { className: "text-2xl font-bold text-primary", children: state.studentsCount })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Users, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("teachersLabel") })] }), _jsx("p", { className: "text-2xl font-bold text-primary", children: state.teachersCount })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(BookOpen, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("classesLabel") })] }), _jsx("p", { className: "text-2xl font-bold text-primary", children: state.classesCount })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(BookOpen, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("coursesLabel") })] }), _jsx("p", { className: "text-2xl font-bold text-primary", children: state.coursesCount })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Home, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("familiesLabel") })] }), _jsx("p", { className: "text-2xl font-bold text-primary", children: state.familiesCount })] }), _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(HardDrive, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("storageUsedLabel") })] }), _jsx("p", { className: "text-2xl font-bold text-primary", children: formatStorage(state.storageUsedMB) })] })] }) })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Shield, { className: "h-5 w-5 text-primary" }), _jsx(CardTitle, { className: "text-lg", children: t("secretsTitle") })] }), _jsx(CardDescription, { children: t("secretsDescription") })] }), _jsx(Separator, {}), _jsx(CardContent, { className: "pt-6", children: _jsx("div", { className: "space-y-4", children: _jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [_jsx(Shield, { className: "h-4 w-4 text-muted-foreground" }), _jsx("p", { className: "text-sm font-medium text-muted-foreground", children: t("secretsJsonLabel") })] }), state.secrets ? (_jsx("div", { className: "space-y-2", children: Object.keys(state.secrets).length ===
|
|
49
|
+
0 ? (_jsx("p", { className: "text-muted-foreground italic", children: t("noSecretsConfigured") })) : (Object.entries(state.secrets).map(([k, v]) => (_jsxs("div", { className: "flex items-center justify-between bg-muted/10 border border-border/60 rounded-md p-3", children: [_jsx("div", { className: "text-sm font-medium text-foreground", children: k }), _jsx("div", { className: "text-sm font-mono text-foreground/80", children: typeof v === "string" && v.length > 0
|
|
50
|
+
? `${String(v).slice(0, 3)}${"*".repeat(Math.max(0, String(v).length - 3))}`
|
|
51
|
+
: "—" })] }, k)))) })) : (_jsx("p", { className: "text-muted-foreground italic", children: t("noSecretsConfigured") })), _jsx("p", { className: "text-xs text-muted-foreground mt-2", children: t("secretsHelpText") })] }) }) })] })] }));
|
|
52
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export const RbacNoAccess = ({ moduleName }) => {
|
|
3
|
+
return (_jsxs("div", { className: "flex flex-col items-center justify-center h-full gap-6 p-8", children: [_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", xmlnsXlink: "http://www.w3.org/1999/xlink", width: "293", height: "330", viewBox: "0 0 586.47858 659.29778", role: "img", "aria-label": "Access restricted illustration", className: "text-primary", children: [_jsx("circle", { cx: "332.47856", cy: "254", r: "254.00001", fill: "#f2f2f2" }), _jsx("path", { d: "M498.46363,113.58835H33.17063c-.99774-.02133-1.78931-.84746-1.76797-1.84521,.02069-.96771,.80026-1.74727,1.76797-1.76796H498.46363c.99774,.02133,1.78931,.84746,1.76794,1.84521-.02069,.96771-.80023,1.74727-1.76794,1.76796Z", fill: "#cacaca" }), _jsx("rect", { x: "193.77441", y: "174.47256", width: "163.61147", height: "34.98639", rx: "17.49318", ry: "17.49318", fill: "#fff" }), _jsx("path", { d: "M128.17493,244.44534H422.98542c9.66122,0,17.49316,7.83197,17.49316,17.49319h0c0,9.66122-7.83194,17.49319-17.49316,17.49319H128.17493c-9.66122,0-17.49318-7.83197-17.49318-17.49319h0c0-9.66122,7.83196-17.49319,17.49318-17.49319Z", fill: "#fff" }), _jsx("path", { d: "M128.17493,314.41812H422.98542c9.66122,0,17.49316,7.83197,17.49316,17.49319h0c0,9.66122-7.83194,17.49319-17.49316,17.49319H128.17493c-9.66122,0-17.49318-7.83197-17.49318-17.49319h0c0-9.66122,7.83196-17.49319,17.49318-17.49319Z", fill: "#fff" }), _jsx("path", { d: "M91.64085,657.75932l-.69385-.06793c-23.54068-2.42871-44.82135-15.08929-58.18845-34.61835-3.66138-5.44159-6.62299-11.32251-8.815-17.50409l-.21069-.58966,.62375-.05048c7.44699-.59924,15.09732-1.86292,18.49585-2.46417l-21.91473-7.42511-.1355-.65033c-1.29926-6.10406,1.24612-12.38458,6.4285-15.86176,5.19641-3.64447,12.08731-3.76111,17.40405-.29449,2.38599,1.52399,4.88162,3.03339,7.29489,4.49359,8.29321,5.01636,16.8688,10.20337,23.29828,17.30121,9.74951,10.97778,14.02298,25.76984,11.63,40.25562l4.7829,17.47595Z", fill: "#f2f2f2" }), _jsx("polygon", { points: "171.30016 646.86102 182.10017 646.85999 187.23916 605.198 171.29716 605.19897 171.30016 646.86102", fill: "#a0616a" }), _jsx("path", { d: "M170.9192,658.12816l33.21436-.00122v-.41998c-.00049-7.13965-5.78833-12.92737-12.92798-12.92773h-.00079l-6.06702-4.60278-11.3197,4.60345-2.89941,.00012,.00055,13.34814Z", fill: "#2f2e41" }), _jsx("polygon", { points: "84.74116 616.94501 93.38016 623.42603 122.49316 593.185 109.74116 583.61902 84.74116 616.94501", fill: "#a0616a" }), _jsx("path", { d: "M77.67448,625.72966l26.569,19.93188,.25208-.336c4.2843-5.71136,3.12799-13.81433-2.58279-18.09937l-.00064-.00049-2.09079-7.32275-11.81735-3.11102-2.31931-1.73993-8.01019,10.67767Z", fill: "#2f2e41" }), _jsx("path", { d: "M120.64463,451.35271s.59625,16.26422,1.3483,29.30737c.12335,2.13916-4.88821,4.46301-4.75842,6.7901,.08609,1.54395,1.02808,3.04486,1.1156,4.65472,.09235,1.69897-1.20822,3.20282-1.1156,4.95984,.09052,1.71667,1.57422,3.6853,1.66373,5.44244,.96317,18.9093,4.45459,41.54633,.9584,47.87439-1.72299,3.11871-23.68533,46.32446-23.68533,46.32446,0,0,12.23666,18.35498,15.73285,12.23663,4.61771-8.08099,40.20615-45.88745,40.20615-53.10712,0-7.21088,8.23346-61.25323,8.23346-61.25323l5.74103,31.98169,2.63239,6.33655-.82715,3.71997,1.70117,5.02045,.09192,4.96838,1.65619,9.22614s-4.98199,71.88159-2.17633,73.88312c2.81439,2.01038,16.44086,5.62018,18.04901,2.01038,1.59955-3.6098,12.0108-75.01947,12.0108-75.01947,0,0,1.6781-32.72424,3.49622-63.14111,.1048-1.76556,1.34607-3.89825,1.4422-5.63763,.11365-2.01898-.67297-4.64111-.56818-6.599,.11365-2.24628,1.11005-3.82831,1.20618-5.97852,.74292-16.6156-3.42761-36.84912-4.7561-38.84192-4.01202-6.01343-7.62177-10.82074-7.62177-10.82074,0,0-54.03558-17.75403-68.47485,.28625l-3.30185,25.37585Z", fill: "#2f2e41" }), _jsx("path", { d: "M174.53779,284.10378l-21.4209-4.28418-9.9964,13.56656h0c-18.65262,18.34058-18.93359,34.52753-15.60379,60.47382v36.41553l-2.41,24.41187s-8.53156,17.84521,.26788,22.00006,66.59857,3.80066,72.117,2.14209,.73517-3.69482-.71399-11.4245c-2.72211-14.51929-.90131-7.51562-.71399-12.13849,2.68585-66.31363-3.57013-93.5379-4.20544-100.69376l-10.89398-19.75858-6.42639-10.71042Z", fill: "#3f3d56" }), _jsx("path", { d: "M287.43909,337.57097c-2.23248,4.23007-7.47144,5.84943-11.70148,3.61694-.45099-.23804-.88013-.51541-1.28229-.82895l-46.26044,29.37308,.13336-15.9924,44.93842-26.07846c3.20093-3.58887,8.70514-3.90332,12.29401-.70239,3.00305,2.67844,3.7796,7.0657,1.87842,10.61218Z", fill: "#a0616a" }), _jsx("path", { d: "M157.62488,302.62425l-5.26666-.55807c-4.86633-.50473-9.64093,1.57941-12.57947,5.491-1.12549,1.48346-1.9339,3.18253-2.37491,4.99164l-.00317,.01447c-1.32108,5.44534,.75095,11.15201,5.25803,14.48117l18.19031,13.41101c12.76544,17.24899,36.75653,28.69272,64.89832,37.98978l43.74274-27.16666-15.47186-18.73843-30.00336,16.0798-44.59833-34.52374-.0257-.02075-16.97424-10.936-4.79169-.5152Z", fill: "#3f3d56" }), _jsx("circle", { cx: "167.29993", cy: "248.60526", r: "24.9798", fill: "#a0616a" }), _jsx("path", { d: "M167.8769,273.59047c-.20135,.00662-.4032,.01108-.6048,.01657-.0863,.22388-.17938,.44583-.2868,.66357l.8916-.68015Z", fill: "#2f2e41" }), _jsx("path", { d: "M174.73243,249.29823c.03918,.24612,.09912,.48846,.17914,.72449-.03302-.24731-.09308-.49026-.17914-.72449Z", fill: "#2f2e41" }), _jsx("path", { d: "M192.59852,224.6942c-1.0282,3.19272-1.94586-.85715-5.32825-.12869-4.06885,.87625-8.80377,.57532-12.13586-1.91879-4.96478-3.64273-11.39874-4.62335-17.22333-2.62509-5.70154,2.01706-15.25348,3.43933-16.73907,9.30179-.51642,2.03781-.7215,4.24933-1.97321,5.9382-1.09436,1.47662-2.82166,2.31854-4.26608,3.45499-4.87726,3.83743-1.14954,14.73981,1.15881,20.50046,2.30838,5.76065,7.60355,9.95721,13.42526,12.10678,5.63281,2.07977,11.7464,2.44662,17.75531,2.28317,1.04517-2.7106,.59363-5.84137-.26874-8.65134-.93359-3.04199-2.31592-5.97791-2.70593-9.13599s.46643-6.74527,3.11444-8.50986c2.4339-1.62192,6.39465-.63388,7.32062,1.98843-.54028-3.27841,2.7807-6.4509,6.20508-7.00882,3.67651-.599,7.35291,.72833,11.01886,1.38901s2.36475-14.77301,.64209-18.98425Z", fill: "#2f2e41" }), _jsx("circle", { cx: "281.3585", cy: "285.71051", r: "51.12006", transform: "translate(-26.58509 542.54478) rotate(-85.26884)", fill: "currentColor" }), _jsx("path", { d: "M294.78675,264.41051l-13.42828,13.42828-13.42828-13.42828c-2.17371-2.17374-5.69806-2.17374-7.87177,0s-2.17371,5.69803,0,7.87177l13.42828,13.42828-13.42828,13.42828c-2.17169,2.17575-2.1684,5.70007,.00739,7.87177,2.17285,2.16879,5.69153,2.16879,7.86438-.00003l13.42828-13.42828,13.42828,13.42828c2.17578,2.17169,5.70007,2.1684,7.87177-.00735,2.16882-2.17288,2.16882-5.6915,0-7.86438l-13.42828-13.42828,13.42828-13.42828c2.17371-2.17374,2.17371-5.69803,0-7.87177s-5.69806-2.17374-7.87177,0h0Z", fill: "#fff" }), _jsx("path", { d: "M261.21387,242.74385c1.5069,4.53946-.95154,9.44101-5.49097,10.94791-.48401,.16064-.9812,.27823-1.4859,.35141l-10.83051,53.71692-11.44788-11.16785,12.29266-50.48209c-.37366-4.7944,3.21008-8.98395,8.00452-9.3576,4.01166-.31265,7.71509,2.16425,8.95807,5.9913Z", fill: "#a0616a" }), _jsx("path", { d: "M146.12519,312.22478l-4.04883,3.41412c-3.73322,3.16214-5.53476,8.05035-4.74649,12.87888,.29129,1.83917,.95773,3.59879,1.95786,5.16949l.00824,.0123c3.01477,4.72311,8.5672,7.17865,14.08978,6.23117l22.27075-3.84171c21.28461,2.72995,46.15155-6.65967,72.34302-20.53055l10.67969-50.37274-24.23297-1.80811-9.16821,32.78271-55.78815,8.28149-.03278,.00415-19.64294,4.67767-3.68896,3.1011Z", fill: "#3f3d56" }), _jsx("path", { d: "M272.93684,658.99046l-271.75,.30731c-.65759-.00214-1.18896-.53693-1.18683-1.19452,.00211-.6546,.53223-1.18469,1.18683-1.18683l271.75-.30731c.65759,.00214,1.18896,.53693,1.18683,1.19452-.00208,.6546-.53223,1.18469-1.18683,1.18683Z", fill: "#cacaca" }), _jsxs("g", { children: [_jsx("ellipse", { cx: "56.77685", cy: "82.05834", rx: "8.45661", ry: "8.64507", fill: "#3f3d56" }), _jsx("ellipse", { cx: "85.9906", cy: "82.05834", rx: "8.45661", ry: "8.64507", fill: "#3f3d56" }), _jsx("ellipse", { cx: "115.20435", cy: "82.05834", rx: "8.45661", ry: "8.64507", fill: "#3f3d56" }), _jsx("path", { d: "M148.51577,88.89113c-.25977,0-.51904-.10059-.71484-.30078l-5.70605-5.83301c-.38037-.38867-.38037-1.00977,0-1.39844l5.70605-5.83252c.38721-.39453,1.021-.40088,1.41406-.01562,.39502,.38623,.40186,1.01953,.01562,1.41406l-5.02197,5.1333,5.02197,5.13379c.38623,.39453,.37939,1.02783-.01562,1.41406-.19434,.19043-.44678,.28516-.69922,.28516Z", fill: "#3f3d56" }), _jsx("path", { d: "M158.10415,88.89113c-.25244,0-.50488-.09473-.69922-.28516-.39502-.38623-.40186-1.01904-.01562-1.41406l5.02148-5.13379-5.02148-5.1333c-.38623-.39453-.37939-1.02783,.01562-1.41406,.39404-.38672,1.02783-.37939,1.41406,.01562l5.70557,5.83252c.38037,.38867,.38037,1.00977,0,1.39844l-5.70557,5.83301c-.1958,.2002-.45508,.30078-.71484,.30078Z", fill: "#3f3d56" }), _jsx("path", { d: "M456.61398,74.41416h-10.60999c-1.21002,0-2.19,.97998-2.19,2.19v10.62c0,1.21002,.97998,2.19,2.19,2.19h10.60999c1.21002,0,2.20001-.97998,2.20001-2.19v-10.62c0-1.21002-.98999-2.19-2.20001-2.19Z", fill: "#3f3d56" }), _jsx("path", { d: "M430.61398,74.41416h-10.60999c-1.21002,0-2.19,.97998-2.19,2.19v10.62c0,1.21002,.97998,2.19,2.19,2.19h10.60999c1.21002,0,2.20001-.97998,2.20001-2.19v-10.62c0-1.21002-.98999-2.19-2.20001-2.19Z", fill: "#3f3d56" }), _jsx("path", { d: "M481.11398,74.91416h-10.60999c-1.21002,0-2.19,.97998-2.19,2.19v10.62c0,1.21002,.97998,2.19,2.19,2.19h10.60999c1.21002,0,2.20001-.97998,2.20001-2.19v-10.62c0-1.21002-.98999-2.19-2.20001-2.19Z", fill: "#3f3d56" }), _jsx("path", { d: "M321.19229,78.95414h-84.81c-1.48004,0-2.67004,1.20001-2.67004,2.67004s1.19,2.66998,2.67004,2.66998h84.81c1.46997,0,2.66998-1.20001,2.66998-2.66998s-1.20001-2.67004-2.66998-2.67004Z", fill: "#3f3d56" })] })] }), _jsxs("div", { className: "text-center max-w-sm", children: [_jsx("h1", { className: "text-2xl font-bold text-gray-900 dark:text-gray-100 mb-2", children: "Access Restricted" }), _jsxs("p", { className: "text-gray-500 dark:text-gray-400 text-sm leading-relaxed", children: ["You don't have permission to access", " ", _jsx("span", { className: "font-medium text-gray-700 dark:text-gray-300", children: moduleName ? `the ${moduleName} module` : "this module" }), ". Please contact your administrator if you believe this is an error."] })] })] }));
|
|
4
|
+
};
|