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.
- package/dist/index.cjs +1317 -0
- package/dist/index.d.cts +45 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +1288 -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
|
@@ -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
|
-
};
|
package/src/services/api.ts
DELETED
|
@@ -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
|
-
}
|
package/src/styles/theme.ts
DELETED
|
@@ -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
|
-
}
|
package/src/utils/utils.ts
DELETED
|
@@ -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" />
|