---
name: project_notifications
description: "Système de notifications in-app — table DB, routes backend, cloche topbar, page /notifications"
metadata: 
  node_type: memory
  type: project
  originSessionId: dc9d0717-dc15-48a7-a013-2988b2e0ad4a
---

## Architecture

**Table SQLite** : `notifications` (id, user_id FK, type, title, body, link, read, created_at). Les notifications sont strictement personnelles (filtrées par `user_id` via JWT sur toutes les routes).

**Routes backend** `backend/src/routes/notifications.js` :
- `GET /` — liste paginée (params: limit, offset, unread_only, type)
- `GET /count` — nombre non lus (polling)
- `PATCH /read-all` — tout marquer lu
- `PATCH /:id/read` — marquer un lu
- `DELETE /:id` — supprimer une notif
- `DELETE /` — tout supprimer
- `POST /seed` — générer des notifs de test (requireAdmin)

⚠️ Routes statiques (`/count`, `/read-all`, `/seed`) déclarées **avant** `/:id` pour éviter le conflit Express.

**Composants frontend** :
- `NotifTypeAvatar.jsx` — source unique des icônes SVG (paths Lucide) et couleurs par type ; exporte `TYPE_META` et le composant par défaut
- `NotificationBell.jsx` — cloche dans la topbar, polling 30s via `fetchCount`, écoute `window` event `notif:refresh` pour rechargement immédiat
- `pages/Notifications.jsx` — page `/notifications`, layout fragment + `.topbar` hidden, bloc card 65% centré, bloc Simulation admin en dessous

**Événement cross-composant** : `window.dispatchEvent(new CustomEvent('notif:refresh'))` à dispatcher après toute création de notification pour forcer le rechargement immédiat du compteur cloche.

## Types de notifications

| Type | Label | Icône Lucide | Couleur |
|---|---|---|---|
| `system` | Système | Radio | Gris |
| `ticket_reply` | Ticket | FileText | Bleu |
| `info` | Info | Info | Bleu ciel |
| `team` | Équipe | Users | Violet |
| `success` | Succès | Check | Vert |
| `warning` | Avertissement | AlertTriangle | Ambre |
| `security` | Sécurité | ShieldAlert | Rouge |
| `announcement` | Annonce | Megaphone | Rose |

Les icônes sont des SVG inline (paths Lucide) car `lucide-react` n'est pas installé dans le projet.

## CSS notable

- `.notif-bell-btn` : sans fond, sans bordure, sans effet hover — juste l'icône et le badge
- `.notif-row-unread` / `.notif-item-unread` : `border-left: 3px solid var(--primary)` + fond primaire à 4-5% d'opacité
- `.notif-dropdown-list` : scrollbar fine (4px) via `scrollbar-width: thin`
- Layout page : fragment root + `.topbar` hidden → wrapper `.notif-center-wrap` → `.card.notif-block` (max-width 65%, margin auto)

**Why:** Notifications personnelles par user_id ; `notif:refresh` évite d'attendre le poll de 30s après une action.
**How to apply:** Toute future source de notifications doit dispatcher `notif:refresh` après insertion. Nouveaux types à ajouter dans `TYPE_META` de `NotifTypeAvatar.jsx`.
