# 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.