feat(simulations): choix du sujet — dropdown intégré + bouton aléatoire

This commit is contained in:
Hermann_Kitio 2026-04-21 02:06:08 +03:00
parent 477477b6a6
commit 7902eec042
5 changed files with 193 additions and 29 deletions

View file

@ -2,13 +2,15 @@
* Hook d'orchestration du flux simulation EE.
*
* Séquence : createSimulation (POST /simulations)
* [choosing-subject] (sauf EO_T1 sujet fixe)
* correctEe (POST /corrections/ee, timeout 30 s)
*
* State machine :
* 'idle' sélection de tâche disponible
* 'task-selected' formulaire de saisie visible
* 'correcting' correction en cours (30 s max)
* 'done' rapport disponible dans `report`
* 'idle' sélection de tâche disponible
* 'choosing-subject' écran SujetSelector (hors EO_T1)
* 'task-selected' formulaire de saisie visible
* 'correcting' correction en cours (30 s max)
* 'done' rapport disponible dans `report`
*
* Règle H : aucune logique métier ici les gardes de quota et de plan
* sont dans TaskSelector (UX) et dans le backend (autorité).
@ -18,11 +20,24 @@ import { useState } from 'react'
import { useMutation } from '@tanstack/react-query'
import { createSimulation } from '@/entities/production/api'
import { correctEe } from '@/entities/report/api'
import type { CreateSimulationPayload, Production } from '@/entities/production/types'
import type {
CreateSimulationPayload,
Production,
SujetData,
Tache,
} from '@/entities/production/types'
import type { Report } from '@/entities/report/types'
import type { ApiError } from '@/shared/types/api'
export type SimulationStep = 'idle' | 'task-selected' | 'correcting' | 'done'
export type SimulationStep =
| 'idle'
| 'choosing-subject'
| 'task-selected'
| 'correcting'
| 'done'
/** Tâches qui ne passent pas par l'écran de choix de sujet. */
const TACHES_SANS_CATALOGUE: Tache[] = ['EO_T1']
export function useSimulation() {
const [step, setStep] = useState<SimulationStep>('idle')
@ -32,7 +47,7 @@ export function useSimulation() {
mutationFn: createSimulation,
onSuccess: (data) => {
setProduction(data)
setStep('task-selected')
setStep(TACHES_SANS_CATALOGUE.includes(data.tache) ? 'task-selected' : 'choosing-subject')
},
})
@ -52,6 +67,31 @@ export function useSimulation() {
correctMutation.mutate({ simulationId: production.id, contenu: texte, tache: production.tache })
}
/** Remplace le sujet courant sans toucher à l'étape. */
function changeSubject(sujet: SujetData): void {
setProduction((p) => (p ? { ...p, sujet } : p))
}
/** Choix manuel : remplace le sujet et passe à la saisie. */
function selectSujet(sujet: SujetData): void {
changeSubject(sujet)
setStep('task-selected')
}
/** Choix aléatoire côté client à partir d'une liste pré-chargée. */
function selectRandom(sujets: SujetData[]): void {
if (sujets.length > 0) {
const pick = sujets[Math.floor(Math.random() * sujets.length)]
changeSubject(pick)
}
setStep('task-selected')
}
/** Retour à l'écran SujetSelector depuis SimulationForm. */
function backToSubject(): void {
setStep('choosing-subject')
}
function reset(): void {
setStep('idle')
setProduction(null)
@ -70,6 +110,10 @@ export function useSimulation() {
correctError: correctMutation.error as ApiError | null,
selectTask,
submitText,
changeSubject,
selectSujet,
selectRandom,
backToSubject,
reset,
}
}