feat(simulations): exposer sujet dans useSimulation + composant SujetDisplay

This commit is contained in:
Hermann_Kitio 2026-04-20 23:09:35 +03:00
parent e130d3792e
commit b356bc7109
2 changed files with 68 additions and 0 deletions

View file

@ -0,0 +1,67 @@
/**
* Affichage du sujet d'examen (consigne + documents) au-dessus de la zone de saisie.
*
* Prop `sujet` vient du hook `useSimulation` (alimenté par `POST /simulations`).
* Si `sujet === null` (aucun sujet actif pour la tâche, ou EO_T2_LIVE) rien n'est rendu.
*
* Règle H : composant purement présentationnel, aucune logique métier.
* Règle L : tokens Direction H exclusivement (canvas, surface, ink-*, line, expria).
*
* Rendu plain-text avec `whitespace-pre-wrap` pour préserver les sauts de ligne.
* Les sujets étant du contenu admin-curé (pas du texte IA), pas de react-markdown.
*/
import { Badge } from '@/shared/ui/Badge'
import { Card } from '@/shared/ui/Card'
import type { SujetData } from '@/entities/production/types'
interface Props {
sujet: SujetData | null
}
function DocumentBlock({ titre, texte }: { titre: string | null; texte: string | null }) {
if (!titre && !texte) return null
return (
<article className="rounded-md border border-line bg-canvas-2 p-3">
{titre && <h4 className="mb-2 text-sm font-semibold text-ink-1">{titre}</h4>}
{texte && (
<p className="whitespace-pre-wrap text-sm leading-relaxed text-ink-2">{texte}</p>
)}
</article>
)
}
export function SujetDisplay({ sujet }: Props) {
if (!sujet) return null
return (
<Card variant="default" className="p-5">
<div className="space-y-4">
{sujet.role && (
<div className="flex items-center gap-2">
<Badge variant="neutral">Rôle</Badge>
<span className="text-sm text-ink-2">{sujet.role}</span>
</div>
)}
{sujet.contexte && (
<p className="whitespace-pre-wrap text-sm leading-relaxed text-ink-3">
{sujet.contexte}
</p>
)}
<div>
<h3 className="mb-1 text-xs font-semibold uppercase tracking-wide text-ink-4">
Consigne
</h3>
<p className="whitespace-pre-wrap text-base leading-relaxed text-ink-1">
{sujet.consigne}
</p>
</div>
<DocumentBlock titre={sujet.doc1_titre} texte={sujet.doc1_texte} />
<DocumentBlock titre={sujet.doc2_titre} texte={sujet.doc2_texte} />
</div>
</Card>
)
}

View file

@ -62,6 +62,7 @@ export function useSimulation() {
return {
step,
production,
sujet: production?.sujet ?? null,
report: (correctMutation.data ?? null) as Report | null,
isCreating: createMutation.isPending,
isCorrecting: correctMutation.isPending,