feat(historique): page /historique — liste paginée des productions + gating plan (Sprint 3.7)

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

View file

@ -0,0 +1,59 @@
/**
* SimulationListItem Sprint 3.7.
*
* Carte item de la page /historique. Clic /rapport/:id (RapportPage gère le
* cas `rapport === null` en redirigeant vers /simulation/ee FTD-21).
*
* Règle L : tokens Direction H exclusivement.
* Règle H : purement présentationnel aucune logique plan ici.
*/
import { Link } from 'react-router-dom'
import { Badge } from '@/shared/ui/Badge'
import { formatTache } from '@/entities/production/lib'
import { formatRelativeDate } from '@/shared/lib/date'
import type { SimulationListItem as Item } from '@/entities/production/types'
interface Props {
item: Item
}
export function SimulationListItem({ item }: Props) {
const hasScore = item.score !== null && item.nclc !== null
const isExam = item.mode === 'examen'
return (
<Link
to={`/rapport/${item.id}`}
className="block rounded-lg border border-line bg-surface p-4 shadow-sm transition-colors duration-150 hover:border-expria hover:bg-surface-hover focus-visible:outline-none focus-visible:shadow-focus"
>
<div className="flex items-start justify-between gap-3">
<div className="min-w-0 space-y-1">
<div className="flex flex-wrap items-center gap-2">
<span className="text-sm font-semibold text-ink-1">{formatTache(item.tache)}</span>
{isExam && <Badge variant="nclc">Examen</Badge>}
{!hasScore && <Badge variant="neutral">En cours</Badge>}
</div>
<p className="text-xs text-ink-4">{formatRelativeDate(item.created_at)}</p>
</div>
{hasScore ? (
<div className="shrink-0 text-right">
<p className="tabular-nums text-ink-1">
<span className="text-xl font-bold">{item.score}</span>
<span className="text-sm font-medium text-ink-4">/20</span>
</p>
<p className="text-xs text-ink-4 tabular-nums">
NCLC {item.nclc}
{item.nclc_cible ? ` / cible ${item.nclc_cible}` : ''}
</p>
</div>
) : (
<div className="shrink-0 text-right text-xs text-ink-4">
Score à venir
</div>
)}
</div>
</Link>
)
}