feat(progression): page /progression + section Dashboard Premium — patterns, exercices long terme, indice de préparation (Sprint 3.6c)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hermann_Kitio 2026-04-22 23:12:23 +03:00
parent a752029c19
commit a60c298605
18 changed files with 1005 additions and 7 deletions

View file

@ -0,0 +1,54 @@
/**
* PatternsList Sprint 3.6c.
*
* Liste les erreurs récurrentes détectées, groupées par critère et triées par
* fréquence DESC (déjà fait côté backend).
*
* Règle L : tokens Direction H exclusivement.
*/
import { Card } from '@/shared/ui/Card'
import { Badge } from '@/shared/ui/Badge'
import { CRITERE_LABELS } from '@/entities/report/lib'
import type { Pattern } from '@/entities/patterns/types'
interface Props {
patterns: Pattern[]
}
function humanizeCode(code: string): string {
return code.replace(/_/g, ' ')
}
export function PatternsList({ patterns }: Props) {
if (patterns.length === 0) {
return (
<Card variant="default" className="p-4">
<p className="text-sm text-ink-3">
Aucune erreur récurrente détectée sur vos 5 dernières productions.
Continuez ainsi !
</p>
</Card>
)
}
return (
<ul className="space-y-2">
{patterns.map((p) => (
<li key={`${p.critere}-${p.code}-${p.description ?? ''}`}>
<Card variant="default" className="flex items-start justify-between gap-3 p-4">
<div className="min-w-0 space-y-1">
<p className="text-sm font-semibold text-ink-1">
{p.description ?? humanizeCode(p.code)}
</p>
<p className="text-xs text-ink-4">{CRITERE_LABELS[p.critere]}</p>
</div>
<Badge variant="nclc" className="shrink-0 tabular-nums">
{p.frequency}/5
</Badge>
</Card>
</li>
))}
</ul>
)
}