From 166e2c33660e6a873d7becbd5f0949d318f6af2d Mon Sep 17 00:00:00 2001 From: AdamThomas Date: Tue, 15 Sep 2026 22:05:52 +0200 Subject: [PATCH] =?UTF-8?q?Fiche=20b=C3=A9n=C3=A9vole=20:=20recherche=20po?= =?UTF-8?q?ur=20les=20compagnons,=20badges=20pour=20artistes/postes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Vœu de compagnon : le sélecteur (déjà trié par ordre alphabétique) gagne un champ de recherche (insensible aux accents/casse) qui filtre la liste déroulante — plus pratique avec 100+ bénévoles. - Vœux d'artiste et de poste : remplacé le menu déroulant par des badges à cocher (`BadgeWishPicker`, réutilise le composant `Chip`) — toutes les options sont visibles d'un coup, un clic les bascule, plus besoin d'ouvrir une liste pour un petit nombre d'options. Vérifié : typecheck, lint, build, smoke frontend OK. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017uUsRg7XzopkCPWimwg9ZM --- frontend/src/i18n/locales/fr.json | 3 +- .../src/pages/config/ConfigVolunteers.tsx | 83 ++++++++++++++++--- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/frontend/src/i18n/locales/fr.json b/frontend/src/i18n/locales/fr.json index 4c6a467..5d95742 100644 --- a/frontend/src/i18n/locales/fr.json +++ b/frontend/src/i18n/locales/fr.json @@ -293,9 +293,8 @@ "config.vol.noArtists": "Aucun artiste choisi", "config.vol.noPositions": "Aucun poste choisi", "config.vol.noCompanions": "Aucun bénévole choisi", - "config.vol.pickArtist": "Ajouter un artiste…", - "config.vol.pickPosition": "Ajouter un poste…", "config.vol.pickCompanion": "Ajouter un bénévole…", + "config.vol.searchCompanion": "Rechercher un bénévole…", "config.vol.colWishes": "VŒUX", "config.vol.wishesCount": "{count} vœu(x)", "config.vol.addAvailabilityHint": "Les disponibilités se renseignent sur la fiche du bénévole, une fois celui-ci créé.", diff --git a/frontend/src/pages/config/ConfigVolunteers.tsx b/frontend/src/pages/config/ConfigVolunteers.tsx index 1f189c8..42b62f9 100644 --- a/frontend/src/pages/config/ConfigVolunteers.tsx +++ b/frontend/src/pages/config/ConfigVolunteers.tsx @@ -28,7 +28,7 @@ import type { VolunteerCreate, VolunteerRead, } from '@/api/schema'; -import { FieldLabel, HelpTip, TextInput } from '@/components/ui'; +import { Chip, FieldLabel, HelpTip, TextInput } from '@/components/ui'; import { ErrorNote, Loading } from '@/components/state'; import { t } from '@/i18n'; import { shortDayLabel } from '@/lib/time'; @@ -151,6 +151,15 @@ function VolunteerAccessSection({ ); } +function foldAccents(value: string): string { + return value + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') + .toLowerCase(); +} + +/** Sélecteur de vœux avec recherche (bénévoles : liste potentiellement + * longue) — options déjà triées par ordre alphabétique par l'appelant. */ function WishPicker({ label, options, @@ -158,6 +167,7 @@ function WishPicker({ onChange, emptyLabel, addLabel, + searchPlaceholder, }: { label: ReactNode; options: WishOption[]; @@ -165,9 +175,15 @@ function WishPicker({ onChange: (ids: string[]) => void; emptyLabel: string; addLabel: string; + searchPlaceholder: string; }) { + const [search, setSearch] = useState(''); const byId = new Map(options.map((o) => [o.id, o])); const available = options.filter((o) => !selected.includes(o.id)); + const needle = foldAccents(search.trim()); + const filtered = needle + ? available.filter((o) => foldAccents(`${o.hint ?? ''} ${o.label}`).includes(needle)) + : available; return (
{label} @@ -186,16 +202,28 @@ function WishPicker({ {emptyLabel} ) : null}
+ setSearch(e.target.value)} + placeholder={searchPlaceholder} + disabled={available.length === 0} + className="mb-[6px] w-full border-2 border-ink bg-paper p-[7px] font-mono text-[11px] disabled:opacity-50" + />