gigafibre-fsm/apps/ops/src
louispaulb d961c57f9e Events: reminder ("Petit rappel") for non-registered invitees
- New reminder engine (events.js): reminderCandidates(eventId, sourceCampaignId)
  targets recipients from a past invitation send who haven't submitted an RSVP
  yet — covering both "never clicked" and "clicked but didn't register" — while
  excluding pending/failed/excluded rows. Returns a status breakdown (not
  opened / opened not clicked / clicked not registered) for preview before
  sending. reminderSend() creates+starts a new tracked campaign (reminder_of
  linking back to the source), reusing the same send worker with an
  isReminder flag.
- isReminder threads through inviteSubject (prefixes "Petit rappel — "/
  "Reminder — ") and inviteEmailFestive (adds a 🔔 badge above the title);
  exposed on invite-preview and test-send too so the look can be checked
  before a real reminder blast.
- New routes: GET /events/:id/campaigns (past sends for the picker),
  GET /events/:id/reminder-preview (count + breakdown + sample, no side
  effects), POST /events/:id/reminder-send.
- campaigns.js: listCampaigns() summary gains event_id/type/reminder_of
  (same read, no extra cost) and is now exported, so events.js can list an
  event's past campaigns without loading each one in full.
- EventsPage.vue: new "Rappel" tab in the send dialog — pick a source send,
  see the live count/breakdown/recipient list, confirm-to-send. Test tab
  gains a toggle to preview the reminder look via a real test-send.
- CampaignDetailPage.vue: "Ouvert le"/"Cliqué le" columns on the recipient
  table (shared by gift and event campaigns).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 09:56:15 -04:00
..
api Events: reminder ("Petit rappel") for non-registered invitees 2026-07-24 09:56:15 -04:00
boot feat(ops): dispatch auto complet + perf Boîte/rapports + fix session 2026-07-02 08:49:35 -04:00
components fix(ui): icône corbeille pour les suppressions (au lieu d'un X ambigu avec « fermer ») 2026-07-23 21:57:43 -04:00
composables chore(reconcile): commit MES hunks déployés dans les fichiers co-édités (split via git apply --cached) 2026-07-19 20:06:47 -04:00
config feat(ops): « / » = accueil universel adapté au rôle (step 3/3) + consolidation Thème/Équipe→Paramètres 2026-07-19 15:35:33 -04:00
css fix(ops/mobile): Network GPON tient sur mobile (onglets défilants + arbre enroulé + boutons tactiles) 2026-07-04 20:56:11 -04:00
data ops : types de job = source unique (config/job-types) 2026-07-07 21:27:32 -04:00
layouts feat(assistant): désambiguïsation client via options cliquables (un seul champ) 2026-07-20 08:54:53 -04:00
modules Events: reminder ("Petit rappel") for non-registered invitees 2026-07-24 09:56:15 -04:00
pages Events: reminder ("Petit rappel") for non-registered invitees 2026-07-24 09:56:15 -04:00
router feat(ops): « / » = accueil universel adapté au rôle (step 3/3) + consolidation Thème/Équipe→Paramètres 2026-07-19 15:35:33 -04:00
stores chore(ops): supprime le sous-système dispatch MORT (23 fichiers, 0 importeur) 2026-07-19 10:32:18 -04:00
utils ticket panel: décodage entités HTML + fil unifié + lien client cherchable 2026-07-07 07:09:25 -04:00
App.vue fix(ops): overlay accès — message exact « n'a pas pu charger » + détail erreur + piste extension 2026-07-03 17:31:41 -04:00