"use client"; // Tableau de progression : score global, série, statistiques, maîtrise par semaine, // concepts groupés par niveau, recommandations justifiées, activité récente. import Link from "next/link"; import { useEffect, useState } from "react"; import { Activity, AlertTriangle, ArrowRight, BellRing, CheckCircle2, Clock3, Flame, Layers, ListChecks, Target, } from "lucide-react"; import { Badge, Card, EmptyState, Skeleton, cn } from "@/components/ui"; import { ErrorBanner, LEVELS, ProgressRing, fetchJson, fmtDateTime, levelInfo, type MasteryLevel } from "./shared"; type Concept = { conceptId: number; slug: string; name: string; week: number | null; importance: number; axis: string; score: number; level: MasteryLevel; observations: number; }; type Recommendation = { kind: string; label: string; reason: string; href: string; courseCode: string; priority: number }; type Overview = { globalScore: number; levels: Record; concepts: Concept[]; practicedCount: number; weekScores: { week: number; score: number }[]; streak: number; stats: { cardsReviewed: number; quizAnswered: number; quizAccuracy: number | null; examAttempts: number; studyMinutes: number; errorsToReview: number; cardsDue: number; }; recent: { kind: string; meta: string | null; created_at: string }[]; recommendations: Recommendation[]; }; const ACTIVITY_LABELS: Record = { chat: "Conversation avec le tuteur", flashcards: "Révision de cartes mémoire", quiz: "Quiz adaptatif", exam: "Examen blanc", summary: "Génération d'un résumé", plan: "Plan d'étude", }; const LEVEL_ORDER: MasteryLevel[] = ["maitrise", "solide", "en-construction", "a-decouvrir"]; export function ProgressDashboard({ course }: { course: string }) { const [data, setData] = useState(null); const [error, setError] = useState(null); useEffect(() => { fetchJson(`/api/learning/${course}/overview`) .then(setData) .catch((e) => setError(e instanceof Error ? e.message : "Erreur de chargement.")); }, [course]); if (error) { return
; } if (!data) { return (
); } const stats = [ { icon: Layers, label: "Cartes révisées", value: String(data.stats.cardsReviewed) }, { icon: ListChecks, label: "Questions de quiz", value: String(data.stats.quizAnswered) }, { icon: Target, label: "Précision aux quiz", value: data.stats.quizAccuracy == null ? "—" : `${data.stats.quizAccuracy} %` }, { icon: CheckCircle2, label: "Examens blancs", value: String(data.stats.examAttempts) }, { icon: Clock3, label: "Minutes d'étude", value: String(data.stats.studyMinutes) }, { icon: AlertTriangle, label: "Erreurs à revoir", value: String(data.stats.errorsToReview) }, ]; return (
{/* Rangée d'entête compacte : score global + série + cartes dues */}

Estimation pondérée ({data.practicedCount}/{data.concepts.length} notions pratiquées)

maîtrise estimée

0 ? "text-amber-500" : "text-muted")}> 0 ? "fill-amber-500/25" : ""} /> {data.streak}

jour{data.streak > 1 ? "s" : ""} de suite

{data.streak > 0 ? "La régularité bat l'intensité — continuez !" : "Une activité aujourd'hui démarre votre série."}

0 ? "text-brand-600 dark:text-brand-300" : "text-fg")}> {data.stats.cardsDue}

carte{data.stats.cardsDue > 1 ? "s" : ""} due{data.stats.cardsDue > 1 ? "s" : ""}

Réviser
{/* Statistiques */}
{stats.map((s) => (

{s.value}

{s.label}

))}
{/* Maîtrise par semaine */}

Maîtrise par semaine

{data.weekScores.length === 0 ? (

Aucune donnée encore — les barres apparaîtront après vos premières activités.

) : (
{data.weekScores.map((w) => { const pct = Math.round(w.score * 100); const lv = levelInfo(w.score >= 0.85 ? "maitrise" : w.score >= 0.6 ? "solide" : w.score >= 0.3 ? "en-construction" : "a-decouvrir"); return (
{pct}
S{w.week}
); })}
)}
{/* Concepts par niveau */}

Concepts par niveau de maîtrise

{LEVEL_ORDER.map((lvl) => { const items = data.concepts.filter((c) => c.level === lvl); if (!items.length) return null; const info = LEVELS[lvl]; return (

{info.label}

({items.length})
{items.map((c) => ( {Math.round(c.score * 100)} {c.name} {c.week != null && S{c.week}} ))}
); })} {data.concepts.length === 0 && ( } title="Aucun concept" description="La carte des concepts de ce cours n'est pas encore chargée." /> )}
{/* Recommandations + activité récente */}

Recommandé maintenant

{data.recommendations.length === 0 ? (

Rien d'urgent — poursuivez votre plan ou explorez la carte des concepts.

) : (
{data.recommendations.map((r, i) => (

{r.label}

Pourquoi : {r.reason}

))}
)}

Activité récente

{data.recent.length === 0 ? (

Aucune activité enregistrée pour ce cours.

) : (
    {data.recent.map((a, i) => (
  1. {ACTIVITY_LABELS[a.kind] ?? a.kind} {fmtDateTime(a.created_at)}
  2. ))}
)}
{/* Légende des niveaux */}
{LEVEL_ORDER.map((lvl) => ( {LEVELS[lvl].label} ))} La maîtrise est une estimation : elle décroît doucement sans pratique.
); }