From bfa3161646c4d92cee9fd8e7bbcb7fa3ab61f3c4 Mon Sep 17 00:00:00 2001 From: maximus Date: Fri, 12 Jun 2026 15:53:16 +0200 Subject: [PATCH] ajout du dashboard --- src/App.jsx | 52 ++++-- src/components/ProtectedRoute.jsx | 19 ++ src/layouts/AppLayout.jsx | 111 ++++++++++++ src/layouts/PublicLayout.jsx | 2 +- src/pages/app/Dashboard.jsx | 285 +++++++++++++++--------------- src/pages/app/Services.jsx | 0 src/pages/public/Home.jsx | 2 +- src/pages/public/Login.jsx | 85 ++++++--- src/pages/public/Offres.jsx | 0 src/pages/public/Register.jsx | 39 +++- 10 files changed, 400 insertions(+), 195 deletions(-) create mode 100644 src/components/ProtectedRoute.jsx create mode 100644 src/layouts/AppLayout.jsx create mode 100644 src/pages/app/Services.jsx create mode 100644 src/pages/public/Offres.jsx diff --git a/src/App.jsx b/src/App.jsx index a79ea88..b15ffd9 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,29 +1,53 @@ // src/App.jsx import { BrowserRouter, Routes, Route } from 'react-router-dom'; -import PublicLayout from './layouts/PublicLayout'; -import Home from './pages/public/Home'; -import Login from './pages/public/Login'; -import Dashboard from './pages/app/Dashboard'; -import Register from './pages/public/Register'; -function App() { +// Import des Layouts +import PublicLayout from './layouts/PublicLayout'; +import AppLayout from './layouts/AppLayout'; + +// Import du Garde du Corps +import ProtectedRoute from './components/ProtectedRoute'; + +// Import des Pages Publiques +import Register from './pages/public/Register'; +import Login from './pages/public/Login'; +import Home from './pages/public/Home'; +//import Offres from './pages/public/Offres'; + +// Import des Pages Privées (Espace Client) +import Dashboard from './pages/app/Dashboard'; +//import Services from './pages/app/Services'; + +export default function App() { return ( - {/* === ROUTES PUBLIQUES (Utilisent le PublicLayout) === */} + + {/* ========================================== */} + {/* ZONE PUBLIQUE (Accès Libre) */} + {/* ========================================== */} }> } /> + {/* } /> */} } /> } /> - {/* Tu pourras ajouter /offres, /register ici plus tard */} - {/* === ROUTES PRIVÉES (Espace Client) === */} - {/* Pour l'instant on les met à nu, on créera un AppLayout et un système de sécurité plus tard */} - } /> + {/* ========================================== */} + {/* ZONE PRIVÉE SÉCURISÉE (Le Bunker) */} + {/* ========================================== */} + {/* Le Garde du corps bloque l'entrée ici */} + }> + + {/* Si autorisé, on charge l'interface avec la Sidebar */} + }> + } /> + {/* } /> */} + + + + ); -} - -export default App; \ No newline at end of file +} \ No newline at end of file diff --git a/src/components/ProtectedRoute.jsx b/src/components/ProtectedRoute.jsx new file mode 100644 index 0000000..1fb9eff --- /dev/null +++ b/src/components/ProtectedRoute.jsx @@ -0,0 +1,19 @@ +// src/components/ProtectedRoute.jsx +import { Navigate, Outlet } from 'react-router-dom'; + +export default function ProtectedRoute() { + // 1. VÉRIFICATION DU BADGE D'ACCÈS + // Pour l'instant, on regarde si un jeton "gise_token" existe dans le navigateur. + // (Lors de ta vraie fonction de connexion, tu enregistreras le token de FOSSBilling ici) + const isAuthenticated = localStorage.getItem('gise_token'); + + // 2. DÉCISION DE SÉCURITÉ + if (!isAuthenticated) { + // ALERTE INTRUSION : On renvoie l'utilisateur vers la porte d'entrée + // Le "replace" efface la tentative de l'historique du navigateur + return ; + } + + // ACCÈS AUTORISÉ : On affiche les routes enfants (Le Dashboard, l'AppLayout...) + return ; +} \ No newline at end of file diff --git a/src/layouts/AppLayout.jsx b/src/layouts/AppLayout.jsx new file mode 100644 index 0000000..bca9457 --- /dev/null +++ b/src/layouts/AppLayout.jsx @@ -0,0 +1,111 @@ +// src/layouts/AppLayout.jsx +import { Outlet, NavLink, useNavigate } from 'react-router-dom'; + +export default function AppLayout() { + const navigate = useNavigate(); + + const handleLogout = () => { + // Ici, tu pourras ajouter la logique de déconnexion (effacer les cookies/tokens) + alert("[ DÉCONNEXION EN COURS... ]"); + navigate('/login'); + }; + + // --- DESIGN SYSTEM DU BUNKER --- + const sidebarStyle = { + width: '260px', + backgroundColor: '#121212', // Gris blindage + borderRight: '1px solid #222222', + height: '100vh', + display: 'flex', + flexDirection: 'column', + position: 'fixed', + top: 0, + left: 0, + fontFamily: 'monospace' + }; + + const mainContentStyle = { + marginLeft: '260px', // Laisse la place à la sidebar + minHeight: '100vh', + backgroundColor: '#050505', // Fond abyssal + color: '#E0E0E0', + padding: '40px' + }; + + // Fonction pour styliser le lien actif (en Cyan) + const getNavLinkStyle = ({ isActive }) => ({ + display: 'block', + padding: '15px 25px', + color: isActive ? '#00E5FF' : '#888', + backgroundColor: isActive ? 'rgba(0, 229, 255, 0.05)' : 'transparent', + textDecoration: 'none', + borderLeft: isActive ? '4px solid #00E5FF' : '4px solid transparent', + transition: 'all 0.2s', + textTransform: 'uppercase', + letterSpacing: '1px', + fontSize: '0.9rem' + }); + + return ( +
+ + {/* ========================================== */} + {/* BARRE LATÉRALE (SIDEBAR) */} + {/* ========================================== */} + + + {/* ========================================== */} + {/* ZONE DE CONTENU DYNAMIQUE */} + {/* ========================================== */} +
+ {/* Le composant est magique : + C'est ici que React Router va injecter le contenu de la page demandée + (Dashboard, Settings, etc.) sans jamais recharger la barre latérale ! + */} + +
+ +
+ ); +} \ No newline at end of file diff --git a/src/layouts/PublicLayout.jsx b/src/layouts/PublicLayout.jsx index 5b6d521..6c619b6 100644 --- a/src/layouts/PublicLayout.jsx +++ b/src/layouts/PublicLayout.jsx @@ -5,7 +5,7 @@ export default function PublicLayout() { return (