import { useAuth } from "@/_core/hooks/useAuth"; import SonumLayout from "@/components/SonumLayout"; import { trpc } from "@/lib/trpc"; import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, PieChart, Pie, Cell, Legend, } from "recharts"; import { Building2, LayoutGrid, FileText, TrendingUp, Shield, CheckCircle, } from "lucide-react"; // ─── Palette de couleurs ────────────────────────────────────────────────────── const COLORS = [ "#1e40af", // bleu foncé "#3b82f6", // bleu "#60a5fa", // bleu clair "#93c5fd", // bleu très clair "#1d4ed8", "#2563eb", "#6366f1", "#818cf8", "#a5b4fc", "#c7d2fe", ]; const ETAT_COLORS: Record = { "en production": "#16a34a", "en cours de déploiement": "#ca8a04", "en projet": "#2563eb", "abandonné": "#dc2626", "Inconnu": "#9ca3af", }; // ─── Composant carte KPI ────────────────────────────────────────────────────── function KpiCard({ icon, label, value, sub, color = "primary", }: { icon: React.ReactNode; label: string; value: string | number; sub?: string; color?: "primary" | "green" | "amber" | "blue"; }) { const colorMap = { primary: "bg-primary/10 text-primary", green: "bg-emerald-50 text-emerald-600", amber: "bg-amber-50 text-amber-600", blue: "bg-blue-50 text-blue-600", }; return (
{icon}

{label}

{value}

{sub &&

{sub}

}
); } // ─── Tooltip personnalisé ───────────────────────────────────────────────────── function CustomTooltip({ active, payload, label }: any) { if (active && payload && payload.length) { return (

{label}

{payload[0].value} établissement{payload[0].value !== 1 ? "s" : ""}

); } return null; } // ─── Page principale ────────────────────────────────────────────────────────── export default function Statistiques() { const { user } = useAuth(); const isGestionnaire = user?.sonumRole === "gestionnaire" || user?.role === "admin"; const statsQuery = trpc.referentiel.statistiques.useQuery(undefined, { enabled: isGestionnaire, }); if (!isGestionnaire) { return (

Accès réservé aux gestionnaires SONUM

); } const stats = statsQuery.data; return (
{/* En-tête */}

Tableau de bord statistiques

Vue d'ensemble de la cartographie des solutions numériques FEHAP

{statsQuery.isLoading && (
)} {statsQuery.isError && (

Erreur lors du chargement des statistiques

{statsQuery.error?.message}

)} {stats && (
{/* KPIs */}
} label="Établissements" value={stats.totalEtablissements} sub="adhérents FEHAP référencés" color="primary" /> } label="Solutions distinctes" value={stats.totalSolutions} sub="logiciels référencés" color="blue" /> } label="Fiches logiciels" value={stats.totalFiches} sub="rattachements établissement / solution" color="amber" /> } label="Taux de remplissage" value={`${stats.tauxRemplissage} %`} sub={`${stats.etabAvecLogiciel} étab. avec au moins 1 logiciel`} color="green" />
{/* Graphiques ligne 1 : Blocs fonctionnels + Régions */}
{/* Répartition par bloc fonctionnel */}

Répartition par bloc fonctionnel

{stats.parBloc.length === 0 ? (
Aucune donnée disponible
) : ( } /> )}
{/* Répartition par région */}

Répartition par région

{stats.parRegion.length === 0 ? (
Aucune donnée disponible
) : ( } /> {stats.parRegion.map((_: { nom: string; count: number }, index: number) => ( ))} )}
{/* Graphiques ligne 2 : État de déploiement + Top solutions */}
{/* Répartition par état de déploiement */}

État de déploiement

{stats.parEtat.length === 0 ? (
Aucune donnée disponible
) : (
{stats.parEtat.map((entry: { nom: string; count: number }, index: number) => ( ))} [`${value} fiche${value !== 1 ? "s" : ""}`, name]} contentStyle={{ background: "hsl(var(--card))", border: "1px solid hsl(var(--border))", borderRadius: "8px", fontSize: "12px", }} />
)}
{/* Top 10 solutions */}

Top 10 solutions les plus utilisées

{stats.topSolutions.length === 0 ? (
Aucune donnée disponible
) : (
{stats.topSolutions.map((sol: { nom: string; editeur: string; count: number }, index: number) => (
{index + 1}
{sol.nom} {sol.count} étab.
{sol.editeur}
))}
)}
)}
); }