feat(simulations): exposer sujet dans useSimulation + composant SujetDisplay
This commit is contained in:
parent
e130d3792e
commit
b356bc7109
2 changed files with 68 additions and 0 deletions
67
src/features/simulations/components/SujetDisplay.tsx
Normal file
67
src/features/simulations/components/SujetDisplay.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -62,6 +62,7 @@ export function useSimulation() {
|
||||||
return {
|
return {
|
||||||
step,
|
step,
|
||||||
production,
|
production,
|
||||||
|
sujet: production?.sujet ?? null,
|
||||||
report: (correctMutation.data ?? null) as Report | null,
|
report: (correctMutation.data ?? null) as Report | null,
|
||||||
isCreating: createMutation.isPending,
|
isCreating: createMutation.isPending,
|
||||||
isCorrecting: correctMutation.isPending,
|
isCorrecting: correctMutation.isPending,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue