Checkpoint: Menu latéral et tableau de bord harmonisés avec palette pastel + correction bugs "Cannot convert undefined or null to object" sur pages émargement formateur et suivi questionnaires

This commit is contained in:
Manus
2026-01-20 08:43:38 -05:00
parent a7a5ebdfe8
commit 6bd47f7577
3 changed files with 37 additions and 24 deletions

View File

@@ -20,9 +20,9 @@ export default function Admin() {
const autres = apprenants.filter(a => a.fonction === "autre").length;
return [
{ name: "Directeurs", value: directeurs, color: "#3b82f6" },
{ name: "Chefs de service", value: chefsService, color: "#10b981" },
{ name: "Autres", value: autres, color: "#f59e0b" },
{ name: "Directeurs", value: directeurs, color: "#93c5fd" },
{ name: "Chefs de service", value: chefsService, color: "#6ee7b7" },
{ name: "Autres", value: autres, color: "#fcd34d" },
].filter(item => item.value > 0);
}, [apprenants]);
@@ -36,7 +36,7 @@ export default function Admin() {
etablissementCounts[code] = (etablissementCounts[code] || 0) + 1;
});
const colors = ["#3b82f6", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#ec4899", "#06b6d4", "#84cc16", "#f97316", "#6366f1"];
const colors = ["#93c5fd", "#6ee7b7", "#fcd34d", "#fca5a5", "#c4b5fd", "#f9a8d4", "#67e8f9", "#bef264", "#fdba74", "#a5b4fc"];
return Object.entries(etablissementCounts)
.map(([name, value], index) => ({
@@ -53,40 +53,40 @@ export default function Admin() {
title: "Formations actives",
value: formations?.filter(f => f.actif).length || 0,
icon: GraduationCap,
gradient: "from-blue-500 to-blue-600",
borderColor: "border-l-blue-500",
bgColor: "bg-blue-50/50",
iconBg: "bg-gradient-to-br from-blue-500 to-blue-600",
gradient: "from-blue-300 to-blue-400",
borderColor: "border-l-blue-400",
bgColor: "bg-blue-50/80",
iconBg: "bg-gradient-to-br from-blue-300 to-blue-400",
loading: loadingFormations,
},
{
title: "Séquences ouvertes",
value: sequences?.filter(s => s.statut === "ouverte").length || 0,
icon: Calendar,
gradient: "from-green-500 to-emerald-600",
borderColor: "border-l-green-500",
bgColor: "bg-green-50/50",
iconBg: "bg-gradient-to-br from-green-500 to-emerald-600",
gradient: "from-green-300 to-emerald-400",
borderColor: "border-l-green-400",
bgColor: "bg-green-50/80",
iconBg: "bg-gradient-to-br from-green-300 to-emerald-400",
loading: loadingSessions,
},
{
title: "Apprenants inscrits",
value: apprenants?.length || 0,
icon: Users,
gradient: "from-purple-500 to-purple-600",
borderColor: "border-l-purple-500",
bgColor: "bg-purple-50/50",
iconBg: "bg-gradient-to-br from-purple-500 to-purple-600",
gradient: "from-purple-300 to-purple-400",
borderColor: "border-l-purple-400",
bgColor: "bg-purple-50/80",
iconBg: "bg-gradient-to-br from-purple-300 to-purple-400",
loading: loadingApprenants,
},
{
title: "Séquences terminées",
value: sequences?.filter(s => s.statut === "terminee").length || 0,
icon: CheckCircle,
gradient: "from-orange-500 to-orange-600",
borderColor: "border-l-orange-500",
bgColor: "bg-orange-50/50",
iconBg: "bg-gradient-to-br from-orange-500 to-orange-600",
gradient: "from-orange-300 to-orange-400",
borderColor: "border-l-orange-400",
bgColor: "bg-orange-50/80",
iconBg: "bg-gradient-to-br from-orange-300 to-orange-400",
loading: loadingSessions,
},
];
@@ -96,7 +96,7 @@ export default function Admin() {
<div className="space-y-8 animate-in fade-in duration-500">
<div className="flex items-center justify-between">
<div>
<h1 className="text-4xl font-bold tracking-tight bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
<h1 className="text-4xl font-bold tracking-tight bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent">
Tableau de bord
</h1>
<p className="text-muted-foreground mt-2 text-lg">

View File

@@ -152,7 +152,7 @@ export default function AdminQuestionnaireSuivi() {
outerRadius={80}
label={(entry) => `${entry.formationNom}: ${entry.tauxReponse}%`}
>
{statsByFormation.map((entry, index) => (
{statsByFormation && Array.isArray(statsByFormation) && statsByFormation.map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
@@ -201,7 +201,7 @@ export default function AdminQuestionnaireSuivi() {
</tr>
</thead>
<tbody>
{statsByFormateur.map((formateur) => (
{statsByFormateur && Array.isArray(statsByFormateur) && statsByFormateur.map((formateur) => (
<tr key={formateur.formateurId} className="border-b">
<td className="p-2">{formateur.formateurNom}</td>
<td className="p-2 text-center">{formateur.totalEnvois}</td>