From d83b7ad4e7acf1d7d7d5a6007ed07698f57c8a7c Mon Sep 17 00:00:00 2001 From: LathanDevers Date: Thu, 25 Jun 2026 10:50:49 +0200 Subject: [PATCH] upgrade design --- src/components/services/VpsManager.jsx | 48 ++++++- src/components/services/WebManager.jsx | 74 +++++++++-- src/layouts/AppLayout.jsx | 175 ++++++------------------- src/layouts/PublicLayout.jsx | 31 ++--- src/pages/app/Services.jsx | 13 +- src/pages/public/Home.jsx | 60 ++------- src/pages/public/Login.jsx | 68 +++------- src/pages/public/Register.jsx | 109 +++++---------- src/pages/public/login.old.jsx | 90 ------------- 9 files changed, 226 insertions(+), 442 deletions(-) delete mode 100644 src/pages/public/login.old.jsx diff --git a/src/components/services/VpsManager.jsx b/src/components/services/VpsManager.jsx index f4890d5..d39a3a1 100644 --- a/src/components/services/VpsManager.jsx +++ b/src/components/services/VpsManager.jsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Folder, ExternalLink, Play, Maximize2, Lock } from 'lucide-react'; +import { Folder, ExternalLink, Play, Maximize2, Lock, Copy, Check } from 'lucide-react'; export default function VpsManager({ details, orderId, onRefresh, onAlert }) { const [showTerminal, setShowTerminal] = useState(false); @@ -7,11 +7,18 @@ export default function VpsManager({ details, orderId, onRefresh, onAlert }) { const [newDomain, setNewDomain] = useState(details.domain); const [isUpdating, setIsUpdating] = useState(false); const [sslStatus, setSslStatus] = useState(null); + const [copiedField, setCopiedField] = useState(null); const isInternal = details.domain && details.domain.endsWith('.gise.be'); const fileManagerUrl = isInternal ? `https://file-${details.domain}` : `http://${details.domain}:8080`; const terminalUrl = isInternal ? `https://terminal-${details.domain}` : `http://${details.domain}:8081`; + const handleCopy = (text, field) => { + navigator.clipboard.writeText(text); + setCopiedField(field); + setTimeout(() => setCopiedField(null), 2000); + }; + const handleUpdateDomain = async () => { if (!newDomain || newDomain === details.domain) return; setIsUpdating(true); @@ -62,7 +69,44 @@ export default function VpsManager({ details, orderId, onRefresh, onAlert }) { )} -
+ + {/* ENCART DES IDENTIFIANTS */} +
+
+ + Accès Explorateur + +
+ User: root + +
+
+ Pass: NexusGise2026! + +
+
+
+ + Accès Console / SSH + +
+ User: root + +
+
+ Pass: Défini à l'installation +
+
+
+ + {/* BOUTONS D'ACTIONS */} +
diff --git a/src/components/services/WebManager.jsx b/src/components/services/WebManager.jsx index 3f47354..3d06cf4 100644 --- a/src/components/services/WebManager.jsx +++ b/src/components/services/WebManager.jsx @@ -1,17 +1,28 @@ import { useState } from 'react'; -import { Globe, ExternalLink, Lock, Loader } from 'lucide-react'; +import { Globe, ExternalLink, Lock, Loader, Copy, Check } from 'lucide-react'; import { resetHostingPassword } from '../../services/api'; -export default function WebManager({ details, orderId, onRefresh, onOpenSso, onAlert }) { +export default function WebManager({ details, orderId, onRefresh, onAlert }) { const [isEditingDomain, setIsEditingDomain] = useState(false); const [newDomain, setNewDomain] = useState(details.domain); const [isUpdating, setIsUpdating] = useState(false); const [sslStatus, setSslStatus] = useState(null); + + // Nouveaux états pour gérer les accès localement const [isGeneratingSso, setIsGeneratingSso] = useState(false); + const [ssoData, setSsoData] = useState(null); + const [copiedField, setCopiedField] = useState(null); const isCustomDomain = details.domain && !details.domain.endsWith('.gise.be'); const siteUrl = (isCustomDomain && sslStatus !== 'success') ? `http://${details.domain}` : `https://${details.domain}`; + // Fonction utilitaire pour copier + const handleCopy = (text, field) => { + navigator.clipboard.writeText(text); + setCopiedField(field); + setTimeout(() => setCopiedField(null), 2000); + }; + const handleUpdateDomain = async () => { if (!newDomain || newDomain === details.domain) return; setIsUpdating(true); @@ -39,9 +50,12 @@ export default function WebManager({ details, orderId, onRefresh, onOpenSso, onA const secureHash = Math.random().toString(36).slice(-8) + Math.random().toString(36).slice(-4).toUpperCase(); const rollingPassword = `Nx${secureHash}`; await resetHostingPassword(orderId, rollingPassword); - onOpenSso({ username: details.username, password: rollingPassword, url: 'https://panel.gise.be/login/' }); - } catch (err) { onAlert("Erreur Métal", "Erreur lors de la génération du SSO HestiaCP.", "error"); } - finally { setIsGeneratingSso(false); } + setSsoData({ username: details.username, password: rollingPassword, url: 'https://panel.gise.be/login/' }); + } catch (err) { + onAlert("Erreur Métal", "Erreur lors de la génération du SSO HestiaCP.", "error"); + } finally { + setIsGeneratingSso(false); + } }; return ( @@ -50,7 +64,9 @@ export default function WebManager({ details, orderId, onRefresh, onOpenSso, onA {!isEditingDomain ? (
- {details.domain} + + {details.domain} +
) : ( @@ -60,6 +76,7 @@ export default function WebManager({ details, orderId, onRefresh, onOpenSso, onA
)} + {isCustomDomain && (

Domaine personnalisé détecté.

@@ -69,13 +86,48 @@ export default function WebManager({ details, orderId, onRefresh, onOpenSso, onA
)}
-
+ +
- + + {/* ZONE DES ACCÈS PANEL */} + {!ssoData ? ( + + ) : ( +
+

+ Accès Panel Généré +

+ +
+
+ User: {ssoData.username} + +
+ +
+ Pass: {ssoData.password} + +
+
+ + +
+ )}
); diff --git a/src/layouts/AppLayout.jsx b/src/layouts/AppLayout.jsx index 7342376..25bfa7b 100644 --- a/src/layouts/AppLayout.jsx +++ b/src/layouts/AppLayout.jsx @@ -1,12 +1,8 @@ -// src/layouts/AppLayout.jsx import { useState, useEffect } from 'react'; import { Outlet, NavLink, useNavigate } from 'react-router-dom'; import { getClientTickets } from '../services/api'; -import ConfirmLogoutModal from '../components/ui/ConfirmLogoutModal'; +import ConfirmLogoutModal from '../components/ui/ConfirmLogoutModal'; // Le modal extrait ! -// ============================================================================ -// COMPOSANT PRINCIPAL : LAYOUT DU PORTAIL -// ============================================================================ export default function AppLayout() { const navigate = useNavigate(); const [showLogoutModal, setShowLogoutModal] = useState(false); @@ -16,187 +12,98 @@ export default function AppLayout() { try { const data = await getClientTickets(); if (data && data.list) { - // On cherche les tickets qui ont le statut 'on_hold' const unread = data.list.filter(t => t.status === 'on_hold' || t.unread).length; setUnreadCount(unread); } - } catch (err) { - // Erreur silencieuse : on ne pollue pas l'écran si le réseau saute - } + } catch (err) {} }; + useEffect(() => { - checkUnreadTickets(); // Premier check immédiat - const intervalId = setInterval(checkUnreadTickets, 120000); // Check toutes les 2 minutes + checkUnreadTickets(); + const intervalId = setInterval(checkUnreadTickets, 120000); return () => clearInterval(intervalId); }, []); - // 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' - }); + // 🌟 La fonction magique Tailwind pour les liens du menu + const navLinkClass = ({ isActive }) => + `block px-6 py-4 no-underline border-l-4 transition-all uppercase tracking-widest text-sm font-mono ${ + isActive + ? 'text-cyan-400 bg-cyan-400/5 border-cyan-400' + : 'text-[#888] border-transparent hover:text-gray-300 hover:bg-white/5' + }`; return ( -
- - {/* ========================================== */} - {/* BARRE LATÉRALE (SIDEBAR) */} - {/* ========================================== */} -