ptechcore_ui 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/index.cjs +1317 -0
  2. package/dist/index.d.cts +45 -0
  3. package/dist/index.d.ts +45 -0
  4. package/dist/index.js +1288 -0
  5. package/package.json +14 -1
  6. package/eslint.config.js +0 -28
  7. package/index.html +0 -78
  8. package/postcss.config.js +0 -6
  9. package/src/App.tsx +0 -156
  10. package/src/assets/imgs/login_illustration.png +0 -0
  11. package/src/components/common/Buttons.tsx +0 -39
  12. package/src/components/common/Cards.tsx +0 -18
  13. package/src/components/common/FDrawer.tsx +0 -2448
  14. package/src/components/common/FDrawer.types.ts +0 -191
  15. package/src/components/common/Inputs.tsx +0 -409
  16. package/src/components/common/Modals.tsx +0 -41
  17. package/src/components/common/Navigations.tsx +0 -0
  18. package/src/components/common/Toast.tsx +0 -0
  19. package/src/components/demo/ToastDemo.tsx +0 -73
  20. package/src/components/layout/Header.tsx +0 -202
  21. package/src/components/layout/ModernDoubleSidebarLayout.tsx +0 -719
  22. package/src/components/layout/PrivateLayout.tsx +0 -52
  23. package/src/components/layout/Sidebar.tsx +0 -182
  24. package/src/components/ui/Toast.tsx +0 -93
  25. package/src/contexts/SessionContext.tsx +0 -77
  26. package/src/contexts/ThemeContext.tsx +0 -58
  27. package/src/contexts/ToastContext.tsx +0 -94
  28. package/src/index.css +0 -3
  29. package/src/index.ts +0 -10
  30. package/src/main.tsx +0 -10
  31. package/src/models/Organization.ts +0 -47
  32. package/src/models/Plan.ts +0 -42
  33. package/src/models/User.ts +0 -23
  34. package/src/pages/Analytics.tsx +0 -101
  35. package/src/pages/CreateOrganization.tsx +0 -215
  36. package/src/pages/Dashboard.tsx +0 -15
  37. package/src/pages/Home.tsx +0 -12
  38. package/src/pages/Profile.tsx +0 -313
  39. package/src/pages/Settings.tsx +0 -382
  40. package/src/pages/Team.tsx +0 -180
  41. package/src/pages/auth/Login.tsx +0 -140
  42. package/src/pages/auth/Register.tsx +0 -302
  43. package/src/pages/organizations/DetailEntity.tsx +0 -1002
  44. package/src/pages/organizations/DetailOrganizations.tsx +0 -1628
  45. package/src/pages/organizations/ListOrganizations.tsx +0 -270
  46. package/src/pages/pricings/CartPlan.tsx +0 -486
  47. package/src/pages/pricings/ListPricing.tsx +0 -321
  48. package/src/pages/users/CreateUser.tsx +0 -448
  49. package/src/pages/users/ListUsers.tsx +0 -0
  50. package/src/services/AuthServices.ts +0 -94
  51. package/src/services/OrganizationServices.ts +0 -61
  52. package/src/services/PlanSubscriptionServices.tsx +0 -137
  53. package/src/services/UserServices.ts +0 -36
  54. package/src/services/api.ts +0 -64
  55. package/src/styles/theme.ts +0 -383
  56. package/src/utils/utils.ts +0 -48
  57. package/src/vite-env.d.ts +0 -1
  58. package/tailwind.config.js +0 -158
  59. package/tsconfig.app.json +0 -24
  60. package/tsconfig.json +0 -31
  61. package/tsconfig.node.json +0 -22
  62. package/vite.config.ts +0 -10
@@ -1,137 +0,0 @@
1
- import { Module, Plan } from '../models/Plan';
2
- import { API_URL, FetchApi } from './api';
3
-
4
-
5
- const MODULES_API_URL = `${API_URL}/core/modules/`;
6
- const PLANS_API_URL = `${API_URL}/core/plans/`;
7
-
8
-
9
-
10
- export const ModuleServices = {
11
- // CRUD Operations pour Module
12
- createModule: (data: Partial<Module>, token: string) =>
13
- FetchApi.post(`${MODULES_API_URL}`, data, token),
14
-
15
- getAllModules: (token: string) =>
16
- FetchApi.get(`${MODULES_API_URL}`, token),
17
-
18
- getActiveModules: (token: string) =>
19
- FetchApi.get(`${MODULES_API_URL}?is_active=true`, token),
20
-
21
- getModule: (id: number, token: string) =>
22
- FetchApi.get(`${MODULES_API_URL}${id}/`, token),
23
-
24
- updateModule: (id: number, data: Partial<Module>, token: string) =>
25
- FetchApi.put(`${MODULES_API_URL}${id}/`, data, token),
26
-
27
- deleteModule: (id: number, token: string) =>
28
- FetchApi.delete(`${MODULES_API_URL}${id}/`, token),
29
-
30
- // Activation/D�sactivation d'un module
31
- toggleModuleStatus: (id: number, is_active: boolean, token: string) =>
32
- FetchApi.put(`${MODULES_API_URL}${id}/`, { is_active }, token),
33
- };
34
-
35
- export const PlanServices = {
36
- // CRUD Operations pour Plan
37
- createPlan: (data: Partial<Plan>, token: string) =>
38
- FetchApi.post(`${PLANS_API_URL}`, data, token),
39
-
40
- getAllPlans: (token: string) =>
41
- FetchApi.get(`${PLANS_API_URL}`, token),
42
-
43
- getPublicPlans: (token?: string) =>
44
- FetchApi.get(`${PLANS_API_URL}?is_private=false`, token),
45
-
46
- getPrivatePlans: (organizationId: number, token: string) =>
47
- FetchApi.get(`${PLANS_API_URL}?private_for=${organizationId}`, token),
48
-
49
- getPlan: (id: number, token: string) =>
50
- FetchApi.get(`${PLANS_API_URL}${id}/`, token),
51
-
52
- updatePlan: (id: number, data: Partial<Plan>, token: string) =>
53
- FetchApi.put(`${PLANS_API_URL}${id}/`, data, token),
54
-
55
- deletePlan: (id: number, token: string) =>
56
- FetchApi.delete(`${PLANS_API_URL}${id}/`, token),
57
-
58
- // Gestion des modules inclus dans un plan
59
- addModuleToPlan: (planId: number, moduleId: number, token: string) =>
60
- FetchApi.post(`${PLANS_API_URL}${planId}/add_module/`, { module_id: moduleId }, token),
61
-
62
- removeModuleFromPlan: (planId: number, moduleId: number, token: string) =>
63
- FetchApi.post(`${PLANS_API_URL}${planId}/remove_module/`, { module_id: moduleId }, token),
64
-
65
- getPlanModules: (planId: number, token: string) =>
66
- FetchApi.get(`${PLANS_API_URL}${planId}/modules/`, token),
67
- };
68
-
69
- // Service combin� pour la gestion des abonnements
70
- export const SubscriptionServices = {
71
- // Obtenir tous les plans disponibles pour une organisation
72
- getAvailablePlans: (organizationId?: number, token?: string) => {
73
- if (organizationId && token) {
74
- // Obtenir les plans publics + les plans priv�s pour cette organisation
75
- return Promise.all([
76
- PlanServices.getPublicPlans(token),
77
- PlanServices.getPrivatePlans(organizationId, token)
78
- ]).then(([publicPlans, privatePlans]) => ({
79
- public: publicPlans,
80
- private: privatePlans,
81
- all: [...(publicPlans as any).data || [], ...(privatePlans as any).data || []]
82
- }));
83
- } else {
84
- // Obtenir seulement les plans publics
85
- return PlanServices.getPublicPlans(token);
86
- }
87
- },
88
-
89
- // Calculer le prix d'un plan selon la p�riode
90
- calculatePlanPrice: (plan: Plan, billing_period: 'monthly' | 'yearly'): number => {
91
- return billing_period === 'monthly' ? plan.price_monthly : plan.price_yearly;
92
- },
93
-
94
- // Calculer les �conomies avec facturation annuelle
95
- calculateYearlySavings: (plan: Plan): number => {
96
- const yearlyTotal = plan.price_monthly * 12;
97
- const savings = yearlyTotal - plan.price_yearly;
98
- return Math.max(0, savings);
99
- },
100
-
101
- // Calculer le pourcentage d'�conomie
102
- calculateSavingsPercentage: (plan: Plan): number => {
103
- const yearlyTotal = plan.price_monthly * 12;
104
- const savings = SubscriptionServices.calculateYearlySavings(plan);
105
- return yearlyTotal > 0 ? Math.round((savings / yearlyTotal) * 100) : 0;
106
- },
107
-
108
- // V�rifier si un plan convient � une organisation
109
- isPlanSuitableForOrganization: (plan: Plan, userCount: number, entityCount: number): boolean => {
110
- return userCount <= plan.max_users && entityCount <= plan.max_entities;
111
- },
112
-
113
- // Obtenir les modules non inclus dans un plan
114
- getAdditionalModules: async (planId: number, token: string) => {
115
- try {
116
- const [allModules, planModules] = await Promise.all([
117
- ModuleServices.getActiveModules(token),
118
- PlanServices.getPlanModules(planId, token)
119
- ]);
120
-
121
- const planModuleIds = new Set((planModules as any).data?.map((m: Module) => m.id) || []);
122
- const additionalModules = (allModules as any).data?.filter((module: Module) =>
123
- !planModuleIds.has(module.id)
124
- ) || [];
125
-
126
- return { data: additionalModules };
127
- } catch (error) {
128
- throw new Error('Erreur lors de la r�cup�ration des modules additionnels');
129
- }
130
- }
131
- };
132
-
133
- export default {
134
- ModuleServices,
135
- PlanServices,
136
- SubscriptionServices
137
- };
@@ -1,36 +0,0 @@
1
-
2
- import { API_URL, FetchApi } from "./api";
3
- import { User } from "../models/User";
4
-
5
- const API_BASE_URL = `${API_URL}/core/auth/`;
6
- const USERS_API_URL = `${API_URL}/core/users/`;
7
-
8
- export const UserServices = {
9
- // Créer un nouvel utilisateur
10
- addUser: (data: Partial<User>, token: string) =>
11
- FetchApi.post(`${USERS_API_URL}`, data, token),
12
-
13
- // Obtenir tous les utilisateurs
14
- getUsers: (token: string) =>
15
- FetchApi.get(`${USERS_API_URL}`, token),
16
-
17
- // Obtenir un utilisateur par ID
18
- getUser: (id: number, token: string) =>
19
- FetchApi.get(`${USERS_API_URL}${id}/`, token),
20
-
21
- // Mettre à jour un utilisateur
22
- updateUser: (id: number, data: Partial<User>, token: string) =>
23
- FetchApi.put(`${USERS_API_URL}${id}/`, data, token),
24
-
25
- // Supprimer un utilisateur
26
- deleteUser: (id: number, token: string) =>
27
- FetchApi.delete(`${USERS_API_URL}${id}/`, token),
28
-
29
- // Obtenir les utilisateurs d'une entité
30
- getEntityUsers: (entityId: number, token: string) =>
31
- FetchApi.get(`${API_URL}/core/entities/${entityId}/users/`, token),
32
-
33
- // Ajouter un utilisateur à une entité
34
- addUserToEntity: (entityId: number, userId: number, token: string) =>
35
- FetchApi.post(`${API_URL}/core/entities/${entityId}/users/`, { user_id: userId }, token),
36
- };
@@ -1,64 +0,0 @@
1
- export const ADDRESS_IP = 'localhost:8000';
2
- export const ADDRESS_IP_URL = `http://${ADDRESS_IP}/`;
3
- export const API_URL = `${ADDRESS_IP_URL}api`;
4
-
5
-
6
- export class FetchApi {
7
- static async post<T>(url: string, payload?: any, token?: string): Promise<T> {
8
- const headers: Record<string, string> = {
9
- "Content-Type": "application/json",
10
- };
11
- if (token) {
12
- headers["Authorization"] = `Token ${token}`;
13
- }
14
- const res = await fetch(url, {
15
- method: "POST",
16
- headers,
17
- body: payload ? JSON.stringify(payload) : undefined,
18
- });
19
- if (!res.ok) throw new Error(await res.text());
20
- return res.json();
21
- }
22
-
23
- static async get<T>(url: string, token?: string): Promise<T> {
24
- const headers: Record<string, string> = {};
25
- if (token) {
26
- headers["Authorization"] = `Token ${token}`;
27
- }
28
- const res = await fetch(url, {
29
- method: "GET",
30
- headers,
31
- });
32
- if (!res.ok) throw new Error(await res.text());
33
- return res.json();
34
- }
35
-
36
- static async put<T>(url: string, payload?: any, token?: string): Promise<T> {
37
- const headers: Record<string, string> = {
38
- "Content-Type": "application/json",
39
- };
40
- if (token) {
41
- headers["Authorization"] = `Token ${token}`;
42
- }
43
- const res = await fetch(url, {
44
- method: "PUT",
45
- headers,
46
- body: payload ? JSON.stringify(payload) : undefined,
47
- });
48
- if (!res.ok) throw new Error(await res.text());
49
- return res.json();
50
- }
51
-
52
- static async delete<T>(url: string, token?: string): Promise<T> {
53
- const headers: Record<string, string> = {};
54
- if (token) {
55
- headers["Authorization"] = `Token ${token}`;
56
- }
57
- const res = await fetch(url, {
58
- method: "DELETE",
59
- headers,
60
- });
61
- if (!res.ok) throw new Error(await res.text());
62
- return res.json();
63
- }
64
- }
@@ -1,383 +0,0 @@
1
- // Système de thème moderne pour WiseBook
2
- // 3 palettes de couleurs professionnelles pour application SaaS
3
-
4
- export interface ThemeColors {
5
- primary: string;
6
- primaryHover: string;
7
- primaryLight: string;
8
- secondary: string;
9
- accent: string;
10
- background: string;
11
- surface: string;
12
- surfaceHover: string;
13
- text: {
14
- primary: string;
15
- secondary: string;
16
- tertiary: string;
17
- inverse: string;
18
- };
19
- border: string;
20
- borderLight: string;
21
- success: string;
22
- successLight: string;
23
- error: string;
24
- errorLight: string;
25
- warning: string;
26
- warningLight: string;
27
- info: string;
28
- infoLight: string;
29
- sidebar: {
30
- bg: string;
31
- bgHover: string;
32
- text: string;
33
- textHover: string;
34
- border: string;
35
- active: string;
36
- activeBg: string;
37
- };
38
- card: {
39
- bg: string;
40
- border: string;
41
- shadow: string;
42
- };
43
- }
44
-
45
- export interface Theme {
46
- name: string;
47
- description: string;
48
- colors: ThemeColors;
49
- shadows: {
50
- sm: string;
51
- md: string;
52
- lg: string;
53
- xl: string;
54
- };
55
- transitions: {
56
- fast: string;
57
- normal: string;
58
- slow: string;
59
- };
60
- borderRadius: {
61
- sm: string;
62
- md: string;
63
- lg: string;
64
- xl: string;
65
- full: string;
66
- };
67
- }
68
-
69
- // Palette 1 – Élégance sobre (finance traditionnelle moderne)
70
- const elegantTheme: Theme = {
71
- name: 'Élégance Sobre',
72
- description: 'Finance traditionnelle moderne - sérieux, luxe discret, rassurant',
73
- colors: {
74
- primary: '#2E7D69', // Vert émeraude
75
- primaryHover: '#246456',
76
- primaryLight: 'rgba(46, 125, 105, 0.1)',
77
- secondary: '#D4AF37', // Or pâle
78
- accent: '#D4AF37',
79
- background: '#F5F5F7', // Gris clair neutre
80
- surface: '#FFFFFF',
81
- surfaceHover: '#FAFAFA',
82
- text: {
83
- primary: '#1E1E2F', // Charbon profond
84
- secondary: '#4A4A5C',
85
- tertiary: '#C2C7CE', // Gris moyen
86
- inverse: '#FFFFFF'
87
- },
88
- border: '#E5E5E7',
89
- borderLight: '#F0F0F2',
90
- success: '#2E7D69',
91
- successLight: 'rgba(46, 125, 105, 0.1)',
92
- error: '#DC3545',
93
- errorLight: 'rgba(220, 53, 69, 0.1)',
94
- warning: '#D4AF37',
95
- warningLight: 'rgba(212, 175, 55, 0.1)',
96
- info: '#5B9BD5',
97
- infoLight: 'rgba(91, 155, 213, 0.1)',
98
- sidebar: {
99
- bg: '#1E1E2F',
100
- bgHover: '#252538',
101
- text: '#C2C7CE',
102
- textHover: '#FFFFFF',
103
- border: 'rgba(194, 199, 206, 0.1)',
104
- active: '#2E7D69',
105
- activeBg: 'rgba(46, 125, 105, 0.1)'
106
- },
107
- card: {
108
- bg: '#FFFFFF',
109
- border: '#E5E5E7',
110
- shadow: 'rgba(30, 30, 47, 0.05)'
111
- }
112
- },
113
- shadows: {
114
- sm: '0 1px 3px rgba(30, 30, 47, 0.05)',
115
- md: '0 4px 6px rgba(30, 30, 47, 0.07)',
116
- lg: '0 10px 15px rgba(30, 30, 47, 0.1)',
117
- xl: '0 20px 25px rgba(30, 30, 47, 0.12)'
118
- },
119
- transitions: {
120
- fast: '150ms ease',
121
- normal: '250ms ease',
122
- slow: '350ms ease'
123
- },
124
- borderRadius: {
125
- sm: '4px',
126
- md: '8px',
127
- lg: '12px',
128
- xl: '16px',
129
- full: '9999px'
130
- }
131
- };
132
-
133
- // Palette 2 – Modern Fintech
134
- const fintechTheme: Theme = {
135
- name: 'Modern Fintech',
136
- description: 'Moderne, clair, orienté tableau de bord financier',
137
- colors: {
138
- primary: '#27AE60', // Vert doux
139
- primaryHover: '#219A52',
140
- primaryLight: 'rgba(39, 174, 96, 0.1)',
141
- secondary: '#2C3E50', // Bleu nuit désaturé
142
- accent: '#3498DB',
143
- background: '#FAFAFA', // Blanc cassé
144
- surface: '#FFFFFF',
145
- surfaceHover: '#F8F9FA',
146
- text: {
147
- primary: '#2C3E50',
148
- secondary: '#7F8C8D', // 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', // Rouge bourgogne
157
- errorLight: 'rgba(192, 57, 43, 0.1)',
158
- warning: '#F39C12',
159
- warningLight: 'rgba(243, 156, 18, 0.1)',
160
- info: '#3498DB',
161
- infoLight: 'rgba(52, 152, 219, 0.1)',
162
- sidebar: {
163
- bg: '#2C3E50',
164
- bgHover: '#34495E',
165
- text: '#95A5A6',
166
- textHover: '#FFFFFF',
167
- border: 'rgba(149, 165, 166, 0.1)',
168
- active: '#27AE60',
169
- activeBg: 'rgba(39, 174, 96, 0.1)'
170
- },
171
- card: {
172
- bg: '#FFFFFF',
173
- border: '#E0E6ED',
174
- shadow: 'rgba(44, 62, 80, 0.04)'
175
- }
176
- },
177
- shadows: {
178
- sm: '0 1px 3px rgba(44, 62, 80, 0.04)',
179
- md: '0 4px 6px rgba(44, 62, 80, 0.06)',
180
- lg: '0 10px 15px rgba(44, 62, 80, 0.08)',
181
- xl: '0 20px 25px rgba(44, 62, 80, 0.1)'
182
- },
183
- transitions: {
184
- fast: '150ms ease',
185
- normal: '250ms ease',
186
- slow: '350ms ease'
187
- },
188
- borderRadius: {
189
- sm: '4px',
190
- md: '8px',
191
- lg: '12px',
192
- xl: '16px',
193
- full: '9999px'
194
- }
195
- };
196
-
197
- // Palette 3 – Minimaliste premium (Par défaut)
198
- const minimalistTheme: Theme = {
199
- name: 'Minimaliste Premium',
200
- description: 'Élégance minimaliste avec touche premium',
201
- colors: {
202
- primary: '#6A8A82', // Vert sauge
203
- primaryHover: '#5A7A72',
204
- primaryLight: 'rgba(106, 138, 130, 0.1)',
205
- secondary: '#B87333', // Cuivre rosé
206
- accent: '#B87333',
207
- background: '#ECECEC', // Gris clair perle
208
- surface: '#FFFFFF',
209
- surfaceHover: '#FAFAFA',
210
- text: {
211
- primary: '#191919', // Noir fumé
212
- secondary: '#444444', // Anthracite doux
213
- tertiary: '#767676',
214
- inverse: '#FFFFFF'
215
- },
216
- border: '#D9D9D9',
217
- borderLight: '#E8E8E8',
218
- success: '#6A8A82',
219
- successLight: 'rgba(106, 138, 130, 0.1)',
220
- error: '#B85450',
221
- errorLight: 'rgba(184, 84, 80, 0.1)',
222
- warning: '#B87333',
223
- warningLight: 'rgba(184, 115, 51, 0.1)',
224
- info: '#7A99AC',
225
- infoLight: 'rgba(122, 153, 172, 0.1)',
226
- sidebar: {
227
- bg: '#191919',
228
- bgHover: '#242424',
229
- text: '#999999',
230
- textHover: '#FFFFFF',
231
- border: 'rgba(153, 153, 153, 0.1)',
232
- active: '#B87333',
233
- activeBg: 'rgba(184, 115, 51, 0.1)'
234
- },
235
- card: {
236
- bg: '#FFFFFF',
237
- border: '#D9D9D9',
238
- shadow: 'rgba(25, 25, 25, 0.03)'
239
- }
240
- },
241
- shadows: {
242
- sm: '0 1px 3px rgba(25, 25, 25, 0.03)',
243
- md: '0 4px 6px rgba(25, 25, 25, 0.05)',
244
- lg: '0 10px 15px rgba(25, 25, 25, 0.07)',
245
- xl: '0 20px 25px rgba(25, 25, 25, 0.09)'
246
- },
247
- transitions: {
248
- fast: '150ms ease',
249
- normal: '250ms ease',
250
- slow: '350ms ease'
251
- },
252
- borderRadius: {
253
- sm: '4px',
254
- md: '8px',
255
- lg: '12px',
256
- xl: '16px',
257
- full: '9999px'
258
- }
259
- };
260
-
261
- // Palette 4 – Neutral Odyssey (Immobilier haut de gamme)
262
- const neutralOdysseyTheme: Theme = {
263
- name: 'Neutral Odyssey',
264
- description: 'Palette haut de gamme pour immobilier - élégance neutre et moderne',
265
- colors: {
266
- primary: '#373B4D', // Gris profond, élégant - Actions fortes
267
- primaryHover: '#2C2F3D', // Version plus sombre pour hover
268
- primaryLight: 'rgba(55, 59, 77, 0.1)',
269
- secondary: '#BDBFB7', // Accents - éléments surlignés, cartes de projet
270
- accent: '#BDBFB7',
271
- background: '#ECEDEF', // Fond clair principal
272
- surface: '#ECECEF', // Surface des cartes et panneaux
273
- surfaceHover: '#E6E6E9',
274
- text: {
275
- primary: '#373B4D', // Texte principal sur fond clair
276
- secondary: '#949597', // Texte secondaire / icônes
277
- tertiary: '#BDBFB7', // Texte tertiaire
278
- inverse: '#ECECEF' // Texte sur fond sombre
279
- },
280
- border: '#BDBFB7', // Bordures principales
281
- borderLight: '#E0E0E3', // Bordures légères
282
- success: '#6A8A82', // Réutilisation du vert sauge pour succès
283
- successLight: 'rgba(106, 138, 130, 0.1)',
284
- error: '#B85450',
285
- errorLight: 'rgba(184, 84, 80, 0.1)',
286
- warning: '#D4AF37', // Or pour les avertissements
287
- warningLight: 'rgba(212, 175, 55, 0.1)',
288
- info: '#7A99AC',
289
- infoLight: 'rgba(122, 153, 172, 0.1)',
290
- sidebar: {
291
- bg: 'linear-gradient(180deg, #ECECEF 0%, #ECEDEF 100%)', // Dégradé vertical
292
- bgHover: '#E6E6E9',
293
- text: '#373B4D', // Icônes et texte en gris profond
294
- textHover: '#2C2F3D', // Plus sombre au hover
295
- border: 'rgba(189, 191, 183, 0.2)',
296
- active: '#373B4D', // État actif en couleur principale
297
- activeBg: 'rgba(55, 59, 77, 0.1)'
298
- },
299
- card: {
300
- bg: '#ECEDEF', // Cartes sur fond légèrement différent
301
- border: '#BDBFB7', // Encadrement des cartes
302
- shadow: 'rgba(55, 59, 77, 0.08)'
303
- }
304
- },
305
- shadows: {
306
- sm: '0 1px 3px rgba(55, 59, 77, 0.08)',
307
- md: '0 4px 6px rgba(55, 59, 77, 0.10)',
308
- lg: '0 10px 15px rgba(55, 59, 77, 0.12)',
309
- xl: '0 20px 25px rgba(55, 59, 77, 0.15)'
310
- },
311
- transitions: {
312
- fast: '150ms ease',
313
- normal: '250ms ease',
314
- slow: '350ms ease'
315
- },
316
- borderRadius: {
317
- sm: '4px',
318
- md: '8px',
319
- lg: '12px',
320
- xl: '16px',
321
- full: '9999px'
322
- }
323
- };
324
-
325
- // Thèmes disponibles
326
- export const themes = {
327
- elegant: elegantTheme,
328
- fintech: fintechTheme,
329
- minimalist: minimalistTheme,
330
- neutralOdyssey: neutralOdysseyTheme
331
- };
332
-
333
- // Thème par défaut
334
- export const defaultTheme = minimalistTheme;
335
-
336
- // Helper pour obtenir les variables CSS d'un thème
337
- export const getThemeCSSVariables = (theme: Theme) => {
338
- return {
339
- '--color-primary': theme.colors.primary,
340
- '--color-primary-hover': theme.colors.primaryHover,
341
- '--color-primary-light': theme.colors.primaryLight,
342
- '--color-secondary': theme.colors.secondary,
343
- '--color-accent': theme.colors.accent,
344
- '--color-background': theme.colors.background,
345
- '--color-surface': theme.colors.surface,
346
- '--color-surface-hover': theme.colors.surfaceHover,
347
- '--color-text-primary': theme.colors.text.primary,
348
- '--color-text-secondary': theme.colors.text.secondary,
349
- '--color-text-tertiary': theme.colors.text.tertiary,
350
- '--color-text-inverse': theme.colors.text.inverse,
351
- '--color-border': theme.colors.border,
352
- '--color-border-light': theme.colors.borderLight,
353
- '--color-success': theme.colors.success,
354
- '--color-success-light': theme.colors.successLight,
355
- '--color-error': theme.colors.error,
356
- '--color-error-light': theme.colors.errorLight,
357
- '--color-warning': theme.colors.warning,
358
- '--color-warning-light': theme.colors.warningLight,
359
- '--color-info': theme.colors.info,
360
- '--color-info-light': theme.colors.infoLight,
361
- '--shadow-sm': theme.shadows.sm,
362
- '--shadow-md': theme.shadows.md,
363
- '--shadow-lg': theme.shadows.lg,
364
- '--shadow-xl': theme.shadows.xl,
365
- '--transition-fast': theme.transitions.fast,
366
- '--transition-normal': theme.transitions.normal,
367
- '--transition-slow': theme.transitions.slow,
368
- '--radius-sm': theme.borderRadius.sm,
369
- '--radius-md': theme.borderRadius.md,
370
- '--radius-lg': theme.borderRadius.lg,
371
- '--radius-xl': theme.borderRadius.xl,
372
- '--radius-full': theme.borderRadius.full
373
- };
374
- };
375
-
376
- // Types pour le contexte du thème
377
- export type ThemeType = 'elegant' | 'fintech' | 'minimalist' | 'neutralOdyssey';
378
-
379
- export interface ThemeContextValue {
380
- theme: Theme;
381
- themeType: ThemeType;
382
- setTheme: (type: ThemeType) => void;
383
- }
@@ -1,48 +0,0 @@
1
- import { type ClassValue, clsx } from "clsx"
2
- import { twMerge } from "tailwind-merge"
3
-
4
- export function cn(...inputs: ClassValue[]) {
5
- return twMerge(clsx(inputs))
6
- }
7
-
8
- export function formatCurrency(amount: number, currency: string = 'XAF') {
9
- if (currency === 'XAF') {
10
- return new Intl.NumberFormat('fr-FR', {
11
- minimumFractionDigits: 0,
12
- maximumFractionDigits: 0,
13
- }).format(amount) + ' XAF';
14
- }
15
- return new Intl.NumberFormat('fr-FR').format(amount) + ' ' + currency;
16
- }
17
-
18
- export function formatDate(date: string | Date | undefined) {
19
- if (!date) return 'Non défini';
20
-
21
- try {
22
- const dateObj = typeof date === 'string' ? new Date(date) : date;
23
-
24
- // Vérifier si la date est valide
25
- if (isNaN(dateObj.getTime())) {
26
- return 'Date invalide';
27
- }
28
-
29
- return dateObj.toLocaleDateString('fr-FR', {
30
- year: 'numeric',
31
- month: 'long',
32
- day: 'numeric'
33
- });
34
- } catch (error) {
35
- return 'Erreur de format';
36
- }
37
- }
38
-
39
- export function formatPercentage(value: number, decimals: number = 1) {
40
- return (value).toFixed(decimals) + '%';
41
- }
42
-
43
- export function formatPercent(value: number | null | undefined, decimals: number = 1) {
44
- if (value === null || value === undefined || isNaN(value)) {
45
- return '0.0%';
46
- }
47
- return value.toFixed(decimals) + '%';
48
- }
package/src/vite-env.d.ts DELETED
@@ -1 +0,0 @@
1
- /// <reference types="vite/client" />