feat(simulations): resume session + RapportPage tolère rapport=null (FTD-21)
This commit is contained in:
parent
aaecc3f804
commit
ae8d8af1df
2 changed files with 48 additions and 5 deletions
|
|
@ -11,11 +11,28 @@
|
|||
*/
|
||||
|
||||
import { apiFetch } from '@/shared/lib/api-client'
|
||||
import { getSimulationState } from '@/entities/production/api'
|
||||
import type { CorrectEePayload, CorrectEoPayload, Report } from './types'
|
||||
|
||||
/** Récupère un rapport existant. Endpoint : `GET /simulations/:id`. */
|
||||
/**
|
||||
* Récupère un rapport existant. Endpoint : `GET /simulations/:id`.
|
||||
*
|
||||
* FTD-21 : depuis l'assouplissement de `getById` côté backend (tolère `rapport=null`
|
||||
* pour permettre le resume), on unwrap le champ `rapport` du `SimulationState`.
|
||||
* Si la simulation est encore en cours (`rapport === null`), on lève une erreur
|
||||
* typée `REPORT_NOT_READY` que RapportPage catche pour rediriger vers /simulation/ee.
|
||||
*/
|
||||
export function getReport(id: string): Promise<Report> {
|
||||
return apiFetch<Report>(`/simulations/${id}`)
|
||||
return getSimulationState(id).then((state) => {
|
||||
if (state.rapport === null) {
|
||||
throw {
|
||||
error: true,
|
||||
code: 'REPORT_NOT_READY',
|
||||
message: 'Simulation en cours — rédaction pas encore corrigée.',
|
||||
}
|
||||
}
|
||||
return { ...state.rapport, simulation_id: state.simulation_id }
|
||||
})
|
||||
}
|
||||
|
||||
const CORRECTION_TIMEOUT_MS = 30_000
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
* Règle H : logique de floutage dans entities/report/lib.ts.
|
||||
*/
|
||||
|
||||
import { useEffect } from 'react'
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
|
|
@ -23,6 +24,15 @@ import { Badge } from '@/shared/ui/Badge'
|
|||
import { Button } from '@/shared/ui/Button'
|
||||
import type { Critere } from '@/entities/report/types'
|
||||
|
||||
function isReportNotReady(err: unknown): boolean {
|
||||
return (
|
||||
typeof err === 'object' &&
|
||||
err !== null &&
|
||||
'code' in err &&
|
||||
(err as { code: unknown }).code === 'REPORT_NOT_READY'
|
||||
)
|
||||
}
|
||||
|
||||
// ── Composants internes ──────────────────────────────────────────────────────
|
||||
|
||||
function RapportSkeleton() {
|
||||
|
|
@ -105,7 +115,16 @@ export function RapportPage() {
|
|||
const { id = '' } = useParams<{ id: string }>()
|
||||
const navigate = useNavigate()
|
||||
|
||||
const { rapport, isLoading, isError } = useRapport(id)
|
||||
const { rapport, isLoading, isError, error } = useRapport(id)
|
||||
const isInProgress = isError && isReportNotReady(error)
|
||||
|
||||
// FTD-21 — si la simulation n'est pas encore corrigée, rediriger vers /simulation/ee.
|
||||
// Le SimulationFlowProvider restaurera la session via localStorage si présent.
|
||||
useEffect(() => {
|
||||
if (isInProgress) {
|
||||
navigate('/simulation/ee', { replace: true })
|
||||
}
|
||||
}, [isInProgress, navigate])
|
||||
|
||||
const {
|
||||
data: planData,
|
||||
|
|
@ -137,8 +156,15 @@ export function RapportPage() {
|
|||
{/* Loading */}
|
||||
{(isLoading || isPlanLoading) && <RapportSkeleton />}
|
||||
|
||||
{/* Erreur */}
|
||||
{(isError || isPlanError) && !isLoading && !isPlanLoading && (
|
||||
{/* FTD-21 — simulation en cours : message discret avant redirection via useEffect */}
|
||||
{isInProgress && (
|
||||
<p className="text-center text-sm text-ink-4" aria-live="polite">
|
||||
Votre simulation est en cours.
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Erreur (hors "en cours" déjà géré au-dessus) */}
|
||||
{(isError || isPlanError) && !isInProgress && !isLoading && !isPlanLoading && (
|
||||
<div
|
||||
role="alert"
|
||||
className="space-y-3 rounded-lg border border-danger/30 bg-danger-bg px-4 py-6 text-center"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue