Email de test : récapitulatif de planning compilé
ci-cd / build-backend (push) Successful in 46s
ci-cd / deploy (push) Successful in 12s
ci-cd / build-frontend (push) Successful in 21s

L'email de test reprend le modèle en cours d'édition, balises remplies
avec le planning d'un bénévole au choix (premier avec un créneau par
défaut), option lien de connexion sans vrai jeton, sujet « [Test] … » —
même fonction de rendu que l'envoi réel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
AdamThomas
2026-10-28 19:44:14 +01:00
co-authored by Claude Opus 5.5
parent 461742eb78
commit 440466ccf9
12 changed files with 262 additions and 46 deletions
+16 -4
View File
@@ -2054,10 +2054,22 @@ export function createMockApi(): PlanningApi {
notifications: {
// Pas de serveur SMTP en démo : rien n'est envoyé, comme
// `EMAIL_ENABLED=false` côté serveur.
sendTest: (_edition, email) => {
const address = email.trim();
if (!/^[^\s@]+@[^\s@]+$/.test(address)) throw new ApiError(422, 'notifications.invalid_email');
return delay({ status: 'disabled' as const, detail: null, smtp_host: 'localhost:25', smtp_from: 'noreply@festival.local' });
sendTest: (_edition, body) => {
if (!/^[^\s@]+@[^\s@]+$/.test(body.email.trim())) {
throw new ApiError(422, 'notifications.invalid_email');
}
const assigned = new Set(state.assignments.map((a) => a.volunteer_id));
const sorted = [...state.volunteers].sort((a, b) => a.last_name.localeCompare(b.last_name, 'fr'));
const example =
sorted.find((v) => v.id === body.volunteer_id) ?? sorted.find((v) => assigned.has(v.id)) ?? sorted[0];
return delay({
status: 'disabled' as const,
detail: null,
smtp_host: 'localhost:25',
smtp_from: 'noreply@festival.local',
example_volunteer_id: example?.id ?? null,
example_volunteer_name: example ? `${example.first_name} ${example.last_name}`.trim() : '',
});
},
sendPlanning: (_edition, body: PlanningNotificationRequest) => {
const ids = body.volunteer_ids ?? null;