Front : retrait des compétences, disponibilités en fenêtres horaires
Aligne le frontend sur le back-end (étape 14). - Types : suppression de `skill_codes` / `required_skill_codes` / `AvailabilityStatus` / `MISSING_REQUIRED_SKILL` ; ajout de `AvailabilityRead` / `AvailabilitySet` et de la surface API `availability` (list / replace / listEdition) + hooks associés. - Fiche bénévole : bloc « compétences » remplacé par un éditeur de disponibilités (plages date + heures libres, `PUT` en bloc). - Assistant d'import : plus de colonnes compétences ni disponibilités (mapping réduit à l'identité) ; rapport simplifié. - Grille des besoins : chaque candidat porte un badge de couverture (disponible / partiel / non déclaré) calculé sur ses fenêtres, et la liste est triée « disponibles d'abord ». Nouvel util `availabilityCoverage` / `uncoveredMinutes` dans `lib/planning`, portage du moteur back-end. - Mock : `state.availability` passe à des fenêtres `AvailabilityRead[]`, validation `OUTSIDE_AVAILABILITY` recalculée sur l'union des fenêtres, jeu de démo et import CSV adaptés. typecheck / lint / build / smoke au vert. 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
be51770b51
commit
36d108b47d
+29
-34
@@ -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 AvailabilityStatus = 'AVAILABLE' | 'IF_NEEDED' | 'UNAVAILABLE';
|
||||
export type Role = 'COORDINATOR' | 'LEAD' | 'VOLUNTEER';
|
||||
export type AuthMethod = 'password' | 'magic_link';
|
||||
|
||||
@@ -23,8 +22,7 @@ export type ViolationCode =
|
||||
| 'SHIFT_OVERLAP'
|
||||
| 'OUTSIDE_AVAILABILITY'
|
||||
| 'DAILY_HOURS_EXCEEDED'
|
||||
| 'INSUFFICIENT_REST'
|
||||
| 'MISSING_REQUIRED_SKILL';
|
||||
| 'INSUFFICIENT_REST';
|
||||
|
||||
export type ViolationSeverity = 'BLOCKING' | 'WARNING';
|
||||
|
||||
@@ -104,7 +102,6 @@ export interface VolunteerRead {
|
||||
email: string | null;
|
||||
phone: 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. */
|
||||
@@ -119,7 +116,6 @@ export interface VolunteerCreate {
|
||||
email?: string | null;
|
||||
phone?: string | null;
|
||||
comment?: string | null;
|
||||
skill_codes?: string[];
|
||||
artist_ids?: string[];
|
||||
wished_position_ids?: string[];
|
||||
}
|
||||
@@ -130,12 +126,37 @@ export interface VolunteerUpdate {
|
||||
email?: string | null;
|
||||
phone?: string | null;
|
||||
comment?: string | null;
|
||||
/** null / absent = inchangé ; [] = vider. Idem artist_ids / wished_position_ids. */
|
||||
skill_codes?: string[] | null;
|
||||
/** null / absent = inchangé ; [] = vider. */
|
||||
artist_ids?: string[] | null;
|
||||
wished_position_ids?: string[] | null;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------- //
|
||||
// Availability (disponibilités déclarées par le bénévole) //
|
||||
// --------------------------------------------------------------------------- //
|
||||
export interface AvailabilityWindowInput {
|
||||
/** Date ISO (YYYY-MM-DD). */
|
||||
date: string;
|
||||
/** Heure « HH:MM » ou « HH:MM:SS ». end <= start ⇒ se termine le lendemain. */
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
}
|
||||
|
||||
export interface AvailabilitySet {
|
||||
windows: AvailabilityWindowInput[];
|
||||
}
|
||||
|
||||
export interface AvailabilityRead {
|
||||
id: string;
|
||||
edition_id: string;
|
||||
volunteer_id: string;
|
||||
date: string;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------- //
|
||||
// Artist (programmation) //
|
||||
// --------------------------------------------------------------------------- //
|
||||
@@ -167,8 +188,7 @@ export type ImportFieldKey =
|
||||
| 'last_name'
|
||||
| 'email'
|
||||
| 'phone'
|
||||
| 'comment'
|
||||
| 'skills';
|
||||
| 'comment';
|
||||
|
||||
export interface ImportColumnMapping {
|
||||
first_name: string;
|
||||
@@ -176,20 +196,11 @@ export interface ImportColumnMapping {
|
||||
email?: string | null;
|
||||
phone?: string | null;
|
||||
comment?: string | null;
|
||||
skills?: string | null;
|
||||
}
|
||||
|
||||
export interface ImportAvailabilityColumn {
|
||||
header: string;
|
||||
/** Date ISO (YYYY-MM-DD). */
|
||||
date: string;
|
||||
day_part_code: string;
|
||||
}
|
||||
|
||||
export interface ImportMapping {
|
||||
dry_run: boolean;
|
||||
columns: ImportColumnMapping;
|
||||
availability_columns: ImportAvailabilityColumn[];
|
||||
}
|
||||
|
||||
export interface ImportPreviewRow {
|
||||
@@ -197,14 +208,6 @@ export interface ImportPreviewRow {
|
||||
values: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface ImportDayPartInfo {
|
||||
code: string;
|
||||
label: string;
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
order: number;
|
||||
}
|
||||
|
||||
export interface ImportAnalyzeResponse {
|
||||
filename: string;
|
||||
format: 'csv' | 'xlsx';
|
||||
@@ -212,9 +215,6 @@ export interface ImportAnalyzeResponse {
|
||||
row_count: number;
|
||||
preview: ImportPreviewRow[];
|
||||
suggested_mapping: Partial<Record<ImportFieldKey, string>>;
|
||||
/** Dates ISO couvertes par l'édition. */
|
||||
edition_dates: string[];
|
||||
day_parts: ImportDayPartInfo[];
|
||||
}
|
||||
|
||||
export type ImportSeverity = 'ERROR' | 'WARNING';
|
||||
@@ -240,8 +240,6 @@ export interface ImportReport {
|
||||
created: number;
|
||||
updated: number;
|
||||
skipped: number;
|
||||
availabilities_written: number;
|
||||
skills_created: string[];
|
||||
rows: ImportRowReport[];
|
||||
}
|
||||
|
||||
@@ -287,7 +285,6 @@ export interface ShiftRead {
|
||||
ends_at: string;
|
||||
min_staff: number;
|
||||
ideal_staff: number;
|
||||
required_skill_codes: string[];
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
@@ -298,7 +295,6 @@ export interface ShiftCreate {
|
||||
ends_at: string;
|
||||
min_staff?: number;
|
||||
ideal_staff?: number;
|
||||
required_skill_codes?: string[];
|
||||
}
|
||||
|
||||
export interface ShiftUpdate {
|
||||
@@ -307,7 +303,6 @@ export interface ShiftUpdate {
|
||||
ends_at?: string;
|
||||
min_staff?: number;
|
||||
ideal_staff?: number;
|
||||
required_skill_codes?: string[] | null;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------- //
|
||||
|
||||
Reference in New Issue
Block a user