Frontend : écran Messages branché sur l'envoi d'emails
- 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
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b268e308ab
commit
6b08dcc953
@@ -5,6 +5,7 @@ import type {
|
||||
AssignmentRead,
|
||||
AssignmentValidateResult,
|
||||
MatrixResponse,
|
||||
PlanningNotificationRequest,
|
||||
ShiftRead,
|
||||
TokenResponse,
|
||||
Violation,
|
||||
@@ -425,6 +426,36 @@ export function createMockApi(): PlanningApi {
|
||||
get: () => delay(buildMatrix()),
|
||||
},
|
||||
|
||||
notifications: {
|
||||
sendPlanning: (_edition, body: PlanningNotificationRequest) => {
|
||||
const ids = body.volunteer_ids ?? null;
|
||||
const targets = state.volunteers.filter((v) => ids === null || ids.includes(v.id));
|
||||
const withEmail = targets.filter((v) => v.email);
|
||||
const wantsLink =
|
||||
(body.subject ?? '').includes('{lien_connexion}') ||
|
||||
(body.body ?? '').includes('{lien_connexion}');
|
||||
for (const volunteer of withEmail) {
|
||||
if (!wantsLink) continue;
|
||||
const account = state.accounts.find(
|
||||
(a) => a.volunteer_id === volunteer.id && a.auth_method === 'magic_link',
|
||||
);
|
||||
if (!account) continue;
|
||||
const raw = `mlt.${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;
|
||||
magicTokens.set(raw, {
|
||||
accountId: account.id,
|
||||
expiresAt: Date.now() + MAGIC_LINK_TTL_MS,
|
||||
used: false,
|
||||
});
|
||||
lastMagicLink.set(account.email.toLowerCase(), raw);
|
||||
}
|
||||
return delay({
|
||||
queued: withEmail.length,
|
||||
skipped_no_email: targets.length - withEmail.length,
|
||||
recipients: withEmail.map((v) => v.id),
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
auth: {
|
||||
login: (_edition, { email, password }) => {
|
||||
const account = accountByEmail(email);
|
||||
|
||||
Reference in New Issue
Block a user