Files
benevoles/frontend
AdamThomasandClaude Sonnet 5 096b7cd26a
ci-cd / build-backend (push) Successful in 1m12s
ci-cd / build-frontend (push) Successful in 18s
ci-cd / deploy (push) Successful in 12s
Lien d'inscription protégé par jeton, reçus fiscaux mécénat, infobulles et revue de sécurité
- Lien d'inscription protégé par un jeton (FormTemplate.access_token,
  /inscription/<token>), avec régénération depuis l'écran de configuration.
- Reçus fiscaux mécénat (cerfa 11580*05) : un PDF par bénévole ayant payé en
  mécénat, donateur/montant (chiffres et toutes lettres en français,
  app/mecenat/number_words.py)/date complétés par-dessus le modèle officiel.
- Jeu de démonstration : bénévoles avec cotisation classique ou mécénat payée.
- Infobulles (HelpTip et détail de cellule de la grille des besoins)
  repositionnées en position: fixed via JS, bornées à l'écran.
- Revue de sécurité : logo des emails en pièce jointe inline au lieu d'une
  URL (fuyait le jeton d'inscription), sujet retiré du log de remise des
  emails (pouvait porter un nom de bénévole), photo du formulaire public
  revalidée par décodage réel avant stockage, export Excel protégé contre
  l'injection de formule, sondage du statut de paiement limité en
  fréquence, pyjwt mis à jour.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-02 07:47:17 +02:00
..
2026-09-16 21:09:28 +02:00

Frontend — Gestion des bénévoles

React + Vite + TypeScript + Tailwind. Interface en français, code en anglais.

Intègre le design Claude Design « Bénévoles Festival » et consomme l'API back-end (editions/{id}/volunteers · positions · shifts · assignments · assignments/validate · matrix).

Modes de données

VITE_API_MODE (voir .env.example) :

  • mock (défaut) — jeu de démonstration déterministe en mémoire, implémenté avec exactement la même surface que l'API (src/api/mock/). Aucun back-end requis ; utile tant que le seed serveur n'existe pas.
  • http — API réelle. VITE_EDITION_ID désigne l'édition ; en dev Vite proxifie /api vers VITE_API_TARGET (défaut http://localhost:8000).

Le passage d'un mode à l'autre ne change aucun écran : tout passe par src/api/ (client HTTP ou mock) et les hooks React Query de src/api/hooks.ts.

Authentification & rôles

Toutes les pages métier sont derrière <RequireAuth> (src/auth/).

  • Coordination → /connexion/coordination : email + mot de passe (POST /editions/{id}/auth/login).
  • Référents / bénévoles → /connexion : lien magique (POST …/auth/magic-link puis …/auth/verify). L'email étant stubé, le mode mock affiche directement le lien de démo à cliquer.
  • Le jeton JWT est stocké en localStorage, envoyé en Authorization: Bearer sur chaque requête ; une réponse 401 déconnecte.
  • Comptes de démo (mode mock) : coordination coordination@lessonsdautomne.fr / demo ; référents referent1..3@lessonsdautomne.fr ; chaque bénévole ayant un email.

Visibilité des onglets par rôle :

Onglet Coordination Référent Bénévole
01 Grille · 02 Vue bénévole · 06 Configuration ✅ — —
04 Bénévole · mobile — — ✅
05 Référent · mobile — ✅ —

L'accueil après connexion dépend du rôle (homePath).

Écrans (onglets)

Depuis l'Étape 9 back-end, une affectation n'a plus de statut : elle est valide dès sa création, la retirer = supprimer la ligne. Il n'y a donc plus d'écran « Confirmations » (ancien onglet 03).

# Route Source de données Actions
01 /grille GET /matrix (assigned / ideal) clic cellule → panneau : GET /assignments?shift_id, POST /assignments/validate par candidat, POST / DELETE /assignments
02 /benevoles volunteers + shifts + assignments lecture (surcharge / oubliés calculés côté client)
04 /mobile-benevole assignments?volunteer_id (du compte) lecture¹
05 /mobile-referent poste du référent → assignments?shift_id pointage local (hors périmètre)
06 /configuration positions · shifts · volunteers CRUD postes / créneaux (min/idéal) / bénévoles (dont suppression RGPD) ; onglet Messages → POST /notifications/planning (récapitulatif + lien de connexion)

¹ En mode http, l'API n'expose pas encore aux bénévoles le détail des créneaux : l'écran dégrade proprement (créneaux sans détail, message d'info). Fonctionne intégralement en mode mock.

Commandes

Action Commande
Installer npm install
Dev npm run dev → http://localhost:5173
Build npm run build
Lint npm run lint
Types npm run typecheck
Rendu headless + vérifs API mock npm run smoke

Conventions

  • Aucun texte d'interface en dur : src/i18n (t(key, params)) + locales/fr.json.
  • Les libellés de données (nom de poste, etc.) viennent de l'API.
  • src/api/schema.ts est le miroir de backend/app/api/schemas.py — à garder synchrone.
  • violationText() (src/lib/planning.ts) rend les violations du moteur ; les params suivent le contrat de backend/app/validation/engine.py.
  • Alias @/ → src/.

Arborescence

src/
├── main.tsx
├── api/
│   ├── schema.ts            # types miroir du back-end (dont auth)
│   ├── types.ts             # interface PlanningApi + ApiError
│   ├── session.ts           # jeton Bearer partagé + callback 401
│   ├── http-client.ts       # implémentation HTTP
│   ├── mock/                # implémentation mémoire (dataset + client + comptes + moteur)
│   ├── index.ts             # sélection mock / http, EDITION_ID
│   └── hooks.ts             # hooks React Query (lectures + mutations)
├── auth/           auth-context (AuthProvider/useAuth) · RequireAuth · roles
├── app/            AppShell (onglets filtrés par rôle) · router
├── pages/          un fichier par écran (+ auth/, grille/, config/, mobile/)
├── components/     ui.tsx (primitives) · state.tsx (Loading / ErrorNote)
├── lib/            time.ts · planning.ts (treillis, heures, surcharge, violationText) · env.ts · cx.ts
└── i18n/           t() + locales/fr.json