Checkpoint: Sélecteur d'année global (2025, 2026, 2027+) sur Renouvellement PC, CAPEX-Construction, CAPEX-Synthèse et DSI-OPEX. Données CAPEX isolées par année en localStorage. Titres dynamiques selon l'année sélectionnée.

This commit is contained in:
Manus
2026-06-03 09:49:14 +00:00
parent 858f0dc4d9
commit 787928c722
7 changed files with 189 additions and 55 deletions

View File

@@ -18,6 +18,8 @@ import {
ArrowUpDown,
} from 'lucide-react';
import { AppSidebar } from '../components/AppSidebar';
import { AnneeSelectorBar } from '../components/AnneeSelectorBar';
import { useAnnee } from '../contexts/AnneeContext';
import opexRaw from '../data_opex.json';
import { formatEuros } from '../lib/format';
@@ -82,7 +84,7 @@ type ViewMode = 'etablissements' | 'postes';
type SortDir = 'asc' | 'desc';
export default function DsiOpex() {
const [selectedYear, setSelectedYear] = useState<2026 | 2027>(2026);
const { annee } = useAnnee();
const [viewMode, setViewMode] = useState<ViewMode>('postes');
const [search, setSearch] = useState('');
const [selectedCategorie, setSelectedCategorie] = useState('Toutes');
@@ -190,22 +192,11 @@ export default function DsiOpex() {
{opexData.meta.nb_postes} postes de charges · {opexData.meta.nb_etablissements} établissements
</p>
</div>
{/* Sélecteur d'année */}
<div className="flex items-center gap-1 bg-muted rounded-lg p-1">
{([2026, 2027] as const).map(year => (
<button
key={year}
onClick={() => setSelectedYear(year)}
className={`px-4 py-1.5 rounded-md text-sm font-semibold transition-all ${
selectedYear === year
? 'bg-primary text-white shadow-sm'
: 'text-muted-foreground hover:text-foreground'
}`}
>
{year}
</button>
))}
{/* Sélecteur d'année remplacé par AnneeSelectorBar global */}
<div className="flex items-center gap-3">
<AnneeSelectorBar />
</div>
</div>
</header>
@@ -215,7 +206,7 @@ export default function DsiOpex() {
<div className="bg-card border border-border rounded-xl p-4">
<div className="flex items-center gap-2 mb-1">
<Euro className="w-4 h-4 text-orange-500" />
<span className="text-xs text-muted-foreground uppercase tracking-wide font-medium">Total OPEX {selectedYear}</span>
<span className="text-xs text-muted-foreground uppercase tracking-wide font-medium">Total OPEX {annee}</span>
</div>
<p className="text-2xl font-bold text-orange-600 tabular-nums" style={{ fontFamily: 'Sora, sans-serif' }}>
{formatEuros(opexData.total_global)}
@@ -354,7 +345,7 @@ export default function DsiOpex() {
{showDetails && <th className="text-left px-4 py-3 font-medium text-muted-foreground hidden xl:table-cell">Compte</th>}
<th className="text-right px-4 py-3 font-medium text-muted-foreground">Budget N-1</th>
<th className="text-right px-4 py-3 font-medium text-muted-foreground">
<SortBtn col="montant" label={`Prév. ${selectedYear}`} />
<SortBtn col="montant" label={`Prév. ${annee}`} />
</th>
<th className="text-right px-4 py-3 font-medium text-muted-foreground w-24">Répartition</th>
</tr>
@@ -441,7 +432,7 @@ export default function DsiOpex() {
<tfoot>
<tr className="bg-muted/40 border-t-2 border-border">
<td colSpan={showDetails ? 7 : 6} className="px-4 py-3 font-bold text-foreground">
TOTAL {selectedCategorie !== 'Toutes' ? selectedCategorie : 'OPEX DSI'} {selectedYear}
TOTAL {selectedCategorie !== 'Toutes' ? selectedCategorie : 'OPEX DSI'} {annee}
</td>
<td className="px-4 py-3 text-right font-bold text-orange-600 text-base tabular-nums">
{formatEuros(totalFiltre)}
@@ -460,7 +451,7 @@ export default function DsiOpex() {
<div className="mt-6 bg-card border border-border rounded-xl p-5">
<h3 className="font-semibold text-foreground mb-4 flex items-center gap-2" style={{ fontFamily: 'Sora, sans-serif' }}>
<BarChart3 className="w-4 h-4 text-muted-foreground" />
Répartition par catégorie {selectedYear}
Répartition par catégorie {annee}
</h3>
<div className="space-y-3">
{Object.entries(totalParCategorie)
@@ -518,7 +509,7 @@ export default function DsiOpex() {
</th>
))}
<th className="text-right px-4 py-3 font-medium text-muted-foreground">
<SortBtn col="total" label={`Total ${selectedYear}`} />
<SortBtn col="total" label={`Total ${annee}`} />
</th>
</tr>
</thead>