Files
crowdlending-app/.cowork/memory/ef8f4a3f-abbf-422c-8382-f0bf9d3a9cdf/memory/project_communication.md
T

3.1 KiB

name, description, metadata
name description metadata
project-communication Page Communication — tickets support + notifications : architecture, comportements UI, jobs backend
node_type type originSessionId
memory project 19a3ce4d-7c1a-418b-9ca2-65b6157249db

Page Communication (frontend/src/pages/Communication.jsx)

Architecture générale

3 volets : sidebar (volet 1), liste (volet 2), détail (volet 3). Onglets : support (tickets) | notifications.

Filtres chips (volet 2)

  • Tickets : multi-select via useState(new Set(['open', 'pending'])) ; si aucune chip active → liste vide (pas "tout afficher")
  • Notifications : multi-select useState(new Set(['unread'])) au démarrage ; même règle liste vide si 0 chip active
  • Chips actives = fond var(--primary) + checkmark SVG blanc ; cumulatives

Comportements notifications

  • Pas de présélection automatique au chargement ni au changement d'onglet
  • La notification sélectionnée reste jusqu'à clic explicite
  • Menu ⋮ dans le volet 3 : "Marquer comme lu" / "Tout considérer comme lu" / "Tout supprimer"

Dropdowns portal (pattern obligatoire)

Tous les dropdowns custom (TagSelect, TypeDropdown, RecipientDropdown) utilisent createPortal(content, document.body) + position: fixed + getBoundingClientRect() pour échapper aux stacking contexts.

Composant RecipientDropdown

Dropdown searchable pour les broadcasts. Trois niveaux :

  • "Tous les utilisateurs" (value '')
  • "Tous les administrateurs" (value 'admins') — routé vers WHERE role='admin' côté backend
  • Utilisateurs individuels filtrés par display_name / email avec avatars initiales

Broadcast payload

payload.user_id = bcUserId === 'admins' ? 'admins' : Number(bcUserId);

Ticket detail header (volet 3)

Structure colonne :

  • Ligne 1 : chip Type + titre (flex:1) + StatusBadge
  • Ligne 2 : "Ouvert par Nom · date [— assigné à Nom]" à gauche + chips pages à droite
  • margin-top: 25px entre les deux lignes

Droits

  • Utilisateur : voit uniquement ses tickets et ses notifications
  • Admin : voit tous les tickets ; voit ses notifs + notifs notifyAdmins
  • Actions admin-only : Assigner à, Mettre en attente, Réouvrir, Clôturer
  • "Modifier la catégorisation" : accessible à tous (owner + admin)
  • "Fermer" (panneau) : accessible à tous

Pièges React connus

  • {msg.is_admin && <span>} → si is_admin = 0 (SQLite), affiche "0". Toujours {!!msg.is_admin && ...}
  • Images dans messages : classe msg-inline-img + wrapper msg-img-wrap ajouté par useEffect. Margin 7px sur .msg-img-wrap ET .msg-inline-img pour couvrir les deux cas.

Jobs backend

  • autoTicketStatus.js : open→pending (2j sans réponse), pending→resolved (5j sans réponse créateur) — toutes les heures
  • autoCleanNotifs.js : supprime notifications >7 jours sauf type security — toutes les heures

Why: Nettoyage automatique pour éviter l'accumulation infinie de notifications lues. How to apply: Si on ajoute un nouveau type de notification critique à ne jamais purger, l'ajouter à la clause type != 'security' dans autoCleanNotifs.js.