From 6b93d21d1931b26911b9fcd7860f41160ba993f4 Mon Sep 17 00:00:00 2001 From: LathanDevers Date: Fri, 31 Jul 2026 21:37:56 +0200 Subject: [PATCH] add useDocuments and load saved documents in DocumentsVault --- src/App.css | 184 ------------------ src/components/layout/Sidebar.tsx | 14 +- src/components/ui/Card.tsx | 5 +- src/components/ui/ServiceObject.tsx | 2 +- src/components/ui/ThemeToggle.tsx | 52 +++++ src/components/ui/UptimeObject.tsx | 38 ++-- src/components/widgets/DocumentsWidget.tsx | 77 ++++++++ .../widgets/EvolutionOptionCard.tsx | 2 +- src/components/widgets/UptimeWidget.tsx | 16 +- src/hooks/useDocuments.ts | 31 +++ src/hooks/useTheme.ts | 42 ++++ src/index.css | 2 + src/pages/DocumentVault.tsx | 84 ++------ src/pages/ServiceDesk.tsx | 4 +- src/styles/Neumorphism.ts | 14 +- src/types/Document.ts | 7 + 16 files changed, 280 insertions(+), 294 deletions(-) create mode 100644 src/components/ui/ThemeToggle.tsx create mode 100644 src/components/widgets/DocumentsWidget.tsx create mode 100644 src/hooks/useDocuments.ts create mode 100644 src/hooks/useTheme.ts create mode 100644 src/types/Document.ts diff --git a/src/App.css b/src/App.css index f90339d..e69de29 100644 --- a/src/App.css +++ b/src/App.css @@ -1,184 +0,0 @@ -.counter { - font-size: 16px; - padding: 5px 10px; - border-radius: 5px; - color: var(--accent); - background: var(--accent-bg); - border: 2px solid transparent; - transition: border-color 0.3s; - margin-bottom: 24px; - - &:hover { - border-color: var(--accent-border); - } - &:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } -} - -.hero { - position: relative; - - .base, - .framework, - .vite { - inset-inline: 0; - margin: 0 auto; - } - - .base { - width: 170px; - position: relative; - z-index: 0; - } - - .framework, - .vite { - position: absolute; - } - - .framework { - z-index: 1; - top: 34px; - height: 28px; - transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg) - scale(1.4); - } - - .vite { - z-index: 0; - top: 107px; - height: 26px; - width: auto; - transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg) - scale(0.8); - } -} - -#center { - display: flex; - flex-direction: column; - gap: 25px; - place-content: center; - place-items: center; - flex-grow: 1; - - @media (max-width: 1024px) { - padding: 32px 20px 24px; - gap: 18px; - } -} - -#next-steps { - display: flex; - border-top: 1px solid var(--border); - text-align: left; - - & > div { - flex: 1 1 0; - padding: 32px; - @media (max-width: 1024px) { - padding: 24px 20px; - } - } - - .icon { - margin-bottom: 16px; - width: 22px; - height: 22px; - } - - @media (max-width: 1024px) { - flex-direction: column; - text-align: center; - } -} - -#docs { - border-right: 1px solid var(--border); - - @media (max-width: 1024px) { - border-right: none; - border-bottom: 1px solid var(--border); - } -} - -#next-steps ul { - list-style: none; - padding: 0; - display: flex; - gap: 8px; - margin: 32px 0 0; - - .logo { - height: 18px; - } - - a { - color: var(--text-h); - font-size: 16px; - border-radius: 6px; - background: var(--social-bg); - display: flex; - padding: 6px 12px; - align-items: center; - gap: 8px; - text-decoration: none; - transition: box-shadow 0.3s; - - &:hover { - box-shadow: var(--shadow); - } - .button-icon { - height: 18px; - width: 18px; - } - } - - @media (max-width: 1024px) { - margin-top: 20px; - flex-wrap: wrap; - justify-content: center; - - li { - flex: 1 1 calc(50% - 8px); - } - - a { - width: 100%; - justify-content: center; - box-sizing: border-box; - } - } -} - -#spacer { - height: 88px; - border-top: 1px solid var(--border); - @media (max-width: 1024px) { - height: 48px; - } -} - -.ticks { - position: relative; - width: 100%; - - &::before, - &::after { - content: ''; - position: absolute; - top: -4.5px; - border: 5px solid transparent; - } - - &::before { - left: 0; - border-left-color: var(--border); - } - &::after { - right: 0; - border-right-color: var(--border); - } -} diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 4475348..86f3a35 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -4,6 +4,8 @@ import { Shield, ShieldCheck, HelpCircle, Lock, Settings, LogOut } from 'lucide- import { cn } from '@/utils/utils'; import { Card } from '@/components/ui/Card'; import { NEUMORPHISM } from '@/styles/Neumorphism'; +import { useTheme } from '@/hooks/useTheme'; +import { ThemeToggle } from '@ui/ThemeToggle'; interface SidebarProps { onLogout: () => void; @@ -21,20 +23,21 @@ const NAVIGATION_ITEMS = [ export const Sidebar: React.FC = ({ onLogout, className }) => { + const { isDark, toggleTheme } = useTheme(); return ( {/* 1. EN-TÊTE / LOGO */}
{/* Petit badge logo avec effet creusé */}
- +
-

AEGIS

- by GISE +

AEGIS

+ by GISE
@@ -52,7 +55,7 @@ export const Sidebar: React.FC = ({ onLogout, className }) => { "w-full flex items-center gap-4 px-5 py-4 rounded-2xl transition-all duration-300 ease-in-out cursor-pointer", "bg-[#e8e8e8] dark:bg-[#1e293b]", isActive - ? cn(NEUMORPHISM.insetLight, NEUMORPHISM.insetDark, "!text-blue-600 dark:!text-blue-400 font-black") + ? cn(NEUMORPHISM.insetLight, NEUMORPHISM.insetDark, "text-blue-600! dark:text-blue-400! font-black") : cn(NEUMORPHISM.lightShadow, NEUMORPHISM.darkShadow, "text-slate-500 dark:text-slate-400 font-bold hover:text-slate-700 dark:hover:text-slate-200") ) } @@ -74,6 +77,7 @@ export const Sidebar: React.FC = ({ onLogout, className }) => { })} + {/* 3. ZONE DE DÉCONNEXION */}
+ ); +} \ No newline at end of file diff --git a/src/components/ui/UptimeObject.tsx b/src/components/ui/UptimeObject.tsx index 12cccaf..4955564 100644 --- a/src/components/ui/UptimeObject.tsx +++ b/src/components/ui/UptimeObject.tsx @@ -1,6 +1,7 @@ import React from 'react'; import type { InfrastructureNode } from '@/types/InfrastructureNode'; import { StatusBadge } from '@ui/StatusBadge'; +import { cn } from '@/utils/utils'; interface UptimeObjectProps { node: InfrastructureNode; @@ -9,24 +10,25 @@ interface UptimeObjectProps { export const UptimeObject: React.FC = ({ node }) => { return ( // La "key" a été retirée d'ici, elle sera gérée par le parent -
- - {/* Infos Serveur */} -
-

{node.label}

-

{node.type}

-
- - {/* Métriques & Badge */} -
-
-

SLA

-

{node.uptime_sla}

-
- - -
+ -
+ {/* Infos Serveur */} + +

{node.label}

+

{node.type}

+ + + {/* Métriques & Badge */} + +

SLA

+

{node.uptime_sla}

+ + + + + + ); }; \ No newline at end of file diff --git a/src/components/widgets/DocumentsWidget.tsx b/src/components/widgets/DocumentsWidget.tsx new file mode 100644 index 0000000..8230f7a --- /dev/null +++ b/src/components/widgets/DocumentsWidget.tsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { useDocuments } from '@/hooks/useDocuments'; +import { Button } from '../ui/Button'; + +interface DocumentsWidgetProps { + onSelectDocument: (id: string) => void; +} + +export function DocumentsWidget(){ + const { documents } = useDocuments(); + + const getCategoryBadge = (category: string) => { + switch (category) { + case 'Audit': return 'bg-purple-50 text-purple-700 border-purple-200'; + case 'Facture': return 'bg-slate-100 text-slate-700 border-slate-200'; + case 'Rapport de conformité': return 'bg-emerald-50 text-emerald-700 border-emerald-200'; + default: return 'bg-blue-50 text-blue-700 border-blue-200'; + } + }; + return ( +
+ + + + + + + + + + + {documents.map((doc) => ( + + + + + + + ))} + +
+ Nom du fichier + + Catégorie + + Ajouté le + + Action +
+
+ + + +
+
{doc.title}
+
{doc.file.size} • PDF
+
+
+
+ + {doc.category} + + + {doc.created.split(" ")[0]+" "+doc.created.split(" ")[1].split(":")[0]+":"+doc.created.split(" ")[1].split(":")[1]} + + +
+
+ ); +}; + +export default DocumentsWidget; \ No newline at end of file diff --git a/src/components/widgets/EvolutionOptionCard.tsx b/src/components/widgets/EvolutionOptionCard.tsx index 09530cb..cfb343d 100644 --- a/src/components/widgets/EvolutionOptionCard.tsx +++ b/src/components/widgets/EvolutionOptionCard.tsx @@ -19,7 +19,7 @@ export const EvolutionOptionCard: React.FC = ({ return (
diff --git a/src/components/widgets/UptimeWidget.tsx b/src/components/widgets/UptimeWidget.tsx index af5ba56..f682c0f 100644 --- a/src/components/widgets/UptimeWidget.tsx +++ b/src/components/widgets/UptimeWidget.tsx @@ -10,8 +10,8 @@ export default function UptimeWidget() { return ( -

État des Services & SLA

- +

État des Services & SLA

+ {/* 1. Gestion de l'erreur */} {error && ( @@ -26,13 +26,15 @@ export default function UptimeWidget() { )} {/* 4. Affichage des données */} + {!isLoading && !error && nodes.length > 0 && ( -
- {nodes.map((node) => ( - - ))} -
+ + {nodes.map((node) => ( + + ))} + )} +
); diff --git a/src/hooks/useDocuments.ts b/src/hooks/useDocuments.ts new file mode 100644 index 0000000..c12c858 --- /dev/null +++ b/src/hooks/useDocuments.ts @@ -0,0 +1,31 @@ +import { useState, useEffect, useCallback } from 'react'; +import { pb } from '@/services/pocketbase'; +import type { Document } from '@/types/Document'; + +export const useDocuments = () => { + const [documents, setDocuments] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState(null); + + const fetchDocuments = useCallback(async () => { + setIsLoading(true); + setError(null); + try { + const records = await pb.collection('aegis_documents_vault').getFullList({ + sort: '-created', // Du plus récent au plus ancien + }); + setDocuments(records); + } catch (err) { + console.error("Erreur lors de la récupération des documents :", err); + setError("Impossible de charger les documents."); + } finally { + setIsLoading(false); + } + }, []); + + useEffect(() => { + fetchDocuments(); + }, [fetchDocuments]); + + return { documents, isLoading, error, refetch: fetchDocuments }; +}; \ No newline at end of file diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts new file mode 100644 index 0000000..83093a6 --- /dev/null +++ b/src/hooks/useTheme.ts @@ -0,0 +1,42 @@ +import { useState, useEffect } from 'react'; + +type Theme = 'light' | 'dark'; + +export function useTheme() { + // Initialisation de l'état avec une fonction pour ne lire le localStorage qu'une seule fois + const [theme, setTheme] = useState(() => { + // 1. On vérifie si un choix a déjà été sauvegardé + const storedTheme = localStorage.getItem('theme'); + if (storedTheme === 'dark' || storedTheme === 'light') { + return storedTheme; + } + + // 2. Sinon, on vérifie la préférence système de l'utilisateur + if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { + return 'dark'; + } + + // 3. Par défaut, mode clair + return 'light'; + }); + + // À chaque fois que 'theme' change, on met à jour le HTML et on sauvegarde + useEffect(() => { + const root = window.document.documentElement; + + if (theme === 'dark') { + root.classList.add('dark'); + } else { + root.classList.remove('dark'); + } + + localStorage.setItem('theme', theme); + }, [theme]); + + // Fonction utilitaire pour basculer facilement + const toggleTheme = () => { + setTheme((prevTheme) => (prevTheme === 'dark' ? 'light' : 'dark')); + }; + + return { theme, isDark: theme === 'dark', toggleTheme, setTheme }; +} \ No newline at end of file diff --git a/src/index.css b/src/index.css index 6ba9b65..788fe36 100644 --- a/src/index.css +++ b/src/index.css @@ -4,6 +4,8 @@ @tailwind components; @tailwind utilities; +@custom-variant dark (&:where(.dark, .dark *)); + /* --- VOS UTILITAIRES PERSONNALISÉS --- */ @layer utilities { .scrollbar-hide { diff --git a/src/pages/DocumentVault.tsx b/src/pages/DocumentVault.tsx index 1e573ef..f4576aa 100644 --- a/src/pages/DocumentVault.tsx +++ b/src/pages/DocumentVault.tsx @@ -1,3 +1,6 @@ +import { Card } from '@/components/ui/Card'; +import PageHeader from '@/components/ui/PageHeader'; +import DocumentsWidget from '@/components/widgets/DocumentsWidget'; import { useState } from 'react'; // Données fictives pour le maquettage visuel @@ -20,26 +23,15 @@ export default function DocumentVault() { }; return ( -
- - {/* Header du Coffre-Fort */} -
-
-
-

Coffre-Fort Documentaire

-

- - - - Espace de stockage chiffré de bout en bout -

-
-
-
+
{/* Contenu Principal */} -
- +
+ + + {/* Barre de recherche (Visuelle) */}
@@ -59,61 +51,9 @@ export default function DocumentVault() {
{/* Liste des Documents (La Carte) */} -
- - - - - - - - - - - {mockDocuments.map((doc) => ( - - - - - - - ))} - -
- Nom du fichier - - Catégorie - - Ajouté le - - Action -
-
- - - -
-
{doc.title}
-
{doc.size} • PDF
-
-
-
- - {doc.category} - - - {doc.date} - - -
-
+
-
+
); } \ No newline at end of file diff --git a/src/pages/ServiceDesk.tsx b/src/pages/ServiceDesk.tsx index f5cb9a8..f02754d 100644 --- a/src/pages/ServiceDesk.tsx +++ b/src/pages/ServiceDesk.tsx @@ -7,8 +7,8 @@ export default function ServiceDesk() { const navigate = useNavigate(); return ( -
-
+
+
{/* HEADER EXTRAIT */}