FormTemplate porte désormais un logo (image, PUT/GET .../form/logo — GET
public comme .../form/public, affiché sur /inscription) et un texte
d'introduction libre (PATCH .../form, description désormais optionnelle
comme is_open). Écran de configuration (/inscriptions) : nouveau panneau
« Personnalisation » pour importer le logo et rédiger le texte. Le
formulaire public affiche le logo en grand au-dessus du panneau et le
texte juste sous le titre.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
La photo ajoutée (fichier ou prise depuis l'appareil) est recadrée en carré
côté navigateur avant l'envoi (centré, tronque le surplus, réencodée en
JPEG ≤ 1024 px de côté) — elle est donc toujours carrée en base, sans
recadrage serveur, ce qui profite aussi aux vignettes des badges et des
feuilles de poste. Un aperçu agrandi (180 px) s'affiche dès que la photo
est choisie.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Un poste ne génère plus de créneaux à sa création : la coordination crée
elle-même ceux dont elle a besoin, avec ses propres horaires de début et
de fin (ConfigGrid.tsx). La génération depuis les créneaux types reste
disponible en option (bouton « Générer les créneaux »).
La grille des besoins devient un vrai axe des temps : une colonne = 30 min,
bornée par jour à la plage réellement utilisée, avec les cases fusionnées
pour correspondre aux horaires de chaque créneau (buildTimeGrid /
placeInTimeGrid). La « Vue bénévoles » garde son ancien modèle (une colonne
par créneau distinct), plus adapté à son tableau bénévole × créneau.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Nom + téléphone du référent du poste (Position.lead_account_id), juste
sous le sous-titre (jour/lieu) — « Référent : à désigner » si aucun.
Même source que le référent affiché à l'écran bénévole
(volunteers.py:get_volunteer_planning).
Vérifié : pytest (287 passés, dont les nouveaux tests avec/sans
référent), ruff, alembic check — tous verts (pas de changement
frontend, la feuille reste un simple téléchargement de PDF).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
« Case « je suis disponible »" / « Case « je veux bien payer une
cotisation »" étaient en fait le libellé de configuration (écran
coordination) réutilisé tel quel comme texte de la case à cocher côté
formulaire public — d'où le ton administratif. Clés dédiées
(publicForm.field.*) avec une formulation à la première personne, plus
adaptée à quelqu'un qui remplit le formulaire.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Une page par poste et par jour, listant les créneaux avec les bénévoles
affectés et leur téléphone — à imprimer et afficher sur place. Aucune
nouvelle entité : dérivé de Position/Shift/Assignment/Volunteer
existants (contrairement aux badges, pas de personnalisation à
configurer). Un créneau à besoin 0/0 sans affectation n'apparaît pas.
Backend : app/sheets/pdf.py (ReportLab, Platypus — SimpleDocTemplate/
Table plutôt que le canvas bas niveau des badges, plus adapté à un
rapport texte multi-pages), POST /editions/{id}/position-sheets/generate
(COORDINATION, {position_ids?} — absent = tous les postes).
Frontend : bouton « Feuilles de poste » dans la grille des besoins,
respecte le filtre de catégorie déjà actif à l'écran.
Vérifié : pytest (284 passés), ruff, alembic check, tsc --noEmit,
eslint, vite build, smoke (flux de bout en bout en mode démonstration)
— tous verts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Photo transmise via le formulaire public (Volunteer.photo) : nouveau
composant partagé VolunteerAvatar (photo si disponible, sinon repli sur
le carré d'initiales existant, même gabarit dans les deux cas).
- Écran bénévole (VolunteerHomeView) : photo dans le bandeau d'accueil,
à côté du message de bienvenue.
- Écran référent (MobileLeadPage) : photo devant le nom de chaque membre
de l'équipe, à la place du carré d'initiales.
GET .../volunteers/{id}/photo n'était accessible qu'à COORDINATION/
RÉFÉRENT ; ouvert aussi à l'intéressé lui-même (même garde que
get_volunteer), sinon l'écran bénévole ne pouvait jamais charger sa
propre photo.
Vérifié : pytest (274 passés, dont le nouveau test d'accès à sa propre
photo), ruff, tsc --noEmit, eslint, vite build, smoke — tous verts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Retire « constructeur de formulaire » des exclusions du CLAUDE.md (§ 5) —
décision explicite prise en conversation.
Un formulaire par édition (COORDINATION choisit les champs actifs parmi
neuf : email, téléphone, vœux de poste — max 2, vœux d'artiste — un par
soir de festival, vœu de compagnon en texte libre, disponibilité/
cotisation déclaratives, photo, commentaire ; nom/prénom toujours
collectés) ouvert/fermé à volonté, avec un lien à partager
(/inscription, aucun compte requis).
Backend : FormTemplate/FormField (migration 0013), quatre nouveaux champs
sur Volunteer (photo, companion_wish_note, self_declared_available,
willing_to_pay_fee), app/api/forms.py — les deux seuls endpoints publics
de toute l'API (GET .../form/public, POST .../form/public/submit),
protégés par hCaptcha (app/forms/captcha.py, désactivé sans
HCAPTCHA_SECRET_KEY) et un filet de sécurité global par édition
(form_submission_limiter). resolve_owned_ids/set_artists/
set_wished_positions déplacés vers app/api/_common.py, partagés avec
volunteers.py.
Frontend : écran de configuration (/inscriptions) avec lien copiable et
bascule ouvert/fermé, formulaire public (/inscription, hors RequireAuth)
avec widget hCaptcha chargé dynamiquement, capture photo native
(<input capture>), vœux de poste/artiste avec les mêmes règles que le
back-end. Réponses du formulaire visibles et éditables depuis la fiche
bénévole existante (ConfigVolunteers.tsx).
Vérifié : pytest (273 passés), ruff, alembic check, tsc --noEmit, eslint,
vite build, smoke (rendu SSR de chaque écran + flux de bout en bout du
formulaire en mode démonstration) — tous verts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Le format déduit de l'image importée (300 dpi supposés, étape
précédente) donne un badge minuscule pour une image à résolution web —
ajout d'un contrôle « largeur du badge (mm) » dans l'écran de
personnalisation : la hauteur suit proportionnellement (ratio de
l'image). PUT /editions/{id}/badges/template/size écrase la taille
déduite de l'image ; la réimporter la recalcule à nouveau.
Vérifié : pytest (250 passés), ruff, tsc --noEmit, eslint, vite build,
smoke — tous verts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Lignes trop longues détectées par ruff (badges.py, tests) ; ajout de
/badges au smoke test frontend (rendu SSR de chaque écran protégé).
Vérifié dans ce commit : pytest (248 passés), ruff check, alembic
check, tsc --noEmit, eslint, vite build, smoke — tous verts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Le format du badge n'est plus fixé à CR80 : il est déduit des pixels de
l'image du recto à l'import (résolution supposée 300 dpi,
app/badges/pdf.py:image_size_mm), stocké sur BadgeTemplate (migration
0012). L'éditeur (BadgesPage.tsx) et la génération PDF s'alignent sur ce
format réel ; CR80 reste le repère par défaut tant qu'aucune image n'est
importée. Le verso est ajusté sans déformation (preserveAspectRatio).
- Le champ « Postes affectés » liste désormais une ligne par créneau
(triées chronologiquement) : nom du poste + horaire, et le référent du
poste s'il y en a un et que ce n'est pas le bénévole badgé lui-même.
Texte multi-lignes pris en charge par la génération PDF (découpe sur
`\n`, hauteur de ligne calculée en mm) et par l'aperçu de l'éditeur.
- Corrige au passage un bug d'unités dans le positionnement vertical du
texte (police en points confondue avec des millimètres).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Recto personnalisable (fond image + champs positionnés : nom, poste(s)
affectés, catégorie, rôle) via un éditeur visuel glisser-déposer ; verso
fixe, la même image pour tous les bénévoles. Nouvel écran « Badges »
(COORDINATION uniquement, /badges).
Backend : modèle BadgeTemplate/BadgeField (migration 0011), génération
PDF isolée (app/badges/pdf.py, ReportLab — planches recto suivies des
planches verso correspondantes pour une impression recto-verso), route
POST /editions/{id}/badges/generate, tests (module pur + API).
Frontend : client HTTP (upload multipart, réponses binaires images/PDF),
client mock (mode démonstration), éditeur de positionnement en
millimètres (coordonnées partagées avec le backend), écran de génération
avec sélection des bénévoles et téléchargement.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>