fix(navigation): correctifs flux retour post-rapport et post-sujets (reset sticky useEffect)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f51caa1b75
commit
da4e465125
3 changed files with 30 additions and 27 deletions
|
|
@ -54,17 +54,19 @@ export function AppRouter() {
|
||||||
<Route path="/" element={<Navigate to="/dashboard" replace />} />
|
<Route path="/" element={<Navigate to="/dashboard" replace />} />
|
||||||
<Route path="/dashboard" element={<DashboardPage />} />
|
<Route path="/dashboard" element={<DashboardPage />} />
|
||||||
|
|
||||||
{/* Simulation — /simulation/ee et /sujets partagent le SimulationFlowProvider. */}
|
{/* Simulation — /simulation/ee, /sujets et /rapport/:id partagent le
|
||||||
|
SimulationFlowProvider. L'instance est préservée entre ces routes
|
||||||
|
par React Router tant que le layout parent reste monté, ce qui
|
||||||
|
permet à RapportPage.reset() d'agir sur le même state que
|
||||||
|
SimulationPage (bouton « Nouvelle simulation » + breadcrumb). */}
|
||||||
<Route path="/simulation" element={<Navigate to="/simulation/ee" replace />} />
|
<Route path="/simulation" element={<Navigate to="/simulation/ee" replace />} />
|
||||||
<Route element={<SimulationFlowLayout />}>
|
<Route element={<SimulationFlowLayout />}>
|
||||||
<Route path="/simulation/ee" element={<SimulationPage />} />
|
<Route path="/simulation/ee" element={<SimulationPage />} />
|
||||||
<Route path="/sujets" element={<SujetsPage />} />
|
<Route path="/sujets" element={<SujetsPage />} />
|
||||||
|
<Route path="/rapport/:id" element={<RapportPage />} />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/simulation/eo" element={<ComingSoon />} />
|
<Route path="/simulation/eo" element={<ComingSoon />} />
|
||||||
|
|
||||||
{/* Rapport */}
|
|
||||||
<Route path="/rapport/:id" element={<RapportPage />} />
|
|
||||||
|
|
||||||
{/* Autres sections — Sprint 4+ */}
|
{/* Autres sections — Sprint 4+ */}
|
||||||
<Route path="/examen" element={<ComingSoon />} />
|
<Route path="/examen" element={<ComingSoon />} />
|
||||||
<Route path="/progression" element={<ComingSoon />} />
|
<Route path="/progression" element={<ComingSoon />} />
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@
|
||||||
* Règle H : aucune logique métier — tout est dans useSimulation() et les entités.
|
* Règle H : aucune logique métier — tout est dans useSimulation() et les entités.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useEffect } from 'react'
|
|
||||||
import { useNavigate } from 'react-router-dom'
|
|
||||||
import { usePlan } from '@/features/dashboard/hooks/usePlan'
|
import { usePlan } from '@/features/dashboard/hooks/usePlan'
|
||||||
import { Button } from '@/shared/ui/Button'
|
import { Button } from '@/shared/ui/Button'
|
||||||
import { useSimulation } from '../hooks/useSimulation'
|
import { useSimulation } from '../hooks/useSimulation'
|
||||||
|
|
@ -30,8 +28,6 @@ function SimulationSkeleton() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SimulationPage() {
|
export function SimulationPage() {
|
||||||
const navigate = useNavigate()
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: planData,
|
data: planData,
|
||||||
isLoading: isPlanLoading,
|
isLoading: isPlanLoading,
|
||||||
|
|
@ -52,18 +48,12 @@ export function SimulationPage() {
|
||||||
reset,
|
reset,
|
||||||
} = useSimulation()
|
} = useSimulation()
|
||||||
|
|
||||||
// Redirige vers /sujets dès que la création aboutit pour une tâche avec catalogue.
|
// Le reset sticky (step='done' ou 'choosing-subject' au retour) est déclenché
|
||||||
useEffect(() => {
|
// explicitement par les callers qui ramènent vers /simulation/ee :
|
||||||
if (step === 'choosing-subject' && production) {
|
// - RapportPage.goToSimulations : reset() avant navigate
|
||||||
navigate('/sujets')
|
// - SujetsPage bouton « ← Retour » : reset() avant navigate
|
||||||
}
|
// Un useEffect réactif ici annulerait les transitions légitimes de
|
||||||
}, [step, production, navigate])
|
// createMutation.onSuccess (idle → choosing-subject → navigate /sujets).
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (step === 'done' && production) {
|
|
||||||
navigate(`/rapport/${production.id}`)
|
|
||||||
}
|
|
||||||
}, [step, production, navigate])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main className="mx-auto max-w-2xl px-4 py-6">
|
<main className="mx-auto max-w-2xl px-4 py-6">
|
||||||
|
|
|
||||||
|
|
@ -34,19 +34,24 @@ function SujetsSkeleton() {
|
||||||
|
|
||||||
export function SujetsPage() {
|
export function SujetsPage() {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { production, changeSubject, setStep } = useSimulationFlow()
|
const { step, production, changeSubject, setStep, reset } = useSimulationFlow()
|
||||||
|
|
||||||
// MVP : pas de production en contexte (refresh direct) → retour à /simulation/ee
|
// Redirige vers /simulation/ee si :
|
||||||
|
// - production absente (refresh direct sur /sujets sans contexte)
|
||||||
|
// - step === 'idle' (état initial, pas de simulation en cours)
|
||||||
|
// - step === 'done' (simulation corrigée — /sujets ne doit pas patcher
|
||||||
|
// une simulation dont le rapport est déjà persisté — cf. FTD-23)
|
||||||
|
const shouldRedirect = !production || step === 'idle' || step === 'done'
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!production) navigate('/simulation/ee', { replace: true })
|
if (shouldRedirect) navigate('/simulation/ee', { replace: true })
|
||||||
}, [production, navigate])
|
}, [shouldRedirect, navigate])
|
||||||
|
|
||||||
const { data: sujets, isLoading, isError, refetch } = useSujets(
|
const { data: sujets, isLoading, isError, refetch } = useSujets(
|
||||||
production?.tache ?? 'EE_T1',
|
production?.tache ?? 'EE_T1',
|
||||||
!!production,
|
!!production && !shouldRedirect,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!production) return null
|
if (shouldRedirect || !production) return null
|
||||||
|
|
||||||
function handleSelect(sujet: SujetData) {
|
function handleSelect(sujet: SujetData) {
|
||||||
changeSubject(sujet)
|
changeSubject(sujet)
|
||||||
|
|
@ -71,7 +76,13 @@ export function SujetsPage() {
|
||||||
<div className="mb-4 flex items-center gap-3">
|
<div className="mb-4 flex items-center gap-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => navigate('/simulation/ee')}
|
onClick={() => {
|
||||||
|
// « Retour » = annuler la simulation en cours et revenir au
|
||||||
|
// TaskSelector. reset() doit être appelé AVANT navigate pour que
|
||||||
|
// step retombe à 'idle' sans repasser par 'choosing-subject'.
|
||||||
|
reset()
|
||||||
|
navigate('/simulation/ee')
|
||||||
|
}}
|
||||||
className="text-sm text-ink-4 underline-offset-4 hover:text-ink-2 hover:underline"
|
className="text-sm text-ink-4 underline-offset-4 hover:text-ink-2 hover:underline"
|
||||||
>
|
>
|
||||||
← Retour
|
← Retour
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue