Import bénévoles : couche API (analyse + exécution) et mock CSV
- `PlanningApi.imports.analyze/execute` : envoi `multipart/form-data` (le client HTTP laisse le navigateur poser le Content-Type). - Types miroir des schémas back-end (`ImportAnalyzeResponse`, `ImportMapping`, `ImportReport`, `ImportRowReport`, `ImportIssue`…). - Hooks `useAnalyzeImport` / `useExecuteImport` ; l'exécution réelle invalide les bénévoles et le planning. - Implémentation mock (mode démo) : lecture CSV, suggestion de mapping, simulation/exécution avec rapport ligne par ligne. Excel renvoie `import.error.xlsx_demo_only`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
06f8736c33
commit
df8d6733db
@@ -5,6 +5,7 @@ import type {
|
||||
DayPartCreate,
|
||||
DayPartUpdate,
|
||||
EditionUpdate,
|
||||
ImportMapping,
|
||||
LoginRequest,
|
||||
MagicLinkRequest,
|
||||
PlanningNotificationRequest,
|
||||
@@ -23,10 +24,13 @@ import { ApiError, type PlanningApi } from './types';
|
||||
export function createHttpApi(baseUrl: string): PlanningApi {
|
||||
async function request<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const token = getAuthToken();
|
||||
// Pour un envoi `multipart/form-data`, on laisse le navigateur fixer
|
||||
// lui-même l'en-tête `Content-Type` (avec la frontière).
|
||||
const isForm = init?.body instanceof FormData;
|
||||
const res = await fetch(`${baseUrl}${path}`, {
|
||||
...init,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...(isForm ? {} : { 'Content-Type': 'application/json' }),
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
...init?.headers,
|
||||
},
|
||||
@@ -93,6 +97,19 @@ export function createHttpApi(baseUrl: string): PlanningApi {
|
||||
remove: (editionId, id) =>
|
||||
request(`${base(editionId)}/volunteers/${id}`, { method: 'DELETE' }),
|
||||
},
|
||||
imports: {
|
||||
analyze: (editionId, file: File) => {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
return request(`${base(editionId)}/import/analyze`, { method: 'POST', body: form });
|
||||
},
|
||||
execute: (editionId, file: File, mapping: ImportMapping) => {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
form.append('mapping', JSON.stringify(mapping));
|
||||
return request(`${base(editionId)}/import/execute`, { method: 'POST', body: form });
|
||||
},
|
||||
},
|
||||
positions: {
|
||||
list: (editionId) => request(`${base(editionId)}/positions`),
|
||||
get: (editionId, id) => request(`${base(editionId)}/positions/${id}`),
|
||||
|
||||
Reference in New Issue
Block a user