/* Page principale du dashboard : KPI cards + grille de monitorings */ import { useState, useEffect, useCallback, useMemo } from 'react'; import { RefreshCw } from 'lucide-react'; import { getDashboard, getDashboardSummary, getDashboardFiltres } from '../../services/api'; import MonitoringCard from '../../components/common/MonitoringCard'; import LoadingSpinner from '../../components/common/LoadingSpinner'; import ErrorMessage from '../../components/common/ErrorMessage'; import styles from './Dashboard.module.css'; /* Carte KPI affichant un indicateur clé */ function KpiCard({ label, value, color }) { return (
{value} {label}
); } export default function Dashboard() { const [summary, setSummary] = useState(null); const [monitorings, setMonitorings] = useState([]); const [services, setServices] = useState([]); const [combinaisons, setCombinaisons] = useState([]); const [filtreService, setFiltreService] = useState(''); const [filtreCategorie, setFiltreCategorie] = useState(''); const [loading, setLoading] = useState(true); const [erreur, setErreur] = useState(''); /* Chargement initial des filtres. On n'utilise pas les référentiels SERVICE / CATEGORIE complets : ils contiennent des entrées sans aucun monitoring rattaché (ex. « Business Intelligence »), qui mèneraient sur un dashboard vide. */ useEffect(() => { async function loadFiltres() { try { const filtres = await getDashboardFiltres(); setServices(filtres.services); setCombinaisons(filtres.combinaisons); } catch { /* Non bloquant, les filtres restent vides */ } } loadFiltres(); }, []); /* Catégories proposées : restreintes au service sélectionné, le cas échéant */ const categoriesDisponibles = useCallback(service => { const pertinentes = service ? combinaisons.filter(c => c.service === service) : combinaisons; return [...new Set(pertinentes.map(c => c.categorie))].sort(); }, [combinaisons]); const categories = useMemo( () => categoriesDisponibles(filtreService), [categoriesDisponibles, filtreService], ); /* Changer de service peut rendre la catégorie sélectionnée sans résultat : on la remet à zéro dans le même rendu, pour ne déclencher qu'un seul appel. */ function handleServiceChange(service) { setFiltreService(service); if (filtreCategorie && !categoriesDisponibles(service).includes(filtreCategorie)) { setFiltreCategorie(''); } } /* Chargement des données dashboard */ const loadData = useCallback(async () => { setLoading(true); setErreur(''); try { const [sum, data] = await Promise.all([ getDashboardSummary(), getDashboard(filtreService, filtreCategorie), ]); setSummary(sum); setMonitorings(Array.isArray(data) ? data : []); } catch (e) { setErreur(e.message || 'Erreur lors du chargement du dashboard.'); } finally { setLoading(false); } }, [filtreService, filtreCategorie]); useEffect(() => { loadData(); }, [loadData]); return (

Dashboard

{/* KPI Cards */} {summary && (
)} {/* Filtres */}
{/* Contenu principal */} {loading ? ( ) : erreur ? ( ) : ( <> {monitorings.length === 0 ? (

Aucun monitoring trouvé pour ces filtres.

) : (
{monitorings.map(m => ( ))}
)} )}
); }