From d897bcedb4db32bea021ad303e807a56b28bcb70 Mon Sep 17 00:00:00 2001 From: louispaulb Date: Thu, 21 May 2026 21:33:10 -0400 Subject: [PATCH] feat(campaigns): auto-clean first/last names (QC accents + compound split) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Map CSV migrated from the legacy ERP carries names with two common defects: missing French accents (Stephane, Andre, Frederic), and compound first names that were typed without a separator (Marcandre, Mariejosee, Jeanphilippe). Sending an email "Bonjour stephane," instead of "Bonjour Stéphane," reads as sloppy automation. Fix both at parse time so the user sees the corrected names in Step 2 and can override inline if the auto-cleaner got it wrong. Backend (lib/campaigns.js): - FR_NAME_FIXES — 100+ entry dictionary mapping lowercase no-accent Québec first names to their canonical accented form (André, Stéphane, Frédéric, Geneviève, Hélène, Joséée, etc.). Sourced from MIQ baby names + older-generation curation. - COMPOUND_PARTS — list of common name parts (jean, marie, anne, marc, philippe, françois, etc.) that combine into QC compound first names. When two parts appear concatenated with no separator, the cleaner splits and hyphenates them. Example: "Marcandre" → ["marc","andre"] → "Marc-André" (dictionary then applies accent). - titleCaseToken — proper Title Case respecting apostrophes (O'Brien, L'Heureux) and hyphens (Marie-Ève). Uses \p{L} Unicode class so it works on accented chars correctly. - cleanName(raw) — full pipeline: trim → Title Case → dictionary lookup per word → compound split fallback. Applied to firstname AND lastname in parseMapCsv. - nameWarning(name) — heuristic flag for cases the cleaner couldn't confidently handle: digit in name, single letter, abnormally long without separator (likely two stuck names not in COMPOUND_PARTS). Returns a short FR description for the UI tooltip. - parseMapCsv now returns firstname/lastname (cleaned) + firstname_raw/ lastname_raw (original from CSV) + cleaned_changed bool + name_warnings per recipient. UI uses these to show before/after + flags. UI (CampaignNewPage Step 2): - New counter card "Noms à vérifier" — count of recipients with at least one nameWarning. Only renders if > 0. - Info banner above the recipients table: "X nom(s) auto-corrigés (...) Y nom(s) suspects (...)" - Per-row icons in the firstname + lastname columns: • ⚠ amber WARNING — cleaner flagged this name as suspicious (tooltip shows the reason: "deux prénoms collés", "contient un chiffre", etc.) • ✨ green AUTO_FIX_HIGH — auto-cleaner changed something at parse time (tooltip shows the original raw value) Both icons are tooltip-only — no action required. - Click any name cell → q-popup-edit opens an inline input. Type the correction, Enter saves. ESC cancels. This is the manual override path for any name the auto-cleaner mishandled. Tests (manual via end-to-end smoke against prod): STEPHANE TREMBLAY → Stéphane Tremblay ✓ accent + Title Case marie tremblay → Marie Tremblay ✓ Title Case only Marcandre Boileau → Marc-André Boileau ✓ compound + accent Jean Francois Lebrun → Jean François Lebrun ✓ accent only Mariejosee Lapierre → Marie-Josée Lapierre ✓ compound + double accent Andre LAPRISE → André Laprise ✓ both fixed Helene St-Pierre → Hélène St-Pierre ✓ accent, hyphen preserved Frederic O'Brien → Frédéric O'Brien ✓ accent, apostrophe preserved Co-Authored-By: Claude Opus 4.7 --- .../campaigns/pages/CampaignNewPage.vue | 67 ++++++++ services/targo-hub/lib/campaigns.js | 147 +++++++++++++++++- 2 files changed, 212 insertions(+), 2 deletions(-) diff --git a/apps/ops/src/modules/campaigns/pages/CampaignNewPage.vue b/apps/ops/src/modules/campaigns/pages/CampaignNewPage.vue index 8037055..226638a 100644 --- a/apps/ops/src/modules/campaigns/pages/CampaignNewPage.vue +++ b/apps/ops/src/modules/campaigns/pages/CampaignNewPage.vue @@ -119,8 +119,27 @@
Liens en surplus
+ + +
{{ namesNeedingReview }}
+
Noms à vérifier
+
+
+ + + + + {{ namesAutoCorrected }} nom(s) auto-corrigés (Title Case, accents québécois, + prénoms composés séparés). L'icône ✨ verte dans le tableau indique les changements. + + + {{ namesNeedingReview }} nom(s) suspects — icône ⚠ amber : cliquer la cellule + pour éditer en place. + + + @@ -151,6 +170,44 @@ + + +