Front : programmation des artistes et vœux des bénévoles

Aligne le frontend sur le back-end (étape 13).

- Types : retrait de `tshirt_size` / `diet` (Volunteer et mapping
  d'import) ; ajout de `ArtistRead/Create/Update` et des champs
  `artist_ids` / `wished_position_ids` sur la fiche bénévole.
- Surface API `artists` (HTTP + mock) et hooks
  `useArtists` / `useCreateArtist` / `useUpdateArtist` / `useDeleteArtist`.
- Nouvel onglet Configuration « Programmation » : liste d'artistes
  éditable, colonne par jour de l'édition (création, renommage,
  suppression ; 409 doublon, 422 nom vide).
- Fiche bénévole & formulaire d'ajout manuel : champs t-shirt / régime
  retirés, sélecteurs « Artistes à voir » et « Postes souhaités »
  (puces retirables, 422 si id étranger).
- Mock : jeu de démo enrichi (2 artistes par jour, vœux aléatoires),
  cascade sur suppression d'artiste / de poste, import CSV sans
  t-shirt / régime.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM
This commit is contained in:
AdamThomas
2026-09-10 22:22:45 +02:00
co-authored by Claude Sonnet 5
parent 24caece7df
commit 81609eecc5
10 changed files with 533 additions and 99 deletions
+32 -12
View File
@@ -15,7 +15,6 @@ export type PositionCategory =
// Depuis l'Étape 9 back-end : une affectation est valide dès sa création,
// il n'y a plus de statut (proposée / confirmée…). La retirer = supprimer la ligne.
export type AssignmentSource = 'SOLVER' | 'MANUAL';
export type TshirtSize = 'XS' | 'S' | 'M' | 'L' | 'XL' | 'XXL' | 'XXXL';
export type AvailabilityStatus = 'AVAILABLE' | 'IF_NEEDED' | 'UNAVAILABLE';
export type Role = 'COORDINATOR' | 'LEAD' | 'VOLUNTEER';
export type AuthMethod = 'password' | 'magic_link';
@@ -104,10 +103,12 @@ export interface VolunteerRead {
last_name: string;
email: string | null;
phone: string | null;
tshirt_size: TshirtSize | null;
diet: string | null;
comment: string | null;
skill_codes: string[];
/** Vœux : artistes que le bénévole veut voir. */
artist_ids: string[];
/** Vœux : postes que le bénévole voudrait tenir. */
wished_position_ids: string[];
created_at: string;
updated_at: string;
}
@@ -117,10 +118,10 @@ export interface VolunteerCreate {
last_name: string;
email?: string | null;
phone?: string | null;
tshirt_size?: TshirtSize | null;
diet?: string | null;
comment?: string | null;
skill_codes?: string[];
artist_ids?: string[];
wished_position_ids?: string[];
}
export interface VolunteerUpdate {
@@ -128,11 +129,34 @@ export interface VolunteerUpdate {
last_name?: string;
email?: string | null;
phone?: string | null;
tshirt_size?: TshirtSize | null;
diet?: string | null;
comment?: string | null;
/** null / absent = inchangé ; [] = vider les compétences. */
/** null / absent = inchangé ; [] = vider. Idem artist_ids / wished_position_ids. */
skill_codes?: string[] | null;
artist_ids?: string[] | null;
wished_position_ids?: string[] | null;
}
// --------------------------------------------------------------------------- //
// Artist (programmation) //
// --------------------------------------------------------------------------- //
export interface ArtistRead {
id: string;
edition_id: string;
name: string;
/** Jour de passage, date ISO (YYYY-MM-DD). */
performance_date: string;
created_at: string;
updated_at: string;
}
export interface ArtistCreate {
name: string;
performance_date: string;
}
export interface ArtistUpdate {
name?: string;
performance_date?: string;
}
// --------------------------------------------------------------------------- //
@@ -143,8 +167,6 @@ export type ImportFieldKey =
| 'last_name'
| 'email'
| 'phone'
| 'tshirt_size'
| 'diet'
| 'comment'
| 'skills';
@@ -153,8 +175,6 @@ export interface ImportColumnMapping {
last_name: string;
email?: string | null;
phone?: string | null;
tshirt_size?: string | null;
diet?: string | null;
comment?: string | null;
skills?: string | null;
}