109 lines
3.9 KiB
TypeScript
109 lines
3.9 KiB
TypeScript
/**
|
|
* Appels API du domaine `production`.
|
|
*
|
|
* Toutes les requêtes passent par `apiFetch` (Règle J / Règle F).
|
|
* - `POST /simulations` : timeout 5s (défaut), retry désactivé (POST non-idempotent).
|
|
* - `GET /simulations/:id` : timeout 5s, retry activé (GET idempotent).
|
|
*
|
|
* Erreurs notables : `QUOTA_REACHED` (Free 5/5), `PLAN_INSUFFICIENT` (exam_mode).
|
|
*/
|
|
|
|
import { apiFetch } from '@/shared/lib/api-client'
|
|
import type {
|
|
CreateSimulationPayload,
|
|
Production,
|
|
SimulationState,
|
|
SimulationsListResponse,
|
|
SujetData,
|
|
Tache,
|
|
} from './types'
|
|
|
|
/** Crée une nouvelle simulation. Endpoint : `POST /simulations` (HTTP 201). */
|
|
export function createSimulation(payload: CreateSimulationPayload): Promise<Production> {
|
|
return apiFetch<Production>('/simulations', { method: 'POST', body: payload })
|
|
}
|
|
|
|
/** Récupère une simulation existante. Endpoint : `GET /simulations/:id`. */
|
|
export function getSimulation(id: string): Promise<Production> {
|
|
return apiFetch<Production>(`/simulations/${id}`)
|
|
}
|
|
|
|
/**
|
|
* Sprint 3.7 — liste paginée des simulations de l'utilisateur connecté.
|
|
* Endpoint : `GET /simulations?page=X&limit=Y`. Tri `created_at DESC` côté backend.
|
|
* Champs lourds exclus (contenu, rapport, exercices, modele) — cf. SimulationListItem.
|
|
*/
|
|
export function listSimulations(page: number, limit: number): Promise<SimulationsListResponse> {
|
|
const qs = new URLSearchParams({ page: String(page), limit: String(limit) })
|
|
return apiFetch<SimulationsListResponse>(`/simulations?${qs.toString()}`)
|
|
}
|
|
|
|
/**
|
|
* FTD-21 — récupère l'état complet d'une simulation (contenu + sujet + rapport).
|
|
* Utilisé par `SimulationFlowProvider` pour restaurer une session depuis
|
|
* `localStorage.expria_simulation_id` au mount.
|
|
*
|
|
* Si `rapport === null` → simulation en cours, restaurer `/simulation/ee`.
|
|
* Sinon → simulation terminée, rediriger vers `/rapport/:id`.
|
|
*/
|
|
export function getSimulationState(id: string): Promise<SimulationState> {
|
|
return apiFetch<SimulationState>(`/simulations/${id}`)
|
|
}
|
|
|
|
/**
|
|
* FTD-21 — autosave du contenu (debounce 30 s + beforeunload).
|
|
* Endpoint : `PATCH /simulations/:id/contenu`.
|
|
* Ne retourne rien : le client conserve déjà le texte localement.
|
|
*/
|
|
export async function autosaveContenu(id: string, contenu: string): Promise<void> {
|
|
await apiFetch<{ ok: true }>(`/simulations/${id}/contenu`, {
|
|
method: 'PATCH',
|
|
body: { contenu },
|
|
})
|
|
}
|
|
|
|
/**
|
|
* FTD-21 — persiste un changement de sujet côté backend.
|
|
* Endpoint : `PATCH /simulations/:id/sujet`.
|
|
* Appelé depuis `SimulationFlowProvider.changeSubject` quand l'utilisateur
|
|
* choisit un autre sujet via `/sujets`.
|
|
*/
|
|
export async function updateSujet(id: string, sujetId: string): Promise<void> {
|
|
await apiFetch<{ sujet: SujetData }>(`/simulations/${id}/sujet`, {
|
|
method: 'PATCH',
|
|
body: { sujet_id: sujetId },
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Mappe une Tache vers les paramètres de la route `GET /sujets`.
|
|
* Retourne `null` pour les tâches sans catalogue de sujets côté base
|
|
* (EO_T1 : sujet fixe connu, EO_T2_LIVE : interaction sans sujet).
|
|
*/
|
|
function mapTacheToSujetParams(tache: Tache): { mode: 'EE' | 'EO'; tacheNumber: 1 | 2 | 3 } | null {
|
|
switch (tache) {
|
|
case 'EE_T1':
|
|
return { mode: 'EE', tacheNumber: 1 }
|
|
case 'EE_T2':
|
|
return { mode: 'EE', tacheNumber: 2 }
|
|
case 'EE_T3':
|
|
return { mode: 'EE', tacheNumber: 3 }
|
|
case 'EO_T3':
|
|
return { mode: 'EO', tacheNumber: 3 }
|
|
case 'EO_T1':
|
|
return null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère la liste des sujets actifs disponibles pour une tâche.
|
|
* Endpoint : `GET /sujets?mode=XX&tache=N`.
|
|
*
|
|
* Retourne `[]` immédiatement pour les tâches sans catalogue (EO_T1).
|
|
*/
|
|
export function getSujets(tache: Tache): Promise<SujetData[]> {
|
|
const params = mapTacheToSujetParams(tache)
|
|
if (!params) return Promise.resolve([])
|
|
const qs = new URLSearchParams({ mode: params.mode, tache: String(params.tacheNumber) })
|
|
return apiFetch<{ sujets: SujetData[] }>(`/sujets?${qs.toString()}`).then((r) => r.sujets)
|
|
}
|