Frontend : suppression du statut d'affectation (suite Étape 9)

Le back-end (Étape 9) a retiré AssignmentStatus : une affectation est valide
dès sa création, la retirer = supprimer la ligne.

- schema.ts : AssignmentRead/Create/Update sans `status` ;
  MatrixShift.{confirmed, proposed} → `assigned`.
- mock : générateur sans statut (plus de rollStatus / DECLINED) ; matrice
  = compte unique ; create → validation toujours exécutée ; PATCH ne porte
  plus que source/locked ; runValidation compte toutes les affectations.
- lib/planning : suppression de isActive() et statusLabel().
- Grille + panneau : cellule « affectés / idéal », plus de +proposés ni de
  badge confirmé/proposé ni de bouton « confirmer ».
- Vue par bénévole : une seule trame d'affectation (bleu).
- Mobile bénévole : plus de bouton « JE CONFIRME » ni de bannière.
- Mobile référent : plus de libellé de statut par équipier.
- Onglet 03 « Confirmations » supprimé (route, page, nav, ROUTE_ROLES) —
  il n'a plus d'objet. Coordination : onglets 01, 02, 06.
- i18n : clés de statut / de l'écran Confirmations retirées.
- Vérifs : build tsc + vite, eslint (0 problème), npm run smoke.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AwswqSChc3Rwtu61pRXiY2
This commit is contained in:
AdamThomas
2026-09-10 07:51:11 +02:00
co-authored by Claude Sonnet 5
parent 6e16db4b7e
commit 8d333deb23
16 changed files with 75 additions and 353 deletions
+3 -21
View File
@@ -3,7 +3,6 @@ import { hoursBetween } from '@/lib/time';
import type {
AccountRead,
AssignmentRead,
AssignmentStatus,
PositionCategory,
PositionRead,
ShiftRead,
@@ -105,12 +104,6 @@ function iso(dateStr: string, hour: number): string {
return `${dateStr}T${String(hour).padStart(2, '0')}:00:00`;
}
function rollStatus(roll: number): AssignmentStatus {
if (roll < 0.72) return 'CONFIRMED';
if (roll < 0.95) return 'PROPOSED';
return 'DECLINED';
}
function demoEmail(firstName: string, lastName: string): string {
const n = (s: string) => s.toLowerCase().normalize('NFD').replace(/[^a-z]/g, '');
return `${n(firstName)}.${n(lastName)}@mail.fr`;
@@ -240,33 +233,23 @@ export function buildMockState(): MockState {
}
for (const v of pool.slice(0, target)) {
const status = rollStatus(rnd());
assignments.push({
id: `a${seq}`,
edition_id,
volunteer_id: v.id,
shift_id: shift.id,
status,
source: 'SOLVER',
locked: false,
created_at: NOW,
updated_at: NOW,
});
seq += 1;
if (status !== 'DECLINED') {
busy.add(`${v.id}|${shift.id}`);
dayHours.set(`${v.id}|${dateStr}`, (dayHours.get(`${v.id}|${dateStr}`) ?? 0) + duration);
totalHours.set(v.id, (totalHours.get(v.id) ?? 0) + duration);
}
busy.add(`${v.id}|${shift.id}`);
dayHours.set(`${v.id}|${dateStr}`, (dayHours.get(`${v.id}|${dateStr}`) ?? 0) + duration);
totalHours.set(v.id, (totalHours.get(v.id) ?? 0) + duration);
}
}
assignments
.filter((a) => a.volunteer_id === me.id)
.forEach((a, i) => {
a.status = i === 0 ? 'CONFIRMED' : 'PROPOSED';
});
OVERLOADED.forEach((index) => {
const v = volunteers[index];
const friday = shifts.filter((s) => s.starts_at.slice(0, 10) === '2026-10-17');
@@ -284,7 +267,6 @@ export function buildMockState(): MockState {
edition_id,
volunteer_id: v.id,
shift_id: shift.id,
status: 'CONFIRMED',
source: 'MANUAL',
locked: false,
created_at: NOW,