Checkpoint: Nouvelle navigation hiérarchique avec 4 menus principaux (Itinova, Santinova, Soins et Santé, St Exupéry), sous-menus dépliables (Établissements, DSI), sidebar partagée AppSidebar sur toutes les pages, et pages placeholder pour les sections à venir.

This commit is contained in:
Manus
2026-06-02 20:50:23 +00:00
parent 73475b697d
commit 751ac207c0
12 changed files with 421 additions and 210 deletions

View File

@@ -2,9 +2,7 @@
// Design: Corporate Modernism — Sidebar bleu marine + grille de cards + vue liste
import { useState } from 'react';
import { useLocation } from 'wouter';
import {
Building2,
Monitor,
Laptop,
Euro,
@@ -12,15 +10,14 @@ import {
SortAsc,
SortDesc,
Filter,
BarChart3,
Building2,
AlertTriangle,
CheckCircle,
ChevronDown,
LayoutGrid,
List,
Settings,
FileText,
} from 'lucide-react';
import { AppSidebar } from '../components/AppSidebar';
import { useBudgetData } from '../hooks/useBudgetData';
import { formatEuros, formatNumber } from '../lib/format';
import { EtablissementCard } from '../components/EtablissementCard';
@@ -45,9 +42,8 @@ export default function Home() {
setFilterType,
} = useBudgetData();
const [, navigate] = useLocation();
const [selectedEtab, setSelectedEtab] = useState<Etablissement | null>(null);
const [sidebarOpen, setSidebarOpen] = useState(true);
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const [viewMode, setViewMode] = useState<ViewMode>('grid');
const sortOptions: { value: SortField; label: string }[] = [
@@ -66,90 +62,7 @@ export default function Home() {
return (
<div className="min-h-screen flex bg-background">
{/* Sidebar */}
<aside
className={`${sidebarOpen ? 'w-64' : 'w-16'} flex-shrink-0 bg-[oklch(0.22_0.06_240)] text-white flex flex-col transition-all duration-300 ease-in-out`}
style={{ minHeight: '100vh' }}
>
{/* Logo / Titre */}
<div className="px-4 py-5 border-b border-white/10">
<div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-lg bg-primary flex items-center justify-center flex-shrink-0">
<BarChart3 className="w-4 h-4 text-white" />
</div>
{sidebarOpen && (
<div className="min-w-0">
<p className="font-bold text-sm leading-tight" style={{ fontFamily: 'Sora, sans-serif' }}>
Budget SI 2027
</p>
<p className="text-[10px] text-white/50 mt-0.5">Itinova Renouvellement</p>
</div>
)}
</div>
</div>
{/* Navigation */}
<nav className="flex-1 px-3 py-4 space-y-1">
<div className={`flex items-center gap-3 px-3 py-2.5 rounded-lg bg-white/10 text-white`}>
<Building2 className="w-4 h-4 flex-shrink-0" />
{sidebarOpen && <span className="text-sm font-medium">Renouvellement PC</span>}
</div>
<button
onClick={() => navigate('/budget2027')}
className="w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-white/60 hover:bg-white/10 hover:text-white transition-colors"
>
<FileText className="w-4 h-4 flex-shrink-0" />
{sidebarOpen && <span className="text-sm font-medium">Construction BP 2027</span>}
</button>
<button
onClick={() => navigate('/parametres')}
className="w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-white/60 hover:bg-white/10 hover:text-white transition-colors"
>
<Settings className="w-4 h-4 flex-shrink-0" />
{sidebarOpen && <span className="text-sm font-medium">Paramètres</span>}
</button>
</nav>
{/* Infos calcul */}
{sidebarOpen && (
<div className="px-4 py-4 border-t border-white/10">
<p className="text-[10px] text-white/40 uppercase tracking-wider mb-2">Paramètres de calcul</p>
<div className="space-y-1.5 text-xs text-white/70">
<div className="flex justify-between">
<span>Référence</span>
<span className="text-white font-medium">{meta.date_reference}</span>
</div>
<div className="flex justify-between">
<span>Seuil fixes</span>
<span className="text-white font-medium">&gt; {meta.seuil_fixes_ans} ans</span>
</div>
<div className="flex justify-between">
<span>Seuil portables</span>
<span className="text-white font-medium">&gt; {meta.seuil_portables_ans} ans</span>
</div>
<div className="flex justify-between">
<span>Coût fixe</span>
<span className="text-white font-medium">{formatEuros(meta.cout_fixe)} TTC</span>
</div>
<div className="flex justify-between">
<span>Coût portable</span>
<span className="text-white font-medium">{formatEuros(meta.cout_portable)} TTC</span>
</div>
</div>
<p className="text-[10px] text-white/30 mt-3">Calculé le {meta.date_calcul}</p>
</div>
)}
{/* Toggle sidebar */}
<button
onClick={() => setSidebarOpen((v) => !v)}
className="px-4 py-3 border-t border-white/10 text-white/40 hover:text-white/70 transition-colors flex items-center justify-center"
>
<ChevronDown
className={`w-4 h-4 transition-transform duration-300 ${sidebarOpen ? '-rotate-90' : 'rotate-90'}`}
/>
</button>
</aside>
<AppSidebar collapsed={sidebarCollapsed} onToggle={() => setSidebarCollapsed(c => !c)} />
{/* Contenu principal */}
<main className="flex-1 flex flex-col min-w-0 overflow-hidden">