Files
portail-gise/src/layouts/AppLayout.jsx
T
maximus da7ee2ba1a
Deploy Nexus Portal to HestiaCP (FTP) / build-and-deploy (push) Has been cancelled
unify design
2026-06-24 20:21:16 +02:00

194 lines
6.7 KiB
React

// src/layouts/AppLayout.jsx
import { useState } from 'react';
import { Outlet, NavLink, useNavigate } from 'react-router-dom';
// ============================================================================
// COMPOSANT : MODAL DE CONFIRMATION DE DÉCONNEXION
// ============================================================================
const ConfirmLogoutModal = ({ isOpen, onClose, onConfirm }) => {
if (!isOpen) return null;
return (
<div style={{
position: 'fixed', top: 0, left: 0, right: 0, bottom: 0,
backgroundColor: 'rgba(0,0,0,0.8)', backdropFilter: 'blur(4px)',
zIndex: 100, display: 'flex', alignItems: 'center', justifyContent: 'center'
}}>
<div style={{
backgroundColor: '#1A1A1A',
border: '1px solid #ff003c',
boxShadow: '0 10px 30px rgba(255, 0, 60, 0.2)',
borderRadius: '8px',
maxWidth: '400px',
width: '100%',
padding: '24px',
color: '#FFF',
fontFamily: 'monospace'
}}>
<h4 style={{ fontSize: '1.1rem', fontWeight: 'bold', letterSpacing: '1px', marginBottom: '10px', color: '#ff003c', textTransform: 'uppercase' }}>
DÉCONNEXION DU TERMINAL
</h4>
<p style={{ fontSize: '0.9rem', color: '#AAA', marginBottom: '24px', lineHeight: '1.5' }}>
Êtes-vous sûr de vouloir fermer la session sécurisée et quitter l'environnement cloud ?
</p>
<div style={{ display: 'flex', gap: '10px' }}>
<button onClick={onClose} style={{
flex: 1, padding: '10px',
backgroundColor: '#333', color: '#FFF',
border: 'none', borderRadius: '4px',
fontFamily: 'monospace', fontWeight: 'bold', cursor: 'pointer', letterSpacing: '1px'
}}>
ANNULER
</button>
<button onClick={onConfirm} style={{
flex: 1, padding: '10px',
backgroundColor: '#ff003c', color: '#FFF',
border: 'none', borderRadius: '4px',
fontFamily: 'monospace', fontWeight: 'bold', cursor: 'pointer', letterSpacing: '1px'
}}>
SE DÉCONNECTER
</button>
</div>
</div>
</div>
);
};
// ============================================================================
// COMPOSANT PRINCIPAL : LAYOUT DU PORTAIL
// ============================================================================
export default function AppLayout() {
const navigate = useNavigate();
const [showLogoutModal, setShowLogoutModal] = useState(false);
// Ouvre simplement le modal
const handleLogoutClick = () => {
setShowLogoutModal(true);
};
// Exécute la vraie déconnexion
const confirmLogout = () => {
// Ici, tu pourras effacer les tokens (ex: localStorage.removeItem('token'))
setShowLogoutModal(false);
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 (
<div style={{ display: 'block' }}>
{/* ========================================== */}
{/* BARRE LATÉRALE (SIDEBAR) */}
{/* ========================================== */}
<aside style={sidebarStyle}>
{/* En-tête de la Sidebar (Logo / Marque) */}
<div style={{ padding: '30px 25px', borderBottom: '1px solid #222' }}>
<h1 style={{
color: '#FFF',
margin: 0,
fontSize: '1.8rem',
letterSpacing: '3px',
display: 'flex',
alignItems: 'baseline',
gap: '8px'
}}>
NEXUS
<span style={{
color: '#00E5FF',
fontSize: '0.7rem',
letterSpacing: '1px',
fontWeight: 'normal',
}}>
by GISE
</span>
</h1>
<p style={{ color: '#555', fontSize: '0.7rem', margin: '8px 0 0 0' }}>
CONSOLE D'INFRASTRUCTURE v1.0
</p>
</div>
{/* Menu de Navigation */}
<nav style={{ flex: 1, marginTop: '20px' }}>
<div style={{ padding: '0 25px', marginBottom: '10px', color: '#444', fontSize: '0.7rem', fontWeight: 'bold' }}>
// SUPERVISION
</div>
<NavLink style={getNavLinkStyle} to="/dashboard">Tableau de bord</NavLink>
<NavLink style={getNavLinkStyle} to="/services">Inventaire Réseau</NavLink>
<div style={{ padding: '0 25px', marginTop: '25px', marginBottom: '10px', color: '#444', fontSize: '0.7rem', fontWeight: 'bold' }}>
// GESTION
</div>
<NavLink style={getNavLinkStyle} to="/billing">Facturation</NavLink>
<NavLink style={getNavLinkStyle} to="/support">Tickets Support</NavLink>
<NavLink style={getNavLinkStyle} to="/settings">Profil & Sécurité</NavLink>
</nav>
{/* Bas de la Sidebar (Déconnexion) */}
<div style={{ padding: '20px', borderTop: '1px solid #222' }}>
<button
onClick={handleLogoutClick}
style={{
width: '100%', padding: '12px', backgroundColor: 'transparent',
color: '#ff003c', border: '1px solid #ff003c', cursor: 'pointer',
fontFamily: 'monospace', textTransform: 'uppercase'
}}
>
[ Déconnexion ]
</button>
</div>
</aside>
{/* ========================================== */}
{/* ZONE DE CONTENU DYNAMIQUE */}
{/* ========================================== */}
<main style={mainContentStyle}>
{/* Le composant <Outlet /> injecte le contenu de la page demandée sans recharger la sidebar */}
<Outlet />
</main>
{/* MODAL DE DÉCONNEXION */}
<ConfirmLogoutModal
isOpen={showLogoutModal}
onClose={() => setShowLogoutModal(false)}
onConfirm={confirmLogout}
/>
</div>
);
}