- api : PlanningNotificationRequest/Result dans schema.ts, méthode
notifications.sendPlanning (http + mock), hook useSendPlanningNotification
- mock : compte les destinataires avec/sans email, émet des liens magiques
quand {lien_connexion} est présent
- ConfigMail : plus une maquette. Éditeur objet/corps, variables cliquables
({prenom} {nom} {nb_creneaux} {nb_heures} {creneaux} {lien_connexion}),
boutons « Envoyer le récapitulatif » et « Envoyer avec lien de connexion »,
retour d'envoi (queued / sans adresse) et ErrorNote
- i18n config.mail.* mis à jour ; onglet « MESSAGES » (plus « (MAQUETTE) »)
typecheck + lint + build + smoke : OK
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM
105 lines
5.0 KiB
Markdown
105 lines
5.0 KiB
Markdown
# 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
|
|
```
|