datastake-daf 0.6.501 → 0.6.503
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/dist/layouts/index.css +1 -0
- package/dist/layouts/index.js +7137 -0
- package/dist/utils/index.js +287 -0
- package/package.json +1 -1
- package/rollup.config.js +25 -0
- package/src/@daf/hooks/usePermissions.js +20 -0
- package/src/@daf/layouts/AppLayout/AppLayout.stories.js +532 -0
- package/src/@daf/layouts/AppLayout/components/LoginPopup/index.js +116 -0
- package/src/@daf/layouts/AppLayout/components/LoginPopup/style.js +26 -0
- package/src/@daf/layouts/AppLayout/components/MobileDrawer/index.js +208 -0
- package/src/@daf/layouts/AppLayout/components/MobileDrawer/style.js +87 -0
- package/src/@daf/layouts/AppLayout/components/Notifications/Notification/index.js +31 -0
- package/src/@daf/layouts/AppLayout/components/Notifications/NotificationHistory/index.js +22 -0
- package/src/@daf/layouts/AppLayout/components/Notifications/context/index.js +79 -0
- package/src/@daf/layouts/AppLayout/components/Notifications/index.js +106 -0
- package/src/@daf/layouts/AppLayout/components/Notifications/style.js +61 -0
- package/src/@daf/layouts/AppLayout/components/Notifications/useNotifications.js +105 -0
- package/src/@daf/layouts/AppLayout/components/Sidenav/index.js +296 -0
- package/src/@daf/layouts/AppLayout/components/UserDropdown/UserIcon.js +96 -0
- package/src/@daf/layouts/AppLayout/components/UserDropdown/index.js +112 -0
- package/src/@daf/layouts/AppLayout/index.jsx +384 -0
- package/src/@daf/layouts/AppLayout/index.scss +5 -0
- package/src/@daf/layouts/AppLayout/styles/header.scss +257 -0
- package/src/@daf/layouts/AppLayout/styles/layout.scss +76 -0
- package/src/@daf/layouts/AppLayout/styles/responsive.scss +52 -0
- package/src/@daf/layouts/AppLayout/styles/sidebar.scss +79 -0
- package/src/@daf/layouts/AppLayout/styles/variables.scss +22 -0
- package/src/helpers/theme.js +304 -0
- package/src/helpers/user.js +4 -0
- package/src/layouts.js +1 -0
- package/src/utils.js +4 -2
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import AppLayout from "./index.jsx";
|
|
3
|
+
import ThemeLayout from "../../core/components/ThemeLayout/index.jsx";
|
|
4
|
+
import { FormsProvider } from "../../core/context/Forms/index.js";
|
|
5
|
+
import { ResizeProvider } from "../../core/context/Resize/index.js";
|
|
6
|
+
import { GeneralProvider } from "../../core/context/General/index.js";
|
|
7
|
+
|
|
8
|
+
// Mock data
|
|
9
|
+
const mockUser = {
|
|
10
|
+
id: "user-1",
|
|
11
|
+
email: "john.doe@example.com",
|
|
12
|
+
firstName: "John",
|
|
13
|
+
lastName: "Doe",
|
|
14
|
+
language: "en",
|
|
15
|
+
role: {
|
|
16
|
+
id: "EDITOR",
|
|
17
|
+
name: "Editor",
|
|
18
|
+
permissions: {
|
|
19
|
+
"dashboard.canView": true,
|
|
20
|
+
"notifications.canView": true,
|
|
21
|
+
"users.canView": true,
|
|
22
|
+
"settings.canView": true,
|
|
23
|
+
"projects.canView": true,
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
company: {
|
|
27
|
+
id: "company-1",
|
|
28
|
+
name: "Acme Corporation",
|
|
29
|
+
logo: [],
|
|
30
|
+
apps: [],
|
|
31
|
+
modules: [
|
|
32
|
+
{ id: "sbg", status: "approved", role: "editor" }
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
modules: {
|
|
36
|
+
sbg: { status: "approved", role: "editor" }
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const mockAdminUser = {
|
|
41
|
+
...mockUser,
|
|
42
|
+
role: {
|
|
43
|
+
id: "APP_ADMIN",
|
|
44
|
+
name: "Admin",
|
|
45
|
+
permissions: {
|
|
46
|
+
"dashboard.canView": true,
|
|
47
|
+
"notifications.canView": true,
|
|
48
|
+
"users.canView": true,
|
|
49
|
+
"settings.canView": true,
|
|
50
|
+
"projects.canView": true,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// Mock navigation
|
|
56
|
+
const mockNavigate = (path) => {
|
|
57
|
+
console.log("Navigate to:", path);
|
|
58
|
+
alert(`Navigating to: ${path}`);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const mockLocation = {
|
|
62
|
+
pathname: "/app/sbg/dashboard",
|
|
63
|
+
search: "",
|
|
64
|
+
hash: "",
|
|
65
|
+
state: null
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const mockMatchPath = (pattern, pathname) => {
|
|
69
|
+
console.log("Matching path:", pattern, pathname);
|
|
70
|
+
return pathname.includes(pattern.path);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Mock Outlet component
|
|
74
|
+
const MockOutlet = () => (
|
|
75
|
+
<div style={{ padding: "20px", minHeight: "500px" }}>
|
|
76
|
+
<h1>Dashboard Content</h1>
|
|
77
|
+
<p>This is where your page content would appear.</p>
|
|
78
|
+
<div style={{
|
|
79
|
+
background: "#f5f5f5",
|
|
80
|
+
padding: "20px",
|
|
81
|
+
borderRadius: "8px",
|
|
82
|
+
marginTop: "20px"
|
|
83
|
+
}}>
|
|
84
|
+
<h2>Sample Content</h2>
|
|
85
|
+
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Mock translation function
|
|
91
|
+
const mockT = (key) => {
|
|
92
|
+
const translations = {
|
|
93
|
+
"Users": "Users",
|
|
94
|
+
"Settings": "Settings",
|
|
95
|
+
"Log out": "Log out",
|
|
96
|
+
"Projects": "Projects",
|
|
97
|
+
"Partners": "Partners",
|
|
98
|
+
"Dashboard": "Dashboard",
|
|
99
|
+
"sbg::notification": "Notifications",
|
|
100
|
+
"Clear All": "Clear All",
|
|
101
|
+
"View All": "View All",
|
|
102
|
+
"No new notifications": "No new notifications",
|
|
103
|
+
"Log back in": "Log back in",
|
|
104
|
+
"You were logged out due to inactivity. Please provide your details.": "You were logged out due to inactivity. Please provide your details.",
|
|
105
|
+
"Email": "Email",
|
|
106
|
+
"Password": "Password",
|
|
107
|
+
"Remember me": "Remember me",
|
|
108
|
+
"Log in": "Log in",
|
|
109
|
+
"Logging-in": "Logging in...",
|
|
110
|
+
};
|
|
111
|
+
return translations[key] || key;
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Mock sidenav configuration
|
|
115
|
+
const mockSidenavConfig = {
|
|
116
|
+
sbg: [
|
|
117
|
+
{
|
|
118
|
+
name: "Dashboard",
|
|
119
|
+
icon: "TifDashboard",
|
|
120
|
+
visible: () => true,
|
|
121
|
+
path: "/app/sbg/dashboard",
|
|
122
|
+
isDashboard: true,
|
|
123
|
+
type: "link",
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: "Producers",
|
|
127
|
+
icon: "TifAmp",
|
|
128
|
+
visible: () => true,
|
|
129
|
+
path: "/app/registration",
|
|
130
|
+
isModule: true,
|
|
131
|
+
type: "link",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "Mines",
|
|
135
|
+
icon: "MineSite",
|
|
136
|
+
visible: () => true,
|
|
137
|
+
path: "/app/mines",
|
|
138
|
+
isModule: true,
|
|
139
|
+
type: "link",
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "Activities",
|
|
143
|
+
icon: "Event",
|
|
144
|
+
visible: () => true,
|
|
145
|
+
path: "/app/activities",
|
|
146
|
+
isModule: true,
|
|
147
|
+
type: "link",
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: "Documentation",
|
|
151
|
+
icon: "DashboardDocuments",
|
|
152
|
+
visible: () => true,
|
|
153
|
+
path: "/app/documents",
|
|
154
|
+
isModule: true,
|
|
155
|
+
type: "link",
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: "Stakeholders",
|
|
159
|
+
icon: "DashboardStakeholder",
|
|
160
|
+
visible: () => true,
|
|
161
|
+
path: "/app/stakeholders",
|
|
162
|
+
isModule: true,
|
|
163
|
+
type: "link",
|
|
164
|
+
},
|
|
165
|
+
]
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Mock permission check function
|
|
169
|
+
const mockCheckPermission = ({ permission, permissions }) => {
|
|
170
|
+
return permissions?.[permission] || false;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
// Mock user helpers
|
|
174
|
+
const mockUserHelpers = {
|
|
175
|
+
userIsAdmin: (user) => user?.role?.id === "APP_ADMIN",
|
|
176
|
+
userIsSbgImplementor: (user) => false,
|
|
177
|
+
userIsSbgPartner: (user) => false,
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// Language configuration
|
|
181
|
+
const languageConfig = [
|
|
182
|
+
{ value: "en", label: "EN", flagUrl: "/assets/images/countries/gb.png" },
|
|
183
|
+
{ value: "fr", label: "FR", flagUrl: "/assets/images/countries/fr.png" },
|
|
184
|
+
{ value: "sp", label: "ES", flagUrl: "/assets/images/countries/sp.png" }
|
|
185
|
+
];
|
|
186
|
+
|
|
187
|
+
// App logos
|
|
188
|
+
const appLogos = {
|
|
189
|
+
collapsed: '/assets/sbg-images/sbg-logo-small.svg',
|
|
190
|
+
expanded: '/assets/sbg-images/sbg-logo.svg'
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Mock notification handlers
|
|
194
|
+
const mockNotificationHandlers = {
|
|
195
|
+
login: (credentials, callback) => {
|
|
196
|
+
console.log("Login attempt:", credentials);
|
|
197
|
+
setTimeout(() => {
|
|
198
|
+
alert("Login successful!");
|
|
199
|
+
callback?.();
|
|
200
|
+
}, 1000);
|
|
201
|
+
},
|
|
202
|
+
loggingIn: false,
|
|
203
|
+
firebaseToken: "mock-firebase-token",
|
|
204
|
+
fetchNotifications: async ({ page, status, limit }) => {
|
|
205
|
+
console.log("Fetching notifications:", { page, status, limit });
|
|
206
|
+
return {
|
|
207
|
+
data: [
|
|
208
|
+
{
|
|
209
|
+
id: "notif-1",
|
|
210
|
+
title: "New Project",
|
|
211
|
+
body: "A new project has been assigned to you",
|
|
212
|
+
createdAt: new Date().toISOString(),
|
|
213
|
+
read: false,
|
|
214
|
+
data: { link: "/app/sbg/projects/1" }
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
id: "notif-2",
|
|
218
|
+
title: "Document Updated",
|
|
219
|
+
body: "Document #123 has been updated",
|
|
220
|
+
createdAt: new Date().toISOString(),
|
|
221
|
+
read: false,
|
|
222
|
+
data: { link: "/app/sbg/documents/123" }
|
|
223
|
+
}
|
|
224
|
+
],
|
|
225
|
+
total: 2
|
|
226
|
+
};
|
|
227
|
+
},
|
|
228
|
+
markAsRead: async (id) => {
|
|
229
|
+
console.log("Mark as read:", id);
|
|
230
|
+
},
|
|
231
|
+
markAllAsRead: async () => {
|
|
232
|
+
console.log("Mark all as read");
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// Mock general context
|
|
237
|
+
const mockGeneralContext = {
|
|
238
|
+
theme: {},
|
|
239
|
+
ajaxOptions: {},
|
|
240
|
+
ajaxForms: {},
|
|
241
|
+
changeAjaxForms: () => {},
|
|
242
|
+
changeAjaxOptions: () => {},
|
|
243
|
+
logOutPopupVisible: false,
|
|
244
|
+
setLogOutPopupVisible: (visible) => console.log("Set logout popup visible:", visible),
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// Mock getUserPreference
|
|
248
|
+
const mockGetUserPreference = async () => {
|
|
249
|
+
return {
|
|
250
|
+
data: [
|
|
251
|
+
{ key: "notification_steper", value: true }
|
|
252
|
+
]
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
// Mock NotificationsHistoryProvider
|
|
257
|
+
const MockNotificationsHistoryProvider = ({ children }) => <>{children}</>;
|
|
258
|
+
|
|
259
|
+
export default {
|
|
260
|
+
title: "Layouts/AppLayout",
|
|
261
|
+
component: AppLayout,
|
|
262
|
+
tags: ["autodocs"],
|
|
263
|
+
decorators: [
|
|
264
|
+
(Story) => (
|
|
265
|
+
<ThemeLayout>
|
|
266
|
+
<GeneralProvider theme={{}}>
|
|
267
|
+
<ResizeProvider>
|
|
268
|
+
<FormsProvider t={mockT}>
|
|
269
|
+
<div style={{ width: "100vw", height: "100vh" }}>
|
|
270
|
+
<Story />
|
|
271
|
+
</div>
|
|
272
|
+
</FormsProvider>
|
|
273
|
+
</ResizeProvider>
|
|
274
|
+
</GeneralProvider>
|
|
275
|
+
</ThemeLayout>
|
|
276
|
+
),
|
|
277
|
+
],
|
|
278
|
+
argTypes: {
|
|
279
|
+
module: {
|
|
280
|
+
control: "select",
|
|
281
|
+
options: ["sbg", "app"],
|
|
282
|
+
description: "Current module/app name",
|
|
283
|
+
},
|
|
284
|
+
collapsed: {
|
|
285
|
+
control: "boolean",
|
|
286
|
+
description: "Initial collapsed state of sidebar",
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
// Default story
|
|
292
|
+
export const Default = {
|
|
293
|
+
name: "Default Layout",
|
|
294
|
+
render: (args) => (
|
|
295
|
+
<AppLayout
|
|
296
|
+
// User & Auth
|
|
297
|
+
user={mockUser}
|
|
298
|
+
module={args.module || "sbg"}
|
|
299
|
+
logout={() => console.log("Logout clicked")}
|
|
300
|
+
exitImpersonation={() => console.log("Exit impersonation")}
|
|
301
|
+
updateLanguage={(lng) => console.log("Language changed to:", lng)}
|
|
302
|
+
getUserOptions={(lang) => console.log("Get user options for:", lang)}
|
|
303
|
+
|
|
304
|
+
// Navigation
|
|
305
|
+
navigate={mockNavigate}
|
|
306
|
+
location={mockLocation}
|
|
307
|
+
matchPath={mockMatchPath}
|
|
308
|
+
Outlet={MockOutlet}
|
|
309
|
+
|
|
310
|
+
// i18n
|
|
311
|
+
t={mockT}
|
|
312
|
+
|
|
313
|
+
// Permissions
|
|
314
|
+
checkPermission={mockCheckPermission}
|
|
315
|
+
|
|
316
|
+
// General Context
|
|
317
|
+
generalContext={mockGeneralContext}
|
|
318
|
+
|
|
319
|
+
// Services
|
|
320
|
+
getUserPreference={mockGetUserPreference}
|
|
321
|
+
|
|
322
|
+
// Notifications
|
|
323
|
+
notificationHandlers={mockNotificationHandlers}
|
|
324
|
+
NotificationsHistoryProvider={MockNotificationsHistoryProvider}
|
|
325
|
+
|
|
326
|
+
// Config
|
|
327
|
+
sidenavConfig={mockSidenavConfig}
|
|
328
|
+
appName="sbg"
|
|
329
|
+
appLogos={appLogos}
|
|
330
|
+
languageConfig={languageConfig}
|
|
331
|
+
userHelpers={mockUserHelpers}
|
|
332
|
+
isDev={true}
|
|
333
|
+
|
|
334
|
+
// Callbacks
|
|
335
|
+
onCollapse={(collapsed) => console.log("Sidebar collapsed:", collapsed)}
|
|
336
|
+
/>
|
|
337
|
+
),
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
// Admin user story
|
|
341
|
+
export const AdminUser = {
|
|
342
|
+
name: "Admin User",
|
|
343
|
+
render: () => (
|
|
344
|
+
<AppLayout
|
|
345
|
+
user={mockAdminUser}
|
|
346
|
+
module="sbg"
|
|
347
|
+
logout={() => console.log("Logout clicked")}
|
|
348
|
+
exitImpersonation={() => console.log("Exit impersonation")}
|
|
349
|
+
updateLanguage={(lng) => console.log("Language changed to:", lng)}
|
|
350
|
+
getUserOptions={(lang) => console.log("Get user options for:", lang)}
|
|
351
|
+
navigate={mockNavigate}
|
|
352
|
+
location={mockLocation}
|
|
353
|
+
matchPath={mockMatchPath}
|
|
354
|
+
Outlet={MockOutlet}
|
|
355
|
+
t={mockT}
|
|
356
|
+
checkPermission={mockCheckPermission}
|
|
357
|
+
generalContext={mockGeneralContext}
|
|
358
|
+
getUserPreference={mockGetUserPreference}
|
|
359
|
+
notificationHandlers={mockNotificationHandlers}
|
|
360
|
+
NotificationsHistoryProvider={MockNotificationsHistoryProvider}
|
|
361
|
+
sidenavConfig={mockSidenavConfig}
|
|
362
|
+
appName="sbg"
|
|
363
|
+
appLogos={appLogos}
|
|
364
|
+
languageConfig={languageConfig}
|
|
365
|
+
userHelpers={mockUserHelpers}
|
|
366
|
+
isDev={true}
|
|
367
|
+
onCollapse={(collapsed) => console.log("Sidebar collapsed:", collapsed)}
|
|
368
|
+
/>
|
|
369
|
+
),
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
// App navigation (no sidebar)
|
|
373
|
+
export const AppNavigation = {
|
|
374
|
+
name: "App Navigation (No Sidebar)",
|
|
375
|
+
render: () => (
|
|
376
|
+
<AppLayout
|
|
377
|
+
user={mockUser}
|
|
378
|
+
module="app"
|
|
379
|
+
logout={() => console.log("Logout clicked")}
|
|
380
|
+
exitImpersonation={() => console.log("Exit impersonation")}
|
|
381
|
+
updateLanguage={(lng) => console.log("Language changed to:", lng)}
|
|
382
|
+
getUserOptions={(lang) => console.log("Get user options for:", lang)}
|
|
383
|
+
navigate={mockNavigate}
|
|
384
|
+
location={mockLocation}
|
|
385
|
+
matchPath={mockMatchPath}
|
|
386
|
+
Outlet={MockOutlet}
|
|
387
|
+
t={mockT}
|
|
388
|
+
checkPermission={mockCheckPermission}
|
|
389
|
+
generalContext={mockGeneralContext}
|
|
390
|
+
getUserPreference={mockGetUserPreference}
|
|
391
|
+
notificationHandlers={mockNotificationHandlers}
|
|
392
|
+
NotificationsHistoryProvider={MockNotificationsHistoryProvider}
|
|
393
|
+
sidenavConfig={mockSidenavConfig}
|
|
394
|
+
appName="sbg"
|
|
395
|
+
appLogos={appLogos}
|
|
396
|
+
languageConfig={languageConfig}
|
|
397
|
+
userHelpers={mockUserHelpers}
|
|
398
|
+
isDev={true}
|
|
399
|
+
onCollapse={(collapsed) => console.log("Sidebar collapsed:", collapsed)}
|
|
400
|
+
/>
|
|
401
|
+
),
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
// With Login Popup
|
|
405
|
+
export const WithLoginPopup = {
|
|
406
|
+
name: "With Login Popup",
|
|
407
|
+
render: () => {
|
|
408
|
+
const contextWithPopup = {
|
|
409
|
+
...mockGeneralContext,
|
|
410
|
+
logOutPopupVisible: true,
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
return (
|
|
414
|
+
<AppLayout
|
|
415
|
+
user={mockUser}
|
|
416
|
+
module="sbg"
|
|
417
|
+
logout={() => console.log("Logout clicked")}
|
|
418
|
+
exitImpersonation={() => console.log("Exit impersonation")}
|
|
419
|
+
updateLanguage={(lng) => console.log("Language changed to:", lng)}
|
|
420
|
+
getUserOptions={(lang) => console.log("Get user options for:", lang)}
|
|
421
|
+
navigate={mockNavigate}
|
|
422
|
+
location={mockLocation}
|
|
423
|
+
matchPath={mockMatchPath}
|
|
424
|
+
Outlet={MockOutlet}
|
|
425
|
+
t={mockT}
|
|
426
|
+
checkPermission={mockCheckPermission}
|
|
427
|
+
generalContext={contextWithPopup}
|
|
428
|
+
getUserPreference={mockGetUserPreference}
|
|
429
|
+
notificationHandlers={mockNotificationHandlers}
|
|
430
|
+
NotificationsHistoryProvider={MockNotificationsHistoryProvider}
|
|
431
|
+
sidenavConfig={mockSidenavConfig}
|
|
432
|
+
appName="sbg"
|
|
433
|
+
appLogos={appLogos}
|
|
434
|
+
languageConfig={languageConfig}
|
|
435
|
+
userHelpers={mockUserHelpers}
|
|
436
|
+
isDev={true}
|
|
437
|
+
onCollapse={(collapsed) => console.log("Sidebar collapsed:", collapsed)}
|
|
438
|
+
/>
|
|
439
|
+
);
|
|
440
|
+
},
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
// No Notifications Permission
|
|
444
|
+
export const NoNotifications = {
|
|
445
|
+
name: "No Notifications Permission",
|
|
446
|
+
render: () => {
|
|
447
|
+
const userWithoutNotifications = {
|
|
448
|
+
...mockUser,
|
|
449
|
+
role: {
|
|
450
|
+
...mockUser.role,
|
|
451
|
+
permissions: {
|
|
452
|
+
...mockUser.role.permissions,
|
|
453
|
+
"notifications.canView": false,
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
return (
|
|
459
|
+
<AppLayout
|
|
460
|
+
user={userWithoutNotifications}
|
|
461
|
+
module="sbg"
|
|
462
|
+
logout={() => console.log("Logout clicked")}
|
|
463
|
+
exitImpersonation={() => console.log("Exit impersonation")}
|
|
464
|
+
updateLanguage={(lng) => console.log("Language changed to:", lng)}
|
|
465
|
+
getUserOptions={(lang) => console.log("Get user options for:", lang)}
|
|
466
|
+
navigate={mockNavigate}
|
|
467
|
+
location={mockLocation}
|
|
468
|
+
matchPath={mockMatchPath}
|
|
469
|
+
Outlet={MockOutlet}
|
|
470
|
+
t={mockT}
|
|
471
|
+
checkPermission={mockCheckPermission}
|
|
472
|
+
generalContext={mockGeneralContext}
|
|
473
|
+
getUserPreference={mockGetUserPreference}
|
|
474
|
+
notificationHandlers={mockNotificationHandlers}
|
|
475
|
+
NotificationsHistoryProvider={MockNotificationsHistoryProvider}
|
|
476
|
+
sidenavConfig={mockSidenavConfig}
|
|
477
|
+
appName="sbg"
|
|
478
|
+
appLogos={appLogos}
|
|
479
|
+
languageConfig={languageConfig}
|
|
480
|
+
userHelpers={mockUserHelpers}
|
|
481
|
+
isDev={true}
|
|
482
|
+
onCollapse={(collapsed) => console.log("Sidebar collapsed:", collapsed)}
|
|
483
|
+
/>
|
|
484
|
+
);
|
|
485
|
+
},
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
// With Custom Children
|
|
489
|
+
export const WithCustomChildren = {
|
|
490
|
+
name: "With Custom Children",
|
|
491
|
+
render: () => (
|
|
492
|
+
<AppLayout
|
|
493
|
+
user={mockUser}
|
|
494
|
+
module="sbg"
|
|
495
|
+
logout={() => console.log("Logout clicked")}
|
|
496
|
+
exitImpersonation={() => console.log("Exit impersonation")}
|
|
497
|
+
updateLanguage={(lng) => console.log("Language changed to:", lng)}
|
|
498
|
+
getUserOptions={(lang) => console.log("Get user options for:", lang)}
|
|
499
|
+
navigate={mockNavigate}
|
|
500
|
+
location={mockLocation}
|
|
501
|
+
matchPath={mockMatchPath}
|
|
502
|
+
t={mockT}
|
|
503
|
+
checkPermission={mockCheckPermission}
|
|
504
|
+
generalContext={mockGeneralContext}
|
|
505
|
+
getUserPreference={mockGetUserPreference}
|
|
506
|
+
notificationHandlers={mockNotificationHandlers}
|
|
507
|
+
NotificationsHistoryProvider={MockNotificationsHistoryProvider}
|
|
508
|
+
sidenavConfig={mockSidenavConfig}
|
|
509
|
+
appName="sbg"
|
|
510
|
+
appLogos={appLogos}
|
|
511
|
+
languageConfig={languageConfig}
|
|
512
|
+
userHelpers={mockUserHelpers}
|
|
513
|
+
isDev={true}
|
|
514
|
+
onCollapse={(collapsed) => console.log("Sidebar collapsed:", collapsed)}
|
|
515
|
+
>
|
|
516
|
+
<div style={{ padding: "40px" }}>
|
|
517
|
+
<h1>Custom Children Content</h1>
|
|
518
|
+
<p>This is custom content passed as children prop.</p>
|
|
519
|
+
<div style={{
|
|
520
|
+
background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
|
|
521
|
+
color: "white",
|
|
522
|
+
padding: "30px",
|
|
523
|
+
borderRadius: "12px",
|
|
524
|
+
marginTop: "20px"
|
|
525
|
+
}}>
|
|
526
|
+
<h2>Beautiful Card</h2>
|
|
527
|
+
<p>With gradient background and custom styling.</p>
|
|
528
|
+
</div>
|
|
529
|
+
</div>
|
|
530
|
+
</AppLayout>
|
|
531
|
+
),
|
|
532
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/* eslint-disable react/prop-types */
|
|
2
|
+
import React, { useEffect, useState } from "react";
|
|
3
|
+
import { Checkbox, Form, Input, Modal } from "antd";
|
|
4
|
+
import Style from './style';
|
|
5
|
+
import BorderedButton from "../../../../core/components/Button/BorderedButton/index.jsx";
|
|
6
|
+
|
|
7
|
+
function LoginPopup({
|
|
8
|
+
user,
|
|
9
|
+
t = (key) => key,
|
|
10
|
+
login,
|
|
11
|
+
loggingIn = false,
|
|
12
|
+
setLogOutPopupVisible,
|
|
13
|
+
firebaseToken,
|
|
14
|
+
}) {
|
|
15
|
+
const [form] = Form.useForm();
|
|
16
|
+
const [formErrors, setFormErrors] = useState(null);
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
form.setFieldsValue({ username: user?.email });
|
|
20
|
+
}, [user, form]);
|
|
21
|
+
|
|
22
|
+
const loginHandle = async () => {
|
|
23
|
+
setFormErrors(null);
|
|
24
|
+
form.validateFields().then(payload => {
|
|
25
|
+
login?.({ ...payload, firebaseToken }, () => setLogOutPopupVisible?.(false));
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const renderErrors = (err, t) => {
|
|
30
|
+
document.querySelectorAll('.ant-form-item')
|
|
31
|
+
.forEach(input => input.classList.add('ant-form-item-has-error'));
|
|
32
|
+
|
|
33
|
+
return Object.keys(err).map(key => {
|
|
34
|
+
return err[key].map(error =>
|
|
35
|
+
<div
|
|
36
|
+
key={error}
|
|
37
|
+
className="ant-form-item-explain errors-cont"
|
|
38
|
+
style={{ color: '#ff4d4f' }}
|
|
39
|
+
>
|
|
40
|
+
{t(error)}
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<Modal
|
|
48
|
+
open
|
|
49
|
+
footer={null}
|
|
50
|
+
closable={false}
|
|
51
|
+
>
|
|
52
|
+
<Style className="popup">
|
|
53
|
+
<h2>{t('Log back in')}</h2>
|
|
54
|
+
<p className="pb-4">{t('You were logged out due to inactivity. Please provide your details.')}</p>
|
|
55
|
+
<Form name="login" layout="vertical" form={form} initialValues={{ remember: true }}>
|
|
56
|
+
<Form.Item
|
|
57
|
+
required
|
|
58
|
+
name="username"
|
|
59
|
+
label={t("Email")}
|
|
60
|
+
rules={[
|
|
61
|
+
{
|
|
62
|
+
required: true,
|
|
63
|
+
message: t("errors::email should not be empty")
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
pattern: /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/,
|
|
67
|
+
message: t('errors::email is not valid'),
|
|
68
|
+
},
|
|
69
|
+
]}
|
|
70
|
+
>
|
|
71
|
+
<Input
|
|
72
|
+
type="email"
|
|
73
|
+
size="large"
|
|
74
|
+
disabled
|
|
75
|
+
placeholder={t("Enter your email")}
|
|
76
|
+
className="email"
|
|
77
|
+
onPressEnter={loginHandle}
|
|
78
|
+
/>
|
|
79
|
+
</Form.Item>
|
|
80
|
+
<Form.Item
|
|
81
|
+
required
|
|
82
|
+
name="password"
|
|
83
|
+
label={t("Password")}
|
|
84
|
+
rules={[{
|
|
85
|
+
required: true,
|
|
86
|
+
message: t("errors::password should not be empty")
|
|
87
|
+
}]}
|
|
88
|
+
>
|
|
89
|
+
<Input.Password
|
|
90
|
+
type="password"
|
|
91
|
+
size="large"
|
|
92
|
+
className="password"
|
|
93
|
+
placeholder="••••••••"
|
|
94
|
+
onPressEnter={loginHandle}
|
|
95
|
+
/>
|
|
96
|
+
</Form.Item>
|
|
97
|
+
<Form.Item name="remember" valuePropName="checked" noStyle style={{ width: '100%' }}>
|
|
98
|
+
<div style={{ display: 'flex', width: '100%' }}>
|
|
99
|
+
<div style={{ flex: 1 }}>
|
|
100
|
+
<Checkbox defaultChecked>{t("Remember me")}</Checkbox>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
</Form.Item>
|
|
104
|
+
</Form>
|
|
105
|
+
{formErrors ? renderErrors(formErrors, t) : null}
|
|
106
|
+
<div className="buttons">
|
|
107
|
+
<BorderedButton onClick={loginHandle} type="primary" block className="normal-br mt-4">
|
|
108
|
+
{loggingIn ? t("Logging-in") : t('Log in')}
|
|
109
|
+
</BorderedButton>
|
|
110
|
+
</div>
|
|
111
|
+
</Style>
|
|
112
|
+
</Modal>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export default LoginPopup;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import styled from 'styled-components';
|
|
2
|
+
|
|
3
|
+
export default styled.div`
|
|
4
|
+
&.popup {
|
|
5
|
+
h2 {
|
|
6
|
+
margin-bottom: 8px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
p {
|
|
10
|
+
color: #667085;
|
|
11
|
+
margin-bottom: 20px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.ant-form-item-label {
|
|
15
|
+
padding-bottom: 6px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.buttons {
|
|
19
|
+
margin-top: 24px;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.errors-cont {
|
|
23
|
+
margin-top: 8px;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
`;
|