ptechcore_ui 1.0.1 → 1.0.3
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/index.cjs +1396 -0
- package/dist/index.d.cts +62 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.js +1366 -0
- package/package.json +14 -1
- package/eslint.config.js +0 -28
- package/index.html +0 -78
- package/postcss.config.js +0 -6
- package/src/App.tsx +0 -156
- package/src/assets/imgs/login_illustration.png +0 -0
- package/src/components/common/Buttons.tsx +0 -39
- package/src/components/common/Cards.tsx +0 -18
- package/src/components/common/FDrawer.tsx +0 -2448
- package/src/components/common/FDrawer.types.ts +0 -191
- package/src/components/common/Inputs.tsx +0 -409
- package/src/components/common/Modals.tsx +0 -41
- package/src/components/common/Navigations.tsx +0 -0
- package/src/components/common/Toast.tsx +0 -0
- package/src/components/demo/ToastDemo.tsx +0 -73
- package/src/components/layout/Header.tsx +0 -202
- package/src/components/layout/ModernDoubleSidebarLayout.tsx +0 -719
- package/src/components/layout/PrivateLayout.tsx +0 -52
- package/src/components/layout/Sidebar.tsx +0 -182
- package/src/components/ui/Toast.tsx +0 -93
- package/src/contexts/SessionContext.tsx +0 -77
- package/src/contexts/ThemeContext.tsx +0 -58
- package/src/contexts/ToastContext.tsx +0 -94
- package/src/index.css +0 -3
- package/src/index.ts +0 -10
- package/src/main.tsx +0 -10
- package/src/models/Organization.ts +0 -47
- package/src/models/Plan.ts +0 -42
- package/src/models/User.ts +0 -23
- package/src/pages/Analytics.tsx +0 -101
- package/src/pages/CreateOrganization.tsx +0 -215
- package/src/pages/Dashboard.tsx +0 -15
- package/src/pages/Home.tsx +0 -12
- package/src/pages/Profile.tsx +0 -313
- package/src/pages/Settings.tsx +0 -382
- package/src/pages/Team.tsx +0 -180
- package/src/pages/auth/Login.tsx +0 -140
- package/src/pages/auth/Register.tsx +0 -302
- package/src/pages/organizations/DetailEntity.tsx +0 -1002
- package/src/pages/organizations/DetailOrganizations.tsx +0 -1628
- package/src/pages/organizations/ListOrganizations.tsx +0 -270
- package/src/pages/pricings/CartPlan.tsx +0 -486
- package/src/pages/pricings/ListPricing.tsx +0 -321
- package/src/pages/users/CreateUser.tsx +0 -448
- package/src/pages/users/ListUsers.tsx +0 -0
- package/src/services/AuthServices.ts +0 -94
- package/src/services/OrganizationServices.ts +0 -61
- package/src/services/PlanSubscriptionServices.tsx +0 -137
- package/src/services/UserServices.ts +0 -36
- package/src/services/api.ts +0 -64
- package/src/styles/theme.ts +0 -383
- package/src/utils/utils.ts +0 -48
- package/src/vite-env.d.ts +0 -1
- package/tailwind.config.js +0 -158
- package/tsconfig.app.json +0 -24
- package/tsconfig.json +0 -31
- package/tsconfig.node.json +0 -22
- package/vite.config.ts +0 -10
package/dist/index.js
ADDED
|
@@ -0,0 +1,1366 @@
|
|
|
1
|
+
// src/components/common/Buttons.tsx
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
var PrimaryButton = ({
|
|
4
|
+
loading = false,
|
|
5
|
+
children,
|
|
6
|
+
classname = "",
|
|
7
|
+
...props
|
|
8
|
+
}) => /* @__PURE__ */ jsx(
|
|
9
|
+
"button",
|
|
10
|
+
{
|
|
11
|
+
type: "submit",
|
|
12
|
+
disabled: loading || props.disabled,
|
|
13
|
+
className: `px-4 py-2 text-sm bg-[#6A8A82] text-white rounded-lg hover:bg-[#5A7A72] transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex justify-center items-center ${classname}`,
|
|
14
|
+
...props,
|
|
15
|
+
children: loading ? "Connexion en cours..." : children
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
var SecondaryButton = ({
|
|
19
|
+
loading = false,
|
|
20
|
+
children,
|
|
21
|
+
...props
|
|
22
|
+
}) => /* @__PURE__ */ jsx(
|
|
23
|
+
"button",
|
|
24
|
+
{
|
|
25
|
+
type: "button",
|
|
26
|
+
disabled: loading || props.disabled,
|
|
27
|
+
className: "px-4 py-2 bg-[#B87333] text-white rounded-lg hover:bg-[#A66B2A] transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center",
|
|
28
|
+
...props,
|
|
29
|
+
children: loading ? "Connexion en cours..." : children
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
var Buttons_default = PrimaryButton;
|
|
33
|
+
|
|
34
|
+
// src/components/layout/ModernDoubleSidebarLayout.tsx
|
|
35
|
+
import React2, { useState as useState2, useEffect as useEffect2 } from "react";
|
|
36
|
+
import { useLocation, useNavigate } from "react-router-dom";
|
|
37
|
+
import {
|
|
38
|
+
Settings,
|
|
39
|
+
ChevronLeft,
|
|
40
|
+
ChevronRight,
|
|
41
|
+
Search,
|
|
42
|
+
Bell,
|
|
43
|
+
User,
|
|
44
|
+
LogOut,
|
|
45
|
+
Menu,
|
|
46
|
+
X,
|
|
47
|
+
Palette,
|
|
48
|
+
DollarSign,
|
|
49
|
+
HelpCircle
|
|
50
|
+
} from "lucide-react";
|
|
51
|
+
|
|
52
|
+
// src/utils/utils.ts
|
|
53
|
+
import { clsx } from "clsx";
|
|
54
|
+
import { twMerge } from "tailwind-merge";
|
|
55
|
+
function cn(...inputs) {
|
|
56
|
+
return twMerge(clsx(inputs));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/contexts/ThemeContext.tsx
|
|
60
|
+
import { createContext, useContext, useState, useEffect } from "react";
|
|
61
|
+
|
|
62
|
+
// src/styles/theme.ts
|
|
63
|
+
var elegantTheme = {
|
|
64
|
+
name: "\xC9l\xE9gance Sobre",
|
|
65
|
+
description: "Finance traditionnelle moderne - s\xE9rieux, luxe discret, rassurant",
|
|
66
|
+
colors: {
|
|
67
|
+
primary: "#2E7D69",
|
|
68
|
+
// Vert émeraude
|
|
69
|
+
primaryHover: "#246456",
|
|
70
|
+
primaryLight: "rgba(46, 125, 105, 0.1)",
|
|
71
|
+
secondary: "#D4AF37",
|
|
72
|
+
// Or pâle
|
|
73
|
+
accent: "#D4AF37",
|
|
74
|
+
background: "#F5F5F7",
|
|
75
|
+
// Gris clair neutre
|
|
76
|
+
surface: "#FFFFFF",
|
|
77
|
+
surfaceHover: "#FAFAFA",
|
|
78
|
+
text: {
|
|
79
|
+
primary: "#1E1E2F",
|
|
80
|
+
// Charbon profond
|
|
81
|
+
secondary: "#4A4A5C",
|
|
82
|
+
tertiary: "#C2C7CE",
|
|
83
|
+
// Gris moyen
|
|
84
|
+
inverse: "#FFFFFF"
|
|
85
|
+
},
|
|
86
|
+
border: "#E5E5E7",
|
|
87
|
+
borderLight: "#F0F0F2",
|
|
88
|
+
success: "#2E7D69",
|
|
89
|
+
successLight: "rgba(46, 125, 105, 0.1)",
|
|
90
|
+
error: "#DC3545",
|
|
91
|
+
errorLight: "rgba(220, 53, 69, 0.1)",
|
|
92
|
+
warning: "#D4AF37",
|
|
93
|
+
warningLight: "rgba(212, 175, 55, 0.1)",
|
|
94
|
+
info: "#5B9BD5",
|
|
95
|
+
infoLight: "rgba(91, 155, 213, 0.1)",
|
|
96
|
+
sidebar: {
|
|
97
|
+
bg: "#1E1E2F",
|
|
98
|
+
bgHover: "#252538",
|
|
99
|
+
text: "#C2C7CE",
|
|
100
|
+
textHover: "#FFFFFF",
|
|
101
|
+
border: "rgba(194, 199, 206, 0.1)",
|
|
102
|
+
active: "#2E7D69",
|
|
103
|
+
activeBg: "rgba(46, 125, 105, 0.1)"
|
|
104
|
+
},
|
|
105
|
+
card: {
|
|
106
|
+
bg: "#FFFFFF",
|
|
107
|
+
border: "#E5E5E7",
|
|
108
|
+
shadow: "rgba(30, 30, 47, 0.05)"
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
shadows: {
|
|
112
|
+
sm: "0 1px 3px rgba(30, 30, 47, 0.05)",
|
|
113
|
+
md: "0 4px 6px rgba(30, 30, 47, 0.07)",
|
|
114
|
+
lg: "0 10px 15px rgba(30, 30, 47, 0.1)",
|
|
115
|
+
xl: "0 20px 25px rgba(30, 30, 47, 0.12)"
|
|
116
|
+
},
|
|
117
|
+
transitions: {
|
|
118
|
+
fast: "150ms ease",
|
|
119
|
+
normal: "250ms ease",
|
|
120
|
+
slow: "350ms ease"
|
|
121
|
+
},
|
|
122
|
+
borderRadius: {
|
|
123
|
+
sm: "4px",
|
|
124
|
+
md: "8px",
|
|
125
|
+
lg: "12px",
|
|
126
|
+
xl: "16px",
|
|
127
|
+
full: "9999px"
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var fintechTheme = {
|
|
131
|
+
name: "Modern Fintech",
|
|
132
|
+
description: "Moderne, clair, orient\xE9 tableau de bord financier",
|
|
133
|
+
colors: {
|
|
134
|
+
primary: "#27AE60",
|
|
135
|
+
// Vert doux
|
|
136
|
+
primaryHover: "#219A52",
|
|
137
|
+
primaryLight: "rgba(39, 174, 96, 0.1)",
|
|
138
|
+
secondary: "#2C3E50",
|
|
139
|
+
// Bleu nuit désaturé
|
|
140
|
+
accent: "#3498DB",
|
|
141
|
+
background: "#FAFAFA",
|
|
142
|
+
// Blanc cassé
|
|
143
|
+
surface: "#FFFFFF",
|
|
144
|
+
surfaceHover: "#F8F9FA",
|
|
145
|
+
text: {
|
|
146
|
+
primary: "#2C3E50",
|
|
147
|
+
secondary: "#7F8C8D",
|
|
148
|
+
// Gris ardoise
|
|
149
|
+
tertiary: "#95A5A6",
|
|
150
|
+
inverse: "#FFFFFF"
|
|
151
|
+
},
|
|
152
|
+
border: "#E0E6ED",
|
|
153
|
+
borderLight: "#F1F4F7",
|
|
154
|
+
success: "#27AE60",
|
|
155
|
+
successLight: "rgba(39, 174, 96, 0.1)",
|
|
156
|
+
error: "#C0392B",
|
|
157
|
+
// Rouge bourgogne
|
|
158
|
+
errorLight: "rgba(192, 57, 43, 0.1)",
|
|
159
|
+
warning: "#F39C12",
|
|
160
|
+
warningLight: "rgba(243, 156, 18, 0.1)",
|
|
161
|
+
info: "#3498DB",
|
|
162
|
+
infoLight: "rgba(52, 152, 219, 0.1)",
|
|
163
|
+
sidebar: {
|
|
164
|
+
bg: "#2C3E50",
|
|
165
|
+
bgHover: "#34495E",
|
|
166
|
+
text: "#95A5A6",
|
|
167
|
+
textHover: "#FFFFFF",
|
|
168
|
+
border: "rgba(149, 165, 166, 0.1)",
|
|
169
|
+
active: "#27AE60",
|
|
170
|
+
activeBg: "rgba(39, 174, 96, 0.1)"
|
|
171
|
+
},
|
|
172
|
+
card: {
|
|
173
|
+
bg: "#FFFFFF",
|
|
174
|
+
border: "#E0E6ED",
|
|
175
|
+
shadow: "rgba(44, 62, 80, 0.04)"
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
shadows: {
|
|
179
|
+
sm: "0 1px 3px rgba(44, 62, 80, 0.04)",
|
|
180
|
+
md: "0 4px 6px rgba(44, 62, 80, 0.06)",
|
|
181
|
+
lg: "0 10px 15px rgba(44, 62, 80, 0.08)",
|
|
182
|
+
xl: "0 20px 25px rgba(44, 62, 80, 0.1)"
|
|
183
|
+
},
|
|
184
|
+
transitions: {
|
|
185
|
+
fast: "150ms ease",
|
|
186
|
+
normal: "250ms ease",
|
|
187
|
+
slow: "350ms ease"
|
|
188
|
+
},
|
|
189
|
+
borderRadius: {
|
|
190
|
+
sm: "4px",
|
|
191
|
+
md: "8px",
|
|
192
|
+
lg: "12px",
|
|
193
|
+
xl: "16px",
|
|
194
|
+
full: "9999px"
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
var minimalistTheme = {
|
|
198
|
+
name: "Minimaliste Premium",
|
|
199
|
+
description: "\xC9l\xE9gance minimaliste avec touche premium",
|
|
200
|
+
colors: {
|
|
201
|
+
primary: "#6A8A82",
|
|
202
|
+
// Vert sauge
|
|
203
|
+
primaryHover: "#5A7A72",
|
|
204
|
+
primaryLight: "rgba(106, 138, 130, 0.1)",
|
|
205
|
+
secondary: "#B87333",
|
|
206
|
+
// Cuivre rosé
|
|
207
|
+
accent: "#B87333",
|
|
208
|
+
background: "#ECECEC",
|
|
209
|
+
// Gris clair perle
|
|
210
|
+
surface: "#FFFFFF",
|
|
211
|
+
surfaceHover: "#FAFAFA",
|
|
212
|
+
text: {
|
|
213
|
+
primary: "#191919",
|
|
214
|
+
// Noir fumé
|
|
215
|
+
secondary: "#444444",
|
|
216
|
+
// Anthracite doux
|
|
217
|
+
tertiary: "#767676",
|
|
218
|
+
inverse: "#FFFFFF"
|
|
219
|
+
},
|
|
220
|
+
border: "#D9D9D9",
|
|
221
|
+
borderLight: "#E8E8E8",
|
|
222
|
+
success: "#6A8A82",
|
|
223
|
+
successLight: "rgba(106, 138, 130, 0.1)",
|
|
224
|
+
error: "#B85450",
|
|
225
|
+
errorLight: "rgba(184, 84, 80, 0.1)",
|
|
226
|
+
warning: "#B87333",
|
|
227
|
+
warningLight: "rgba(184, 115, 51, 0.1)",
|
|
228
|
+
info: "#7A99AC",
|
|
229
|
+
infoLight: "rgba(122, 153, 172, 0.1)",
|
|
230
|
+
sidebar: {
|
|
231
|
+
bg: "#191919",
|
|
232
|
+
bgHover: "#242424",
|
|
233
|
+
text: "#999999",
|
|
234
|
+
textHover: "#FFFFFF",
|
|
235
|
+
border: "rgba(153, 153, 153, 0.1)",
|
|
236
|
+
active: "#B87333",
|
|
237
|
+
activeBg: "rgba(184, 115, 51, 0.1)"
|
|
238
|
+
},
|
|
239
|
+
card: {
|
|
240
|
+
bg: "#FFFFFF",
|
|
241
|
+
border: "#D9D9D9",
|
|
242
|
+
shadow: "rgba(25, 25, 25, 0.03)"
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
shadows: {
|
|
246
|
+
sm: "0 1px 3px rgba(25, 25, 25, 0.03)",
|
|
247
|
+
md: "0 4px 6px rgba(25, 25, 25, 0.05)",
|
|
248
|
+
lg: "0 10px 15px rgba(25, 25, 25, 0.07)",
|
|
249
|
+
xl: "0 20px 25px rgba(25, 25, 25, 0.09)"
|
|
250
|
+
},
|
|
251
|
+
transitions: {
|
|
252
|
+
fast: "150ms ease",
|
|
253
|
+
normal: "250ms ease",
|
|
254
|
+
slow: "350ms ease"
|
|
255
|
+
},
|
|
256
|
+
borderRadius: {
|
|
257
|
+
sm: "4px",
|
|
258
|
+
md: "8px",
|
|
259
|
+
lg: "12px",
|
|
260
|
+
xl: "16px",
|
|
261
|
+
full: "9999px"
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
var neutralOdysseyTheme = {
|
|
265
|
+
name: "Neutral Odyssey",
|
|
266
|
+
description: "Palette haut de gamme pour immobilier - \xE9l\xE9gance neutre et moderne",
|
|
267
|
+
colors: {
|
|
268
|
+
primary: "#373B4D",
|
|
269
|
+
// Gris profond, élégant - Actions fortes
|
|
270
|
+
primaryHover: "#2C2F3D",
|
|
271
|
+
// Version plus sombre pour hover
|
|
272
|
+
primaryLight: "rgba(55, 59, 77, 0.1)",
|
|
273
|
+
secondary: "#BDBFB7",
|
|
274
|
+
// Accents - éléments surlignés, cartes de projet
|
|
275
|
+
accent: "#BDBFB7",
|
|
276
|
+
background: "#ECEDEF",
|
|
277
|
+
// Fond clair principal
|
|
278
|
+
surface: "#ECECEF",
|
|
279
|
+
// Surface des cartes et panneaux
|
|
280
|
+
surfaceHover: "#E6E6E9",
|
|
281
|
+
text: {
|
|
282
|
+
primary: "#373B4D",
|
|
283
|
+
// Texte principal sur fond clair
|
|
284
|
+
secondary: "#949597",
|
|
285
|
+
// Texte secondaire / icônes
|
|
286
|
+
tertiary: "#BDBFB7",
|
|
287
|
+
// Texte tertiaire
|
|
288
|
+
inverse: "#ECECEF"
|
|
289
|
+
// Texte sur fond sombre
|
|
290
|
+
},
|
|
291
|
+
border: "#BDBFB7",
|
|
292
|
+
// Bordures principales
|
|
293
|
+
borderLight: "#E0E0E3",
|
|
294
|
+
// Bordures légères
|
|
295
|
+
success: "#6A8A82",
|
|
296
|
+
// Réutilisation du vert sauge pour succès
|
|
297
|
+
successLight: "rgba(106, 138, 130, 0.1)",
|
|
298
|
+
error: "#B85450",
|
|
299
|
+
errorLight: "rgba(184, 84, 80, 0.1)",
|
|
300
|
+
warning: "#D4AF37",
|
|
301
|
+
// Or pour les avertissements
|
|
302
|
+
warningLight: "rgba(212, 175, 55, 0.1)",
|
|
303
|
+
info: "#7A99AC",
|
|
304
|
+
infoLight: "rgba(122, 153, 172, 0.1)",
|
|
305
|
+
sidebar: {
|
|
306
|
+
bg: "linear-gradient(180deg, #ECECEF 0%, #ECEDEF 100%)",
|
|
307
|
+
// Dégradé vertical
|
|
308
|
+
bgHover: "#E6E6E9",
|
|
309
|
+
text: "#373B4D",
|
|
310
|
+
// Icônes et texte en gris profond
|
|
311
|
+
textHover: "#2C2F3D",
|
|
312
|
+
// Plus sombre au hover
|
|
313
|
+
border: "rgba(189, 191, 183, 0.2)",
|
|
314
|
+
active: "#373B4D",
|
|
315
|
+
// État actif en couleur principale
|
|
316
|
+
activeBg: "rgba(55, 59, 77, 0.1)"
|
|
317
|
+
},
|
|
318
|
+
card: {
|
|
319
|
+
bg: "#ECEDEF",
|
|
320
|
+
// Cartes sur fond légèrement différent
|
|
321
|
+
border: "#BDBFB7",
|
|
322
|
+
// Encadrement des cartes
|
|
323
|
+
shadow: "rgba(55, 59, 77, 0.08)"
|
|
324
|
+
}
|
|
325
|
+
},
|
|
326
|
+
shadows: {
|
|
327
|
+
sm: "0 1px 3px rgba(55, 59, 77, 0.08)",
|
|
328
|
+
md: "0 4px 6px rgba(55, 59, 77, 0.10)",
|
|
329
|
+
lg: "0 10px 15px rgba(55, 59, 77, 0.12)",
|
|
330
|
+
xl: "0 20px 25px rgba(55, 59, 77, 0.15)"
|
|
331
|
+
},
|
|
332
|
+
transitions: {
|
|
333
|
+
fast: "150ms ease",
|
|
334
|
+
normal: "250ms ease",
|
|
335
|
+
slow: "350ms ease"
|
|
336
|
+
},
|
|
337
|
+
borderRadius: {
|
|
338
|
+
sm: "4px",
|
|
339
|
+
md: "8px",
|
|
340
|
+
lg: "12px",
|
|
341
|
+
xl: "16px",
|
|
342
|
+
full: "9999px"
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
var themes = {
|
|
346
|
+
elegant: elegantTheme,
|
|
347
|
+
fintech: fintechTheme,
|
|
348
|
+
minimalist: minimalistTheme,
|
|
349
|
+
neutralOdyssey: neutralOdysseyTheme
|
|
350
|
+
};
|
|
351
|
+
var defaultTheme = minimalistTheme;
|
|
352
|
+
var getThemeCSSVariables = (theme) => {
|
|
353
|
+
return {
|
|
354
|
+
"--color-primary": theme.colors.primary,
|
|
355
|
+
"--color-primary-hover": theme.colors.primaryHover,
|
|
356
|
+
"--color-primary-light": theme.colors.primaryLight,
|
|
357
|
+
"--color-secondary": theme.colors.secondary,
|
|
358
|
+
"--color-accent": theme.colors.accent,
|
|
359
|
+
"--color-background": theme.colors.background,
|
|
360
|
+
"--color-surface": theme.colors.surface,
|
|
361
|
+
"--color-surface-hover": theme.colors.surfaceHover,
|
|
362
|
+
"--color-text-primary": theme.colors.text.primary,
|
|
363
|
+
"--color-text-secondary": theme.colors.text.secondary,
|
|
364
|
+
"--color-text-tertiary": theme.colors.text.tertiary,
|
|
365
|
+
"--color-text-inverse": theme.colors.text.inverse,
|
|
366
|
+
"--color-border": theme.colors.border,
|
|
367
|
+
"--color-border-light": theme.colors.borderLight,
|
|
368
|
+
"--color-success": theme.colors.success,
|
|
369
|
+
"--color-success-light": theme.colors.successLight,
|
|
370
|
+
"--color-error": theme.colors.error,
|
|
371
|
+
"--color-error-light": theme.colors.errorLight,
|
|
372
|
+
"--color-warning": theme.colors.warning,
|
|
373
|
+
"--color-warning-light": theme.colors.warningLight,
|
|
374
|
+
"--color-info": theme.colors.info,
|
|
375
|
+
"--color-info-light": theme.colors.infoLight,
|
|
376
|
+
"--shadow-sm": theme.shadows.sm,
|
|
377
|
+
"--shadow-md": theme.shadows.md,
|
|
378
|
+
"--shadow-lg": theme.shadows.lg,
|
|
379
|
+
"--shadow-xl": theme.shadows.xl,
|
|
380
|
+
"--transition-fast": theme.transitions.fast,
|
|
381
|
+
"--transition-normal": theme.transitions.normal,
|
|
382
|
+
"--transition-slow": theme.transitions.slow,
|
|
383
|
+
"--radius-sm": theme.borderRadius.sm,
|
|
384
|
+
"--radius-md": theme.borderRadius.md,
|
|
385
|
+
"--radius-lg": theme.borderRadius.lg,
|
|
386
|
+
"--radius-xl": theme.borderRadius.xl,
|
|
387
|
+
"--radius-full": theme.borderRadius.full
|
|
388
|
+
};
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
// src/contexts/ThemeContext.tsx
|
|
392
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
393
|
+
var ThemeContext = createContext(void 0);
|
|
394
|
+
var useTheme = () => {
|
|
395
|
+
const context = useContext(ThemeContext);
|
|
396
|
+
if (!context) {
|
|
397
|
+
throw new Error("useTheme must be used within a ThemeProvider");
|
|
398
|
+
}
|
|
399
|
+
return context;
|
|
400
|
+
};
|
|
401
|
+
var ThemeProvider = ({ children }) => {
|
|
402
|
+
const [themeType, setThemeType] = useState(() => {
|
|
403
|
+
const saved = localStorage.getItem("wisebook-theme");
|
|
404
|
+
return saved && saved in themes ? saved : "minimalist";
|
|
405
|
+
});
|
|
406
|
+
const [theme, setThemeState] = useState(themes[themeType] || defaultTheme);
|
|
407
|
+
useEffect(() => {
|
|
408
|
+
const root = document.documentElement;
|
|
409
|
+
const cssVars = getThemeCSSVariables(theme);
|
|
410
|
+
Object.entries(cssVars).forEach(([key, value]) => {
|
|
411
|
+
root.style.setProperty(key, value);
|
|
412
|
+
});
|
|
413
|
+
root.style.backgroundColor = theme.colors.background;
|
|
414
|
+
root.style.color = theme.colors.text.primary;
|
|
415
|
+
localStorage.setItem("wisebook-theme", themeType);
|
|
416
|
+
}, [theme, themeType]);
|
|
417
|
+
const setTheme = (type) => {
|
|
418
|
+
if (type in themes) {
|
|
419
|
+
setThemeType(type);
|
|
420
|
+
setThemeState(themes[type]);
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
return /* @__PURE__ */ jsx2(ThemeContext.Provider, { value: { theme, themeType, setTheme }, children });
|
|
424
|
+
};
|
|
425
|
+
var ThemeContext_default = ThemeProvider;
|
|
426
|
+
|
|
427
|
+
// src/components/layout/ModernDoubleSidebarLayout.tsx
|
|
428
|
+
import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
429
|
+
var RewiseLayout = ({ children, module_name = "Rewise", module_description = "Description du module", primaryMenuItems, secondaryMenuItems }) => {
|
|
430
|
+
const location = useLocation();
|
|
431
|
+
const navigate = useNavigate();
|
|
432
|
+
const { theme, themeType, setTheme } = useTheme();
|
|
433
|
+
const [primaryCollapsed, setPrimaryCollapsed] = useState2(false);
|
|
434
|
+
const [secondaryCollapsed, setSecondaryCollapsed] = useState2(false);
|
|
435
|
+
const [mobileMenuOpen, setMobileMenuOpen] = useState2(false);
|
|
436
|
+
const [selectedModule, setSelectedModule] = useState2("dashboard");
|
|
437
|
+
const [searchQuery, setSearchQuery] = useState2("");
|
|
438
|
+
const [showNotifications, setShowNotifications] = useState2(false);
|
|
439
|
+
const [showUserMenu, setShowUserMenu] = useState2(false);
|
|
440
|
+
const [showThemeMenu, setShowThemeMenu] = useState2(false);
|
|
441
|
+
const [notifications, setNotifications] = useState2([
|
|
442
|
+
{
|
|
443
|
+
id: "1",
|
|
444
|
+
title: "Nouvelle facture",
|
|
445
|
+
message: "3 nouvelles factures en attente de validation",
|
|
446
|
+
type: "info",
|
|
447
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
448
|
+
read: false
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
id: "2",
|
|
452
|
+
title: "Cl\xF4ture mensuelle",
|
|
453
|
+
message: "La cl\xF4ture de janvier est pr\xEAte",
|
|
454
|
+
type: "success",
|
|
455
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
456
|
+
read: false
|
|
457
|
+
}
|
|
458
|
+
]);
|
|
459
|
+
useEffect2(() => {
|
|
460
|
+
const handleKeyDown = (e) => {
|
|
461
|
+
if (e.altKey && e.key === "m") {
|
|
462
|
+
e.preventDefault();
|
|
463
|
+
setMobileMenuOpen((prev) => !prev);
|
|
464
|
+
}
|
|
465
|
+
if (e.altKey && e.key === "s") {
|
|
466
|
+
e.preventDefault();
|
|
467
|
+
document.getElementById("global-search")?.focus();
|
|
468
|
+
}
|
|
469
|
+
if (e.key === "Escape") {
|
|
470
|
+
setShowNotifications(false);
|
|
471
|
+
setShowUserMenu(false);
|
|
472
|
+
setShowThemeMenu(false);
|
|
473
|
+
setMobileMenuOpen(false);
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
477
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
478
|
+
}, []);
|
|
479
|
+
useEffect2(() => {
|
|
480
|
+
const path = location.pathname;
|
|
481
|
+
const moduleMatch = path.match(/^\/([^/]+)/);
|
|
482
|
+
if (moduleMatch) {
|
|
483
|
+
const moduleId = moduleMatch[1];
|
|
484
|
+
const routeMapping = {
|
|
485
|
+
"dashboard": "dashboard",
|
|
486
|
+
"organizations": "organizations",
|
|
487
|
+
"entities": "entities"
|
|
488
|
+
};
|
|
489
|
+
setSelectedModule(routeMapping[moduleId] || "dashboard");
|
|
490
|
+
}
|
|
491
|
+
}, [location]);
|
|
492
|
+
const handleThemeChange = (type) => {
|
|
493
|
+
setTheme(type);
|
|
494
|
+
setShowThemeMenu(false);
|
|
495
|
+
};
|
|
496
|
+
const isActive = (path) => location.pathname === path;
|
|
497
|
+
const isModuleActive = (moduleId) => selectedModule === moduleId;
|
|
498
|
+
const getBreadcrumbs = () => {
|
|
499
|
+
const paths = location.pathname.split("/").filter(Boolean);
|
|
500
|
+
const breadcrumbs = [{ label: "Accueil", path: "/" }];
|
|
501
|
+
paths.forEach((path, index) => {
|
|
502
|
+
const fullPath = "/" + paths.slice(0, index + 1).join("/");
|
|
503
|
+
const module = primaryMenuItems.find((m) => m.id === path);
|
|
504
|
+
const label = module ? module.label : path.charAt(0).toUpperCase() + path.slice(1);
|
|
505
|
+
breadcrumbs.push({ label, path: fullPath });
|
|
506
|
+
});
|
|
507
|
+
return breadcrumbs;
|
|
508
|
+
};
|
|
509
|
+
const markNotificationAsRead = (id) => {
|
|
510
|
+
setNotifications(
|
|
511
|
+
(prev) => prev.map((n) => n.id === id ? { ...n, read: true } : n)
|
|
512
|
+
);
|
|
513
|
+
};
|
|
514
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex h-screen bg-[var(--color-background)] overflow-hidden", children: [
|
|
515
|
+
/* @__PURE__ */ jsx3(
|
|
516
|
+
"a",
|
|
517
|
+
{
|
|
518
|
+
href: "#main-content",
|
|
519
|
+
className: "sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 z-50 bg-[var(--color-primary)] text-[var(--color-background)] px-4 py-2 rounded",
|
|
520
|
+
children: "Aller au contenu principal"
|
|
521
|
+
}
|
|
522
|
+
),
|
|
523
|
+
/* @__PURE__ */ jsxs(
|
|
524
|
+
"aside",
|
|
525
|
+
{
|
|
526
|
+
className: cn(
|
|
527
|
+
"hidden lg:flex flex-col bg-[var(--color-sidebar-bg)] transition-all duration-300",
|
|
528
|
+
primaryCollapsed ? "w-20" : "w-64"
|
|
529
|
+
),
|
|
530
|
+
role: "navigation",
|
|
531
|
+
"aria-label": "Navigation principale",
|
|
532
|
+
children: [
|
|
533
|
+
/* @__PURE__ */ jsxs("div", { className: "h-16 flex items-center justify-between px-4 border-b border-[var(--color-sidebar-border)]", children: [
|
|
534
|
+
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
535
|
+
"flex items-center gap-3",
|
|
536
|
+
primaryCollapsed && "justify-center"
|
|
537
|
+
), children: [
|
|
538
|
+
/* @__PURE__ */ jsx3("div", { className: "w-10 h-10 bg-[var(--color-primary)] rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsx3("span", { className: "text-[var(--color-background)] font-bold text-xl", children: "W" }) }),
|
|
539
|
+
!primaryCollapsed && /* @__PURE__ */ jsxs("div", { children: [
|
|
540
|
+
/* @__PURE__ */ jsx3("h1", { className: "text-[var(--color-sidebar-text)] font-bold text-lg", children: module_name }),
|
|
541
|
+
/* @__PURE__ */ jsx3("p", { className: "text-[var(--color-sidebar-text-secondary)] text-xs", children: module_description })
|
|
542
|
+
] })
|
|
543
|
+
] }),
|
|
544
|
+
/* @__PURE__ */ jsx3(
|
|
545
|
+
"button",
|
|
546
|
+
{
|
|
547
|
+
onClick: () => setPrimaryCollapsed(!primaryCollapsed),
|
|
548
|
+
className: "text-[var(--color-sidebar-text-secondary)] hover:text-[var(--color-sidebar-text)] transition-colors",
|
|
549
|
+
"aria-label": primaryCollapsed ? "D\xE9velopper le menu" : "R\xE9duire le menu",
|
|
550
|
+
"aria-expanded": !primaryCollapsed,
|
|
551
|
+
children: /* @__PURE__ */ jsx3(ChevronLeft, { className: cn(
|
|
552
|
+
"w-5 h-5 transition-transform",
|
|
553
|
+
primaryCollapsed && "rotate-180"
|
|
554
|
+
) })
|
|
555
|
+
}
|
|
556
|
+
)
|
|
557
|
+
] }),
|
|
558
|
+
/* @__PURE__ */ jsx3(
|
|
559
|
+
"nav",
|
|
560
|
+
{
|
|
561
|
+
className: "flex-1 py-4 overflow-y-auto",
|
|
562
|
+
role: "menubar",
|
|
563
|
+
"aria-label": "Modules principaux",
|
|
564
|
+
children: primaryMenuItems.map((item) => /* @__PURE__ */ jsxs(
|
|
565
|
+
"button",
|
|
566
|
+
{
|
|
567
|
+
onClick: () => {
|
|
568
|
+
if (item.path) {
|
|
569
|
+
navigate(item.path);
|
|
570
|
+
} else {
|
|
571
|
+
setSelectedModule(item.id);
|
|
572
|
+
}
|
|
573
|
+
},
|
|
574
|
+
className: cn(
|
|
575
|
+
"w-full flex items-center gap-3 px-4 py-3 transition-all duration-200",
|
|
576
|
+
"hover:bg-[var(--color-sidebar-hover)] relative group",
|
|
577
|
+
isModuleActive(item.id) && "bg-[var(--color-sidebar-active)] border-l-4 border-[var(--color-primary)]",
|
|
578
|
+
primaryCollapsed && "justify-center"
|
|
579
|
+
),
|
|
580
|
+
role: "menuitem",
|
|
581
|
+
"aria-label": item.ariaLabel || item.label,
|
|
582
|
+
"aria-current": isModuleActive(item.id) ? "page" : void 0,
|
|
583
|
+
children: [
|
|
584
|
+
/* @__PURE__ */ jsx3("div", { className: cn(
|
|
585
|
+
"transition-colors",
|
|
586
|
+
isModuleActive(item.id) ? "text-[var(--color-primary)]" : "text-[var(--color-sidebar-text-secondary)] group-hover:text-[var(--color-sidebar-text)]"
|
|
587
|
+
), children: item.icon }),
|
|
588
|
+
!primaryCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
589
|
+
/* @__PURE__ */ jsx3("span", { className: cn(
|
|
590
|
+
"flex-1 text-left text-sm font-medium transition-colors",
|
|
591
|
+
isModuleActive(item.id) ? "text-[var(--color-sidebar-text)]" : "text-[var(--color-sidebar-text-secondary)] group-hover:text-[var(--color-sidebar-text)]"
|
|
592
|
+
), children: item.label }),
|
|
593
|
+
item.badge && /* @__PURE__ */ jsx3("span", { className: "px-2 py-0.5 text-xs bg-[var(--color-primary)] text-[var(--color-background)] rounded-full", children: item.badge })
|
|
594
|
+
] }),
|
|
595
|
+
primaryCollapsed && /* @__PURE__ */ jsx3("div", { className: "absolute left-full ml-2 px-2 py-1 bg-[var(--color-sidebar-active)] text-[var(--color-sidebar-text)] text-xs rounded opacity-0 group-hover:opacity-100 pointer-events-none whitespace-nowrap z-50", children: item.label })
|
|
596
|
+
]
|
|
597
|
+
},
|
|
598
|
+
item.id
|
|
599
|
+
))
|
|
600
|
+
}
|
|
601
|
+
),
|
|
602
|
+
/* @__PURE__ */ jsx3("div", { className: "p-4 border-t border-[var(--color-sidebar-border)]", children: /* @__PURE__ */ jsxs("div", { className: cn(
|
|
603
|
+
"flex items-center gap-3",
|
|
604
|
+
primaryCollapsed && "justify-center"
|
|
605
|
+
), children: [
|
|
606
|
+
/* @__PURE__ */ jsx3("div", { className: "w-10 h-10 bg-[var(--color-sidebar-avatar-bg)] rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx3(User, { className: "w-5 h-5 text-[var(--color-sidebar-text-secondary)]" }) }),
|
|
607
|
+
!primaryCollapsed && /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
608
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-medium text-[var(--color-sidebar-text)]", children: "Admin" }),
|
|
609
|
+
/* @__PURE__ */ jsx3("p", { className: "text-xs text-[var(--color-sidebar-text-secondary)]", children: "admin@wisebook.com" })
|
|
610
|
+
] })
|
|
611
|
+
] }) })
|
|
612
|
+
]
|
|
613
|
+
}
|
|
614
|
+
),
|
|
615
|
+
secondaryMenuItems[selectedModule] && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
616
|
+
secondaryCollapsed && /* @__PURE__ */ jsx3(
|
|
617
|
+
"button",
|
|
618
|
+
{
|
|
619
|
+
onClick: () => setSecondaryCollapsed(false),
|
|
620
|
+
className: "hidden lg:flex items-center justify-center w-12 h-full bg-[var(--color-background)] border-r border-[var(--color-border)] hover:bg-[var(--color-surface-hover)] transition-colors",
|
|
621
|
+
"aria-label": "Ouvrir le sous-menu",
|
|
622
|
+
children: /* @__PURE__ */ jsx3(ChevronRight, { className: "w-5 h-5 text-[var(--color-text-tertiary)]" })
|
|
623
|
+
}
|
|
624
|
+
),
|
|
625
|
+
/* @__PURE__ */ jsxs(
|
|
626
|
+
"aside",
|
|
627
|
+
{
|
|
628
|
+
className: cn(
|
|
629
|
+
"hidden lg:flex flex-col bg-[var(--color-background)] border-r border-[var(--color-border)] transition-all duration-300",
|
|
630
|
+
secondaryCollapsed ? "w-0 overflow-hidden" : "w-64"
|
|
631
|
+
),
|
|
632
|
+
role: "navigation",
|
|
633
|
+
"aria-label": "Navigation secondaire",
|
|
634
|
+
children: [
|
|
635
|
+
/* @__PURE__ */ jsxs("div", { className: "h-16 flex items-center justify-between px-4 border-b border-[var(--color-border)]", children: [
|
|
636
|
+
/* @__PURE__ */ jsx3("h2", { className: "text-sm font-semibold text-[var(--color-text-secondary)] uppercase tracking-wider whitespace-nowrap", children: primaryMenuItems.find((item) => item.id === selectedModule)?.label }),
|
|
637
|
+
/* @__PURE__ */ jsx3(
|
|
638
|
+
"button",
|
|
639
|
+
{
|
|
640
|
+
onClick: () => setSecondaryCollapsed(!secondaryCollapsed),
|
|
641
|
+
className: "text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)] flex-shrink-0",
|
|
642
|
+
"aria-label": secondaryCollapsed ? "D\xE9velopper le sous-menu" : "R\xE9duire le sous-menu",
|
|
643
|
+
children: /* @__PURE__ */ jsx3(ChevronLeft, { className: cn(
|
|
644
|
+
"w-4 h-4 transition-transform",
|
|
645
|
+
secondaryCollapsed && "rotate-180"
|
|
646
|
+
) })
|
|
647
|
+
}
|
|
648
|
+
)
|
|
649
|
+
] }),
|
|
650
|
+
/* @__PURE__ */ jsx3(
|
|
651
|
+
"nav",
|
|
652
|
+
{
|
|
653
|
+
className: "flex-1 py-4 overflow-y-auto",
|
|
654
|
+
role: "menu",
|
|
655
|
+
"aria-label": "Sous-navigation",
|
|
656
|
+
children: secondaryMenuItems[selectedModule]?.map((item) => /* @__PURE__ */ jsxs(
|
|
657
|
+
"button",
|
|
658
|
+
{
|
|
659
|
+
onClick: () => item.path && navigate(item.path),
|
|
660
|
+
className: cn(
|
|
661
|
+
"w-full flex items-center gap-3 px-4 py-2.5 transition-all duration-200",
|
|
662
|
+
"hover:bg-[var(--color-surface-hover)]",
|
|
663
|
+
isActive(item.path || "") && "bg-[var(--color-primary-light)] border-l-4 border-[var(--color-primary)]"
|
|
664
|
+
),
|
|
665
|
+
role: "menuitem",
|
|
666
|
+
"aria-current": isActive(item.path || "") ? "page" : void 0,
|
|
667
|
+
children: [
|
|
668
|
+
item.icon && /* @__PURE__ */ jsx3("div", { className: cn(
|
|
669
|
+
"transition-colors",
|
|
670
|
+
isActive(item.path || "") ? "text-[var(--color-primary)]" : "text-[var(--color-text-tertiary)]"
|
|
671
|
+
), children: item.icon }),
|
|
672
|
+
/* @__PURE__ */ jsx3("span", { className: cn(
|
|
673
|
+
"flex-1 text-left text-sm",
|
|
674
|
+
isActive(item.path || "") ? "text-[var(--color-primary)] font-medium" : "text-[var(--color-text-secondary)]"
|
|
675
|
+
), children: item.label }),
|
|
676
|
+
item.badge && /* @__PURE__ */ jsx3("span", { className: "px-2 py-0.5 text-xs bg-[var(--color-primary)] text-white rounded-full", children: item.badge })
|
|
677
|
+
]
|
|
678
|
+
},
|
|
679
|
+
item.id
|
|
680
|
+
))
|
|
681
|
+
}
|
|
682
|
+
)
|
|
683
|
+
]
|
|
684
|
+
}
|
|
685
|
+
)
|
|
686
|
+
] }),
|
|
687
|
+
mobileMenuOpen && /* @__PURE__ */ jsx3(
|
|
688
|
+
"div",
|
|
689
|
+
{
|
|
690
|
+
className: "fixed inset-0 bg-black bg-opacity-50 z-50 lg:hidden",
|
|
691
|
+
onClick: () => setMobileMenuOpen(false),
|
|
692
|
+
"aria-hidden": "true",
|
|
693
|
+
children: /* @__PURE__ */ jsxs(
|
|
694
|
+
"aside",
|
|
695
|
+
{
|
|
696
|
+
className: "w-80 h-full bg-[var(--color-sidebar-bg)]",
|
|
697
|
+
onClick: (e) => e.stopPropagation(),
|
|
698
|
+
role: "navigation",
|
|
699
|
+
"aria-label": "Navigation mobile",
|
|
700
|
+
children: [
|
|
701
|
+
/* @__PURE__ */ jsxs("div", { className: "h-16 flex items-center justify-between px-4 border-b border-[var(--color-sidebar-border)]", children: [
|
|
702
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
703
|
+
/* @__PURE__ */ jsx3("div", { className: "w-10 h-10 bg-[var(--color-primary)] rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsx3("span", { className: "text-[var(--color-background)] font-bold text-xl", children: "W" }) }),
|
|
704
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
705
|
+
/* @__PURE__ */ jsx3("h1", { className: "text-white font-bold text-lg", children: "WiseBook" }),
|
|
706
|
+
/* @__PURE__ */ jsx3("p", { className: "text-gray-400 text-xs", children: "ERP Next-Gen" })
|
|
707
|
+
] })
|
|
708
|
+
] }),
|
|
709
|
+
/* @__PURE__ */ jsx3(
|
|
710
|
+
"button",
|
|
711
|
+
{
|
|
712
|
+
onClick: () => setMobileMenuOpen(false),
|
|
713
|
+
className: "text-[var(--color-sidebar-text-secondary)]",
|
|
714
|
+
"aria-label": "Fermer le menu",
|
|
715
|
+
children: /* @__PURE__ */ jsx3(X, { className: "w-6 h-6" })
|
|
716
|
+
}
|
|
717
|
+
)
|
|
718
|
+
] }),
|
|
719
|
+
/* @__PURE__ */ jsx3("nav", { className: "py-4", role: "menubar", children: primaryMenuItems.map((item) => /* @__PURE__ */ jsxs("div", { children: [
|
|
720
|
+
/* @__PURE__ */ jsxs(
|
|
721
|
+
"button",
|
|
722
|
+
{
|
|
723
|
+
onClick: () => {
|
|
724
|
+
if (item.path) {
|
|
725
|
+
navigate(item.path);
|
|
726
|
+
setMobileMenuOpen(false);
|
|
727
|
+
} else {
|
|
728
|
+
setSelectedModule(item.id);
|
|
729
|
+
}
|
|
730
|
+
},
|
|
731
|
+
className: cn(
|
|
732
|
+
"w-full flex items-center gap-3 px-4 py-3 transition-all duration-200",
|
|
733
|
+
"hover:bg-[var(--color-sidebar-hover)]",
|
|
734
|
+
isModuleActive(item.id) && "bg-[var(--color-sidebar-active)] border-l-4 border-[var(--color-primary)]"
|
|
735
|
+
),
|
|
736
|
+
role: "menuitem",
|
|
737
|
+
"aria-current": isModuleActive(item.id) ? "page" : void 0,
|
|
738
|
+
children: [
|
|
739
|
+
/* @__PURE__ */ jsx3("div", { className: cn(
|
|
740
|
+
"transition-colors",
|
|
741
|
+
isModuleActive(item.id) ? "text-[var(--color-primary)]" : "text-[var(--color-sidebar-text-secondary)]"
|
|
742
|
+
), children: item.icon }),
|
|
743
|
+
/* @__PURE__ */ jsx3("span", { className: cn(
|
|
744
|
+
"flex-1 text-left text-sm font-medium",
|
|
745
|
+
isModuleActive(item.id) ? "text-[var(--color-sidebar-text)]" : "text-[var(--color-sidebar-text-secondary)]"
|
|
746
|
+
), children: item.label }),
|
|
747
|
+
item.badge && /* @__PURE__ */ jsx3("span", { className: "px-2 py-0.5 text-xs bg-[var(--color-primary)] text-[var(--color-background)] rounded-full", children: item.badge })
|
|
748
|
+
]
|
|
749
|
+
}
|
|
750
|
+
),
|
|
751
|
+
isModuleActive(item.id) && secondaryMenuItems[item.id] && /* @__PURE__ */ jsx3("div", { className: "bg-[var(--color-sidebar-submenu-bg)] py-2", children: secondaryMenuItems[item.id].map((subItem) => /* @__PURE__ */ jsxs(
|
|
752
|
+
"button",
|
|
753
|
+
{
|
|
754
|
+
onClick: () => {
|
|
755
|
+
if (subItem.path) {
|
|
756
|
+
navigate(subItem.path);
|
|
757
|
+
setMobileMenuOpen(false);
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
className: cn(
|
|
761
|
+
"w-full flex items-center gap-3 pl-12 pr-4 py-2 text-sm",
|
|
762
|
+
"hover:bg-[var(--color-sidebar-hover)]",
|
|
763
|
+
isActive(subItem.path || "") && "bg-[var(--color-sidebar-active)] text-[var(--color-primary)]"
|
|
764
|
+
),
|
|
765
|
+
children: [
|
|
766
|
+
subItem.icon,
|
|
767
|
+
/* @__PURE__ */ jsx3("span", { className: cn(
|
|
768
|
+
isActive(subItem.path || "") ? "text-[var(--color-primary)]" : "text-[var(--color-sidebar-text-secondary)]"
|
|
769
|
+
), children: subItem.label })
|
|
770
|
+
]
|
|
771
|
+
},
|
|
772
|
+
subItem.id
|
|
773
|
+
)) })
|
|
774
|
+
] }, item.id)) })
|
|
775
|
+
]
|
|
776
|
+
}
|
|
777
|
+
)
|
|
778
|
+
}
|
|
779
|
+
),
|
|
780
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", children: [
|
|
781
|
+
/* @__PURE__ */ jsxs(
|
|
782
|
+
"header",
|
|
783
|
+
{
|
|
784
|
+
className: "h-14 bg-[var(--color-background)] border-b border-[var(--color-border)] flex items-center justify-between px-3 lg:px-4",
|
|
785
|
+
role: "banner",
|
|
786
|
+
children: [
|
|
787
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 flex-1", children: [
|
|
788
|
+
/* @__PURE__ */ jsx3(
|
|
789
|
+
"button",
|
|
790
|
+
{
|
|
791
|
+
onClick: () => setMobileMenuOpen(true),
|
|
792
|
+
className: "lg:hidden text-[var(--color-text-primary)]",
|
|
793
|
+
"aria-label": "Ouvrir le menu mobile",
|
|
794
|
+
children: /* @__PURE__ */ jsx3(Menu, { className: "w-6 h-6" })
|
|
795
|
+
}
|
|
796
|
+
),
|
|
797
|
+
/* @__PURE__ */ jsx3(
|
|
798
|
+
"nav",
|
|
799
|
+
{
|
|
800
|
+
className: "hidden sm:flex items-center gap-2 text-sm",
|
|
801
|
+
"aria-label": "Fil d'Ariane",
|
|
802
|
+
children: getBreadcrumbs().map((crumb, index) => /* @__PURE__ */ jsxs(React2.Fragment, { children: [
|
|
803
|
+
index > 0 && /* @__PURE__ */ jsx3(ChevronRight, { className: "w-4 h-4 text-[var(--color-text-tertiary)]" }),
|
|
804
|
+
/* @__PURE__ */ jsx3(
|
|
805
|
+
"button",
|
|
806
|
+
{
|
|
807
|
+
onClick: () => navigate(crumb.path),
|
|
808
|
+
className: cn(
|
|
809
|
+
"hover:text-[var(--color-primary)]",
|
|
810
|
+
index === getBreadcrumbs().length - 1 ? "text-[var(--color-text-primary)] font-medium" : "text-[var(--color-text-tertiary)]"
|
|
811
|
+
),
|
|
812
|
+
children: crumb.label
|
|
813
|
+
}
|
|
814
|
+
)
|
|
815
|
+
] }, crumb.path))
|
|
816
|
+
}
|
|
817
|
+
),
|
|
818
|
+
/* @__PURE__ */ jsxs("div", { className: "relative max-w-md flex-1 hidden lg:block", children: [
|
|
819
|
+
/* @__PURE__ */ jsx3(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 text-[var(--color-text-tertiary)] w-5 h-5" }),
|
|
820
|
+
/* @__PURE__ */ jsx3(
|
|
821
|
+
"input",
|
|
822
|
+
{
|
|
823
|
+
id: "global-search",
|
|
824
|
+
type: "text",
|
|
825
|
+
placeholder: "Rechercher... (Alt+S)",
|
|
826
|
+
value: searchQuery,
|
|
827
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
828
|
+
className: "w-full pl-10 pr-4 py-2 bg-[var(--color-surface-hover)] border border-[var(--color-border)] rounded-lg text-sm focus:outline-none focus:border-[var(--color-primary)] focus:ring-2 focus:ring-[var(--color-primary-light)]",
|
|
829
|
+
"aria-label": "Recherche globale"
|
|
830
|
+
}
|
|
831
|
+
)
|
|
832
|
+
] })
|
|
833
|
+
] }),
|
|
834
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
835
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
836
|
+
/* @__PURE__ */ jsx3(
|
|
837
|
+
"button",
|
|
838
|
+
{
|
|
839
|
+
onClick: () => setShowThemeMenu(!showThemeMenu),
|
|
840
|
+
className: "p-2 hover:bg-[var(--color-surface-hover)] rounded-lg transition-colors",
|
|
841
|
+
title: "Changer le th\xE8me",
|
|
842
|
+
"aria-label": "S\xE9lecteur de th\xE8me",
|
|
843
|
+
"aria-expanded": showThemeMenu,
|
|
844
|
+
children: /* @__PURE__ */ jsx3(Palette, { className: "w-5 h-5 text-[var(--color-text-secondary)]" })
|
|
845
|
+
}
|
|
846
|
+
),
|
|
847
|
+
showThemeMenu && /* @__PURE__ */ jsx3(
|
|
848
|
+
"div",
|
|
849
|
+
{
|
|
850
|
+
className: "absolute right-0 mt-2 w-64 bg-[var(--color-background)] rounded-lg shadow-xl border border-[var(--color-border)] z-50",
|
|
851
|
+
role: "menu",
|
|
852
|
+
"aria-label": "S\xE9lection du th\xE8me",
|
|
853
|
+
children: /* @__PURE__ */ jsxs("div", { className: "p-2", children: [
|
|
854
|
+
/* @__PURE__ */ jsx3("p", { className: "px-3 py-2 text-xs font-semibold text-[var(--color-text-tertiary)] uppercase", children: "Th\xE8mes disponibles" }),
|
|
855
|
+
/* @__PURE__ */ jsxs(
|
|
856
|
+
"button",
|
|
857
|
+
{
|
|
858
|
+
onClick: () => handleThemeChange("elegant"),
|
|
859
|
+
className: cn(
|
|
860
|
+
"w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-[var(--color-surface-hover)] transition-colors",
|
|
861
|
+
themeType === "elegant" && "bg-[var(--color-primary-light)]"
|
|
862
|
+
),
|
|
863
|
+
role: "menuitem",
|
|
864
|
+
children: [
|
|
865
|
+
/* @__PURE__ */ jsx3("div", { className: "w-10 h-10 rounded-lg bg-gradient-to-br from-[var(--color-primary)] to-[var(--color-accent)]" }),
|
|
866
|
+
/* @__PURE__ */ jsxs("div", { className: "text-left", children: [
|
|
867
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-medium", children: "\xC9l\xE9gance Sobre" }),
|
|
868
|
+
/* @__PURE__ */ jsx3("p", { className: "text-xs text-[var(--color-text-tertiary)]", children: "Finance traditionnelle" })
|
|
869
|
+
] })
|
|
870
|
+
]
|
|
871
|
+
}
|
|
872
|
+
),
|
|
873
|
+
/* @__PURE__ */ jsxs(
|
|
874
|
+
"button",
|
|
875
|
+
{
|
|
876
|
+
onClick: () => handleThemeChange("fintech"),
|
|
877
|
+
className: cn(
|
|
878
|
+
"w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-[var(--color-surface-hover)] transition-colors",
|
|
879
|
+
themeType === "fintech" && "bg-[var(--color-primary-light)]"
|
|
880
|
+
),
|
|
881
|
+
role: "menuitem",
|
|
882
|
+
children: [
|
|
883
|
+
/* @__PURE__ */ jsx3("div", { className: "w-10 h-10 rounded-lg bg-gradient-to-br from-[var(--color-success)] to-[var(--color-text-primary)]" }),
|
|
884
|
+
/* @__PURE__ */ jsxs("div", { className: "text-left", children: [
|
|
885
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-medium", children: "Modern Fintech" }),
|
|
886
|
+
/* @__PURE__ */ jsx3("p", { className: "text-xs text-[var(--color-text-tertiary)]", children: "Tableau de bord moderne" })
|
|
887
|
+
] })
|
|
888
|
+
]
|
|
889
|
+
}
|
|
890
|
+
),
|
|
891
|
+
/* @__PURE__ */ jsxs(
|
|
892
|
+
"button",
|
|
893
|
+
{
|
|
894
|
+
onClick: () => handleThemeChange("minimalist"),
|
|
895
|
+
className: cn(
|
|
896
|
+
"w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-[var(--color-surface-hover)] transition-colors",
|
|
897
|
+
themeType === "minimalist" && "bg-[var(--color-primary-light)]"
|
|
898
|
+
),
|
|
899
|
+
role: "menuitem",
|
|
900
|
+
children: [
|
|
901
|
+
/* @__PURE__ */ jsx3("div", { className: "w-10 h-10 rounded-lg bg-gradient-to-br from-[var(--color-text-secondary)] to-[var(--color-accent)]" }),
|
|
902
|
+
/* @__PURE__ */ jsxs("div", { className: "text-left", children: [
|
|
903
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-medium", children: "Minimaliste Premium" }),
|
|
904
|
+
/* @__PURE__ */ jsx3("p", { className: "text-xs text-[var(--color-text-tertiary)]", children: "\xC9l\xE9gance minimaliste" })
|
|
905
|
+
] })
|
|
906
|
+
]
|
|
907
|
+
}
|
|
908
|
+
)
|
|
909
|
+
] })
|
|
910
|
+
}
|
|
911
|
+
)
|
|
912
|
+
] }),
|
|
913
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center px-3 py-1.5 bg-[var(--color-surface)] rounded-lg border border-[var(--color-border)]", children: [
|
|
914
|
+
/* @__PURE__ */ jsx3(DollarSign, { className: "w-4 h-4 text-[var(--color-primary)] mr-2" }),
|
|
915
|
+
/* @__PURE__ */ jsx3("span", { className: "text-sm font-medium text-[var(--color-text-primary)]", children: "FCFA" })
|
|
916
|
+
] }),
|
|
917
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
918
|
+
/* @__PURE__ */ jsxs(
|
|
919
|
+
"button",
|
|
920
|
+
{
|
|
921
|
+
className: "relative p-2 hover:bg-[var(--color-surface-hover)] rounded-lg transition-colors",
|
|
922
|
+
onClick: () => setShowNotifications(!showNotifications),
|
|
923
|
+
"aria-label": `Notifications ${notifications.filter((n) => !n.read).length > 0 ? `(${notifications.filter((n) => !n.read).length} non lues)` : ""}`,
|
|
924
|
+
"aria-expanded": showNotifications,
|
|
925
|
+
children: [
|
|
926
|
+
/* @__PURE__ */ jsx3(Bell, { className: "w-5 h-5 text-[var(--color-text-secondary)]" }),
|
|
927
|
+
notifications.filter((n) => !n.read).length > 0 && /* @__PURE__ */ jsx3("span", { className: "absolute top-1 right-1 w-2 h-2 bg-[var(--color-error)] rounded-full" })
|
|
928
|
+
]
|
|
929
|
+
}
|
|
930
|
+
),
|
|
931
|
+
showNotifications && /* @__PURE__ */ jsxs(
|
|
932
|
+
"div",
|
|
933
|
+
{
|
|
934
|
+
className: "absolute right-0 mt-2 w-80 bg-[var(--color-background)] rounded-lg shadow-xl border border-[var(--color-border)] z-50 max-h-96 overflow-y-auto",
|
|
935
|
+
role: "region",
|
|
936
|
+
"aria-label": "Centre de notifications",
|
|
937
|
+
children: [
|
|
938
|
+
/* @__PURE__ */ jsx3("div", { className: "p-4 border-b border-[var(--color-border)]", children: /* @__PURE__ */ jsx3("h3", { className: "font-semibold text-[var(--color-text-primary)]", children: "Notifications" }) }),
|
|
939
|
+
/* @__PURE__ */ jsx3("div", { className: "divide-y divide-[var(--color-border)]", children: notifications.map((notif) => /* @__PURE__ */ jsx3(
|
|
940
|
+
"div",
|
|
941
|
+
{
|
|
942
|
+
className: cn(
|
|
943
|
+
"p-4 hover:bg-[var(--color-surface-hover)] cursor-pointer",
|
|
944
|
+
!notif.read && "bg-[var(--color-primary-light)] bg-opacity-10"
|
|
945
|
+
),
|
|
946
|
+
onClick: () => markNotificationAsRead(notif.id),
|
|
947
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3", children: [
|
|
948
|
+
/* @__PURE__ */ jsx3("div", { className: cn(
|
|
949
|
+
"w-2 h-2 rounded-full mt-2",
|
|
950
|
+
notif.type === "error" && "bg-[var(--color-error)]",
|
|
951
|
+
notif.type === "warning" && "bg-[var(--color-warning)]",
|
|
952
|
+
notif.type === "success" && "bg-[var(--color-success)]",
|
|
953
|
+
notif.type === "info" && "bg-[var(--color-info)]"
|
|
954
|
+
) }),
|
|
955
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
956
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-medium text-[var(--color-text-primary)]", children: notif.title }),
|
|
957
|
+
/* @__PURE__ */ jsx3("p", { className: "text-xs text-[var(--color-text-secondary)] mt-1", children: notif.message }),
|
|
958
|
+
/* @__PURE__ */ jsx3("p", { className: "text-xs text-[var(--color-text-tertiary)] mt-2", children: notif.timestamp.toLocaleTimeString() })
|
|
959
|
+
] })
|
|
960
|
+
] })
|
|
961
|
+
},
|
|
962
|
+
notif.id
|
|
963
|
+
)) })
|
|
964
|
+
]
|
|
965
|
+
}
|
|
966
|
+
)
|
|
967
|
+
] }),
|
|
968
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
969
|
+
/* @__PURE__ */ jsx3(
|
|
970
|
+
"button",
|
|
971
|
+
{
|
|
972
|
+
onClick: () => setShowUserMenu(!showUserMenu),
|
|
973
|
+
className: "flex items-center gap-2 p-2 hover:bg-[var(--color-surface-hover)] rounded-lg transition-colors",
|
|
974
|
+
"aria-label": "Menu utilisateur",
|
|
975
|
+
"aria-expanded": showUserMenu,
|
|
976
|
+
children: /* @__PURE__ */ jsx3("div", { className: "w-8 h-8 bg-[var(--color-primary)] rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx3(User, { className: "w-4 h-4 text-[var(--color-background)]" }) })
|
|
977
|
+
}
|
|
978
|
+
),
|
|
979
|
+
showUserMenu && /* @__PURE__ */ jsx3(
|
|
980
|
+
"div",
|
|
981
|
+
{
|
|
982
|
+
className: "absolute right-0 mt-2 w-56 bg-[var(--color-background)] rounded-lg shadow-xl border border-[var(--color-border)] z-50",
|
|
983
|
+
role: "menu",
|
|
984
|
+
"aria-label": "Menu utilisateur",
|
|
985
|
+
children: /* @__PURE__ */ jsxs("div", { className: "p-2", children: [
|
|
986
|
+
/* @__PURE__ */ jsxs(
|
|
987
|
+
"button",
|
|
988
|
+
{
|
|
989
|
+
className: "w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-[var(--color-surface-hover)] transition-colors",
|
|
990
|
+
role: "menuitem",
|
|
991
|
+
children: [
|
|
992
|
+
/* @__PURE__ */ jsx3(User, { className: "w-4 h-4" }),
|
|
993
|
+
/* @__PURE__ */ jsx3("span", { className: "text-sm", children: "Mon profil" })
|
|
994
|
+
]
|
|
995
|
+
}
|
|
996
|
+
),
|
|
997
|
+
/* @__PURE__ */ jsxs(
|
|
998
|
+
"button",
|
|
999
|
+
{
|
|
1000
|
+
onClick: () => {
|
|
1001
|
+
navigate("/settings");
|
|
1002
|
+
setShowUserMenu(false);
|
|
1003
|
+
},
|
|
1004
|
+
className: "w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-[var(--color-surface-hover)] transition-colors",
|
|
1005
|
+
role: "menuitem",
|
|
1006
|
+
children: [
|
|
1007
|
+
/* @__PURE__ */ jsx3(Settings, { className: "w-4 h-4" }),
|
|
1008
|
+
/* @__PURE__ */ jsx3("span", { className: "text-sm", children: "Param\xE8tres" })
|
|
1009
|
+
]
|
|
1010
|
+
}
|
|
1011
|
+
),
|
|
1012
|
+
/* @__PURE__ */ jsxs(
|
|
1013
|
+
"button",
|
|
1014
|
+
{
|
|
1015
|
+
className: "w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-[var(--color-surface-hover)] transition-colors",
|
|
1016
|
+
role: "menuitem",
|
|
1017
|
+
children: [
|
|
1018
|
+
/* @__PURE__ */ jsx3(HelpCircle, { className: "w-4 h-4" }),
|
|
1019
|
+
/* @__PURE__ */ jsx3("span", { className: "text-sm", children: "Aide" })
|
|
1020
|
+
]
|
|
1021
|
+
}
|
|
1022
|
+
),
|
|
1023
|
+
/* @__PURE__ */ jsx3("hr", { className: "my-2 border-[var(--color-border)]" }),
|
|
1024
|
+
/* @__PURE__ */ jsxs(
|
|
1025
|
+
"button",
|
|
1026
|
+
{
|
|
1027
|
+
className: "w-full flex items-center gap-3 px-3 py-2 rounded-lg hover:bg-[var(--color-surface-hover)] text-[var(--color-error)] transition-colors",
|
|
1028
|
+
role: "menuitem",
|
|
1029
|
+
children: [
|
|
1030
|
+
/* @__PURE__ */ jsx3(LogOut, { className: "w-4 h-4" }),
|
|
1031
|
+
/* @__PURE__ */ jsx3("span", { className: "text-sm", children: "D\xE9connexion" })
|
|
1032
|
+
]
|
|
1033
|
+
}
|
|
1034
|
+
)
|
|
1035
|
+
] })
|
|
1036
|
+
}
|
|
1037
|
+
)
|
|
1038
|
+
] })
|
|
1039
|
+
] })
|
|
1040
|
+
]
|
|
1041
|
+
}
|
|
1042
|
+
),
|
|
1043
|
+
/* @__PURE__ */ jsx3(
|
|
1044
|
+
"main",
|
|
1045
|
+
{
|
|
1046
|
+
id: "main-content",
|
|
1047
|
+
className: "flex-1 overflow-y-auto bg-[var(--color-background)]",
|
|
1048
|
+
role: "main",
|
|
1049
|
+
children: /* @__PURE__ */ jsx3("div", { className: "p-3 lg:p-4", children })
|
|
1050
|
+
}
|
|
1051
|
+
)
|
|
1052
|
+
] })
|
|
1053
|
+
] });
|
|
1054
|
+
};
|
|
1055
|
+
var ModernDoubleSidebarLayout_default = RewiseLayout;
|
|
1056
|
+
|
|
1057
|
+
// src/components/ui/Toast.tsx
|
|
1058
|
+
import { useEffect as useEffect3, useState as useState4 } from "react";
|
|
1059
|
+
|
|
1060
|
+
// src/contexts/ToastContext.tsx
|
|
1061
|
+
import { createContext as createContext2, useContext as useContext2, useState as useState3, useCallback } from "react";
|
|
1062
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1063
|
+
var ToastContext = createContext2(void 0);
|
|
1064
|
+
var useToast = () => {
|
|
1065
|
+
const context = useContext2(ToastContext);
|
|
1066
|
+
if (!context) {
|
|
1067
|
+
throw new Error("useToast must be used within a ToastProvider");
|
|
1068
|
+
}
|
|
1069
|
+
return context;
|
|
1070
|
+
};
|
|
1071
|
+
var ToastProvider = ({ children }) => {
|
|
1072
|
+
const [toasts, setToasts] = useState3([]);
|
|
1073
|
+
const generateId = () => {
|
|
1074
|
+
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
|
1075
|
+
};
|
|
1076
|
+
const addToast = useCallback((toast) => {
|
|
1077
|
+
const id = generateId();
|
|
1078
|
+
const newToast = {
|
|
1079
|
+
id,
|
|
1080
|
+
duration: 5e3,
|
|
1081
|
+
...toast
|
|
1082
|
+
};
|
|
1083
|
+
setToasts((prev) => [...prev, newToast]);
|
|
1084
|
+
if (newToast.duration && newToast.duration > 0) {
|
|
1085
|
+
setTimeout(() => {
|
|
1086
|
+
removeToast(id);
|
|
1087
|
+
}, newToast.duration);
|
|
1088
|
+
}
|
|
1089
|
+
}, []);
|
|
1090
|
+
const removeToast = useCallback((id) => {
|
|
1091
|
+
setToasts((prev) => prev.filter((toast) => toast.id !== id));
|
|
1092
|
+
}, []);
|
|
1093
|
+
const success = useCallback((message, duration) => {
|
|
1094
|
+
addToast({ message, type: "success", duration });
|
|
1095
|
+
}, [addToast]);
|
|
1096
|
+
const error = useCallback((message, duration) => {
|
|
1097
|
+
addToast({ message, type: "error", duration });
|
|
1098
|
+
}, [addToast]);
|
|
1099
|
+
const warning = useCallback((message, duration) => {
|
|
1100
|
+
addToast({ message, type: "warning", duration });
|
|
1101
|
+
}, [addToast]);
|
|
1102
|
+
const info = useCallback((message, duration) => {
|
|
1103
|
+
addToast({ message, type: "info", duration });
|
|
1104
|
+
}, [addToast]);
|
|
1105
|
+
const value = {
|
|
1106
|
+
toasts,
|
|
1107
|
+
addToast,
|
|
1108
|
+
removeToast,
|
|
1109
|
+
success,
|
|
1110
|
+
error,
|
|
1111
|
+
warning,
|
|
1112
|
+
info
|
|
1113
|
+
};
|
|
1114
|
+
return /* @__PURE__ */ jsx4(ToastContext.Provider, { value, children });
|
|
1115
|
+
};
|
|
1116
|
+
|
|
1117
|
+
// src/components/ui/Toast.tsx
|
|
1118
|
+
import { CheckCircle, XCircle, AlertTriangle, Info, X as X2 } from "lucide-react";
|
|
1119
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1120
|
+
var ToastItem = ({ toast }) => {
|
|
1121
|
+
const { removeToast } = useToast();
|
|
1122
|
+
const [isVisible, setIsVisible] = useState4(false);
|
|
1123
|
+
const [isLeaving, setIsLeaving] = useState4(false);
|
|
1124
|
+
useEffect3(() => {
|
|
1125
|
+
const timer = setTimeout(() => setIsVisible(true), 10);
|
|
1126
|
+
return () => clearTimeout(timer);
|
|
1127
|
+
}, []);
|
|
1128
|
+
const handleClose = () => {
|
|
1129
|
+
setIsLeaving(true);
|
|
1130
|
+
setTimeout(() => {
|
|
1131
|
+
removeToast(toast.id);
|
|
1132
|
+
}, 300);
|
|
1133
|
+
};
|
|
1134
|
+
const getIcon = () => {
|
|
1135
|
+
switch (toast.type) {
|
|
1136
|
+
case "success":
|
|
1137
|
+
return /* @__PURE__ */ jsx5(CheckCircle, { className: "w-5 h-5 text-green-600" });
|
|
1138
|
+
case "error":
|
|
1139
|
+
return /* @__PURE__ */ jsx5(XCircle, { className: "w-5 h-5 text-red-600" });
|
|
1140
|
+
case "warning":
|
|
1141
|
+
return /* @__PURE__ */ jsx5(AlertTriangle, { className: "w-5 h-5 text-yellow-600" });
|
|
1142
|
+
case "info":
|
|
1143
|
+
return /* @__PURE__ */ jsx5(Info, { className: "w-5 h-5 text-blue-600" });
|
|
1144
|
+
}
|
|
1145
|
+
};
|
|
1146
|
+
const getBackgroundColor = () => {
|
|
1147
|
+
switch (toast.type) {
|
|
1148
|
+
case "success":
|
|
1149
|
+
return "bg-green-50 border-green-200";
|
|
1150
|
+
case "error":
|
|
1151
|
+
return "bg-red-50 border-red-200";
|
|
1152
|
+
case "warning":
|
|
1153
|
+
return "bg-yellow-50 border-yellow-200";
|
|
1154
|
+
case "info":
|
|
1155
|
+
return "bg-blue-50 border-blue-200";
|
|
1156
|
+
}
|
|
1157
|
+
};
|
|
1158
|
+
return /* @__PURE__ */ jsxs2(
|
|
1159
|
+
"div",
|
|
1160
|
+
{
|
|
1161
|
+
className: `
|
|
1162
|
+
transform transition-all duration-300 ease-in-out
|
|
1163
|
+
${isVisible && !isLeaving ? "translate-x-0 opacity-100" : "translate-x-full opacity-0"}
|
|
1164
|
+
${getBackgroundColor()}
|
|
1165
|
+
max-w-sm w-full border rounded-lg p-4 shadow-lg
|
|
1166
|
+
flex items-start space-x-3
|
|
1167
|
+
`,
|
|
1168
|
+
children: [
|
|
1169
|
+
/* @__PURE__ */ jsx5("div", { className: "flex-shrink-0", children: getIcon() }),
|
|
1170
|
+
/* @__PURE__ */ jsx5("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx5("p", { className: "text-sm text-gray-900 font-medium", children: toast.message }) }),
|
|
1171
|
+
/* @__PURE__ */ jsx5(
|
|
1172
|
+
"button",
|
|
1173
|
+
{
|
|
1174
|
+
onClick: handleClose,
|
|
1175
|
+
className: "flex-shrink-0 ml-4 text-gray-400 hover:text-gray-600 transition-colors",
|
|
1176
|
+
children: /* @__PURE__ */ jsx5(X2, { className: "w-4 h-4" })
|
|
1177
|
+
}
|
|
1178
|
+
)
|
|
1179
|
+
]
|
|
1180
|
+
}
|
|
1181
|
+
);
|
|
1182
|
+
};
|
|
1183
|
+
var ToastContainer = () => {
|
|
1184
|
+
const { toasts } = useToast();
|
|
1185
|
+
return /* @__PURE__ */ jsx5("div", { className: "fixed top-4 right-4 z-50 space-y-3", children: toasts.map((toast) => /* @__PURE__ */ jsx5(ToastItem, { toast }, toast.id)) });
|
|
1186
|
+
};
|
|
1187
|
+
var Toast_default = ToastContainer;
|
|
1188
|
+
|
|
1189
|
+
// src/contexts/SessionContext.tsx
|
|
1190
|
+
import { createContext as createContext3, useContext as useContext3, useEffect as useEffect4, useState as useState5 } from "react";
|
|
1191
|
+
|
|
1192
|
+
// src/services/api.ts
|
|
1193
|
+
var ADDRESS_IP = "localhost:8000";
|
|
1194
|
+
var ADDRESS_IP_URL = `http://${ADDRESS_IP}/`;
|
|
1195
|
+
var API_URL = `${ADDRESS_IP_URL}api`;
|
|
1196
|
+
|
|
1197
|
+
// src/services/AuthServices.ts
|
|
1198
|
+
var API_BASE_URL = `${API_URL}/core/auth/`;
|
|
1199
|
+
var FetchApi = class {
|
|
1200
|
+
static async post(url, payload, token) {
|
|
1201
|
+
const headers = {
|
|
1202
|
+
"Content-Type": "application/json"
|
|
1203
|
+
};
|
|
1204
|
+
if (token) {
|
|
1205
|
+
headers["Authorization"] = `Token ${token}`;
|
|
1206
|
+
}
|
|
1207
|
+
const res = await fetch(url, {
|
|
1208
|
+
method: "POST",
|
|
1209
|
+
headers,
|
|
1210
|
+
body: payload ? JSON.stringify(payload) : void 0
|
|
1211
|
+
});
|
|
1212
|
+
if (!res.ok) throw new Error(await res.text());
|
|
1213
|
+
return res.json();
|
|
1214
|
+
}
|
|
1215
|
+
static async get(url, token) {
|
|
1216
|
+
const headers = {};
|
|
1217
|
+
if (token) {
|
|
1218
|
+
headers["Authorization"] = `Token ${token}`;
|
|
1219
|
+
}
|
|
1220
|
+
const res = await fetch(url, {
|
|
1221
|
+
method: "GET",
|
|
1222
|
+
headers
|
|
1223
|
+
});
|
|
1224
|
+
if (!res.ok) throw new Error(await res.text());
|
|
1225
|
+
return res.json();
|
|
1226
|
+
}
|
|
1227
|
+
};
|
|
1228
|
+
var AuthServices = {
|
|
1229
|
+
sendOtp: (payload) => FetchApi.post(`${API_BASE_URL}send-otp/`, payload),
|
|
1230
|
+
verifyOtp: (payload) => FetchApi.post(`${API_BASE_URL}verify-otp/`, payload),
|
|
1231
|
+
completeRegistration: (payload) => FetchApi.post(`${API_BASE_URL}complete-registration/`, payload),
|
|
1232
|
+
addUser: (payload) => FetchApi.post(`${API_BASE_URL}add-user/`, payload),
|
|
1233
|
+
login: (payload) => FetchApi.post(`${API_BASE_URL}login/`, payload),
|
|
1234
|
+
getUserInformations: (token) => FetchApi.get(`${API_BASE_URL}user-informations/`, token),
|
|
1235
|
+
logout: () => FetchApi.post(`${API_BASE_URL}logout/`)
|
|
1236
|
+
};
|
|
1237
|
+
|
|
1238
|
+
// src/contexts/SessionContext.tsx
|
|
1239
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
1240
|
+
var SessionContext = createContext3(void 0);
|
|
1241
|
+
var SessionProvider = ({ children }) => {
|
|
1242
|
+
const [token, setToken] = useState5(localStorage.getItem("token"));
|
|
1243
|
+
const [loggedUser, setLoggedUser] = useState5(null);
|
|
1244
|
+
useEffect4(() => {
|
|
1245
|
+
const storedToken = localStorage.getItem("token");
|
|
1246
|
+
if (storedToken) {
|
|
1247
|
+
setToken(storedToken);
|
|
1248
|
+
}
|
|
1249
|
+
}, []);
|
|
1250
|
+
const login = (newToken) => {
|
|
1251
|
+
localStorage.setItem("token", newToken);
|
|
1252
|
+
setToken(newToken);
|
|
1253
|
+
};
|
|
1254
|
+
const logout = () => {
|
|
1255
|
+
localStorage.removeItem("token");
|
|
1256
|
+
setToken(null);
|
|
1257
|
+
};
|
|
1258
|
+
useEffect4(() => {
|
|
1259
|
+
if (token) {
|
|
1260
|
+
AuthServices.getUserInformations(token).then((res) => {
|
|
1261
|
+
const result = res;
|
|
1262
|
+
if (result.success === true) {
|
|
1263
|
+
setLoggedUser(result.data.user);
|
|
1264
|
+
} else {
|
|
1265
|
+
setLoggedUser(null);
|
|
1266
|
+
}
|
|
1267
|
+
}).catch(() => setLoggedUser(null));
|
|
1268
|
+
} else {
|
|
1269
|
+
setLoggedUser(null);
|
|
1270
|
+
}
|
|
1271
|
+
}, [token]);
|
|
1272
|
+
return /* @__PURE__ */ jsx6(SessionContext.Provider, { value: {
|
|
1273
|
+
isAuthenticated: !!token,
|
|
1274
|
+
loggedUser,
|
|
1275
|
+
token,
|
|
1276
|
+
login,
|
|
1277
|
+
logout
|
|
1278
|
+
}, children });
|
|
1279
|
+
};
|
|
1280
|
+
|
|
1281
|
+
// src/components/common/Pages.tsx
|
|
1282
|
+
import { ChevronLeft as ChevronLeft2, Download, Menu as Menu2, Settings as Settings2 } from "lucide-react";
|
|
1283
|
+
import { useState as useState6 } from "react";
|
|
1284
|
+
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1285
|
+
var Pages = ({
|
|
1286
|
+
title = "",
|
|
1287
|
+
description = "",
|
|
1288
|
+
sideAction,
|
|
1289
|
+
sidebar,
|
|
1290
|
+
tabs = [],
|
|
1291
|
+
children
|
|
1292
|
+
}) => {
|
|
1293
|
+
const [sidebarOpen, setSidebarOpen] = useState6(false);
|
|
1294
|
+
return /* @__PURE__ */ jsxs3("div", { className: "flex h-full bg-gray-50", children: [
|
|
1295
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex-1 flex flex-col", children: [
|
|
1296
|
+
/* @__PURE__ */ jsxs3("div", { className: "bg-white border-b border-gray-200 p-6", children: [
|
|
1297
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between", children: [
|
|
1298
|
+
/* @__PURE__ */ jsx7("div", { className: "flex items-center space-x-4", children: /* @__PURE__ */ jsxs3("div", { children: [
|
|
1299
|
+
/* @__PURE__ */ jsx7("h1", { className: "text-2xl font-bold text-gray-900", children: title }),
|
|
1300
|
+
/* @__PURE__ */ jsx7("p", { className: "text-sm text-gray-600", children: description })
|
|
1301
|
+
] }) }),
|
|
1302
|
+
/* @__PURE__ */ jsx7("div", { className: "flex items-center space-x-3", children: sideAction })
|
|
1303
|
+
] }),
|
|
1304
|
+
tabs.length > 0 && /* @__PURE__ */ jsx7("div", { className: "flex space-x-1 mt-4 overflow-x-auto", children: tabs.map((tab) => /* @__PURE__ */ jsx7(
|
|
1305
|
+
"button",
|
|
1306
|
+
{
|
|
1307
|
+
className: `px-4 py-2 text-sm rounded-lg transition-all whitespace-nowrap ${tab.id === "manual" ? "bg-[#6A8A82] text-white shadow-md" : "text-gray-600 hover:bg-gray-100"}`,
|
|
1308
|
+
children: tab.label
|
|
1309
|
+
},
|
|
1310
|
+
tab.id
|
|
1311
|
+
)) })
|
|
1312
|
+
] }),
|
|
1313
|
+
/* @__PURE__ */ jsx7("div", { className: "flex-1 p-6 space-y-6", children })
|
|
1314
|
+
] }),
|
|
1315
|
+
sidebar && /* @__PURE__ */ jsxs3("div", { className: `${sidebarOpen ? "w-80" : "w-16"} bg-[var(--color-surface)] border-r border-[var(--color-border)] transition-all duration-300 flex flex-col`, children: [
|
|
1316
|
+
/* @__PURE__ */ jsx7("div", { className: "p-4 ", children: /* @__PURE__ */ jsxs3("div", { className: "flex items-center justify-between", children: [
|
|
1317
|
+
/* @__PURE__ */ jsx7("h2", { className: `font-semibold text-[var(--color-text-primary)] ${!sidebarOpen && "hidden"}`, children: "Classes SYSCOHADA" }),
|
|
1318
|
+
/* @__PURE__ */ jsx7(
|
|
1319
|
+
"button",
|
|
1320
|
+
{
|
|
1321
|
+
onClick: () => setSidebarOpen(!sidebarOpen),
|
|
1322
|
+
className: "p-2 hover:bg-[var(--color-surface-hover)] rounded-lg transition-colors",
|
|
1323
|
+
"aria-label": sidebarOpen ? "R\xE9duire" : "Ouvrir",
|
|
1324
|
+
children: sidebarOpen ? /* @__PURE__ */ jsx7(ChevronLeft2, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx7(Menu2, { className: "w-5 h-5" })
|
|
1325
|
+
}
|
|
1326
|
+
)
|
|
1327
|
+
] }) }),
|
|
1328
|
+
/* @__PURE__ */ jsx7("div", { className: "flex-1 overflow-y-auto py-2", children: /* @__PURE__ */ jsx7(
|
|
1329
|
+
"button",
|
|
1330
|
+
{
|
|
1331
|
+
onClick: () => {
|
|
1332
|
+
},
|
|
1333
|
+
className: `w-full flex items-center gap-3 px-4 py-3 transition-all relative group hover:bg-[var(--color-surface-hover)]`,
|
|
1334
|
+
children: /* @__PURE__ */ jsx7(
|
|
1335
|
+
"div",
|
|
1336
|
+
{
|
|
1337
|
+
className: `flex-shrink-0 w-10 h-10 rounded-lg flex items-center justify-center transition-colors bg-[var(--color-background)]`,
|
|
1338
|
+
children: /* @__PURE__ */ jsx7("span", { className: "font-bold text-lg", children: 1 })
|
|
1339
|
+
}
|
|
1340
|
+
)
|
|
1341
|
+
}
|
|
1342
|
+
) }),
|
|
1343
|
+
sidebarOpen && /* @__PURE__ */ jsx7("div", { className: "p-4 border-t border-[var(--color-border)]", children: /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
|
|
1344
|
+
/* @__PURE__ */ jsxs3("button", { className: "w-full px-3 py-2 bg-[var(--color-background)] rounded-lg text-sm text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-hover)] transition-colors flex items-center gap-2", children: [
|
|
1345
|
+
/* @__PURE__ */ jsx7(Download, { className: "w-4 h-4" }),
|
|
1346
|
+
"Exporter le plan"
|
|
1347
|
+
] }),
|
|
1348
|
+
/* @__PURE__ */ jsxs3("button", { className: "w-full px-3 py-2 bg-[var(--color-background)] rounded-lg text-sm text-[var(--color-text-secondary)] hover:bg-[var(--color-surface-hover)] transition-colors flex items-center gap-2", children: [
|
|
1349
|
+
/* @__PURE__ */ jsx7(Settings2, { className: "w-4 h-4" }),
|
|
1350
|
+
"Configuration"
|
|
1351
|
+
] })
|
|
1352
|
+
] }) })
|
|
1353
|
+
] })
|
|
1354
|
+
] });
|
|
1355
|
+
};
|
|
1356
|
+
var Pages_default = Pages;
|
|
1357
|
+
export {
|
|
1358
|
+
Pages_default as Pages,
|
|
1359
|
+
Buttons_default as PrimaryButton,
|
|
1360
|
+
ModernDoubleSidebarLayout_default as RewiseLayout,
|
|
1361
|
+
SecondaryButton,
|
|
1362
|
+
SessionProvider,
|
|
1363
|
+
ThemeContext_default as ThemeProvider,
|
|
1364
|
+
Toast_default as ToastContainer,
|
|
1365
|
+
ToastProvider
|
|
1366
|
+
};
|