diff --git a/docs/superpowers/plans/2026-05-19-mail-phase5-ui-main.md b/docs/superpowers/plans/2026-05-19-mail-phase5-ui-main.md new file mode 100644 index 0000000..30efe93 --- /dev/null +++ b/docs/superpowers/plans/2026-05-19-mail-phase5-ui-main.md @@ -0,0 +1,1203 @@ +# Mail Integration — Phase 5 : UI principale /mail (3 colonnes) + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Construire la page `/mail` en layout 3 colonnes (dossiers / liste / lecteur) avec composants Vue réutilisables, en branchant le store `useMailStore` créé en Phase 4. Sanitize HTML body via DOMPurify. Refus visuel pour ROLE_CLIENT. + +**Architecture:** 1 page Nuxt `pages/mail.vue`, 4 composants sous `components/mail/`, 1 composable helper `composables/useSystemFolderLabel.ts`. Mapping noms dossiers système (`INBOX` → "Boîte de réception") côté front. Deep-link `?messageId=X` pour sélectionner un mail à l'ouverture. Pas de mode édition/réponse en MVP. + +**Tech Stack:** Nuxt 4, Vue 3 Composition API + ` + + + ``` + +- [ ] **Step 2 : Commit** + + ```bash + git -C /home/r-dev/malio-dev/Lesstime add frontend/components/mail/MailRefreshButton.vue + git -C /home/r-dev/malio-dev/Lesstime commit -m "feat(mail) : MailRefreshButton — bouton sync manuel, disabled pendant syncing" + ``` + +--- + +### Task 5 : Composant `MailFolderTree.vue` + +Arbre récursif des dossiers mail. Reçoit `folderTree` (computed du store, déjà arborifié). Émet `select` avec le `path` du dossier cliqué. + +- [ ] **Step 1 : Créer `frontend/components/mail/MailFolderTree.vue`** + + ```vue + + + + ``` + + Note technique : l'indentation dynamique par CSS `calc` avec `v-bind(depth)` n'est pas fiable dans Tailwind — utiliser `:style` natif comme ci-dessus (`paddingLeft: depth * 0.75rem`). La récursivité via `` fonctionne car Nuxt auto-importe les composants. + +- [ ] **Step 2 : Commit** + + ```bash + git -C /home/r-dev/malio-dev/Lesstime add frontend/components/mail/MailFolderTree.vue + git -C /home/r-dev/malio-dev/Lesstime commit -m "feat(mail) : MailFolderTree — arbre récursif dossiers, badges unread, icônes système" + ``` + +--- + +### Task 6 : Composant `MailMessageList.vue` + +Liste paginée des messages du dossier sélectionné. Infinite scroll via `IntersectionObserver` sur un sentinel div en bas de liste. Indicateurs visuels : point ● (non lu), étoile ⭐ (flagged), trombone 📎 (hasAttachments), date relative. + +- [ ] **Step 1 : Créer `frontend/components/mail/MailMessageList.vue`** + + ```vue + + + + ``` + +- [ ] **Step 2 : Commit** + + ```bash + git -C /home/r-dev/malio-dev/Lesstime add frontend/components/mail/MailMessageList.vue + git -C /home/r-dev/malio-dev/Lesstime commit -m "feat(mail) : MailMessageList — liste paginée infinite scroll, indicateurs lu/étoilé/PJ/date relative" + ``` + +--- + +### Task 7 : Composant `MailMessageViewer.vue` + +Lecteur de mail complet. Reçoit le détail complet du message sélectionné. Sanitize le HTML body via `sanitizeMailHtml`. Gère le toggle "Afficher les images distantes". Actions : Créer tâche, Lier à tâche, Marquer lu/non-lu, Étoiler. Téléchargement PJ. + +- [ ] **Step 1 : Créer `frontend/components/mail/MailMessageViewer.vue`** + + ```vue + + + + ``` + + Points clés : + - `v-html="sanitizedBody"` est le **seul** `v-html` du composant, et il reçoit toujours la sortie de `sanitizeMailHtml` — jamais le `rawHtml` brut directement. + - La bannière "Afficher les images" est visible dès qu'il y a un `bodyHtml` et que `showImages` est false. + - `handleDownload` crée un lien `` temporaire pour déclencher le téléchargement du Blob retourné par `mailService.downloadAttachment`. + +- [ ] **Step 2 : Commit** + + ```bash + git -C /home/r-dev/malio-dev/Lesstime add frontend/components/mail/MailMessageViewer.vue + git -C /home/r-dev/malio-dev/Lesstime commit -m "feat(mail) : MailMessageViewer — header, body sanitizé DOMPurify, PJ téléchargeables, 4 actions" + ``` + +--- + +### Task 8 : Page `pages/mail.vue` + +Page principale en layout 3 colonnes. Intègre les 4 composants créés ci-dessus. Gère le deep-link `?messageId=X`. Vérifie le rôle ROLE_CLIENT (redirection `/portal`). Le middleware global `auth.global.ts` gère déjà l'authentification de base — ici on ajoute seulement le check spécifique ROLE_CLIENT dans `onMounted`. + +- [ ] **Step 1 : Créer `frontend/pages/mail.vue`** + + ```vue + + + + ``` + + Points clés : + - `await navigateTo('/portal')` au niveau du `` dans un corps de mail (via devtools ou fixture) + - [ ] Ouvrir le mail dans le lecteur → aucune alerte JS, contenu rendu inoffensif + - [ ] Vérifier dans le DOM inspecté que la balise `` → aucune alerte | +| Images distantes bloquées par défaut | Body avec `` → placeholder visible | +| Infinite scroll fonctionnel | Scroll jusqu'en bas de la liste → chargement page suivante | +| Deep-link `?messageId=X` | `http://localhost:3002/mail?messageId=42` → message 42 sélectionné | +| Pas d'erreur console Vue | DevTools → onglet Console → aucune erreur rouge | + +La Phase 6 (Intégration tâches : MailCreateTaskModal, MailLinkTaskModal, onglet "Mails" TaskDrawer) peut commencer dès que tous ces critères sont satisfaits.