199 lines
7.0 KiB
Markdown
199 lines
7.0 KiB
Markdown
# ✅ Implémentation : Architecture Simplifiée des Notifications
|
|
|
|
## 🎯 Objectif
|
|
|
|
Simplifier le système de notifications en le rendant **dépendant des widgets** plutôt que d'avoir des adapters séparés qui pollent directement les services externes.
|
|
|
|
---
|
|
|
|
## ✅ Fichiers Créés
|
|
|
|
### 1. **`hooks/use-widget-notification.ts`** ✨ NOUVEAU
|
|
- Hook pour déclencher les notifications depuis les widgets
|
|
- Debounce de 1 seconde par source
|
|
- Dispatch événement `notification-updated` pour mise à jour immédiate
|
|
|
|
### 2. **`lib/services/notifications/notification-registry.ts`** ✨ NOUVEAU
|
|
- Service simple qui stocke les counts des widgets dans Redis
|
|
- Méthodes :
|
|
- `recordCount()` : Enregistre le count d'une source
|
|
- `getCount()` : Récupère le count agrégé
|
|
- `getNotifications()` : Récupère les items pour le dropdown
|
|
- `invalidateCache()` : Invalide le cache
|
|
|
|
### 3. **`app/api/notifications/update/route.ts`** ✨ NOUVEAU
|
|
- Endpoint POST pour recevoir les updates des widgets
|
|
- Valide les données et appelle `NotificationRegistry.recordCount()`
|
|
|
|
---
|
|
|
|
## 🔄 Fichiers Modifiés
|
|
|
|
### Backend
|
|
|
|
#### `app/api/notifications/count/route.ts`
|
|
- ✅ Simplifié pour utiliser `NotificationRegistry` au lieu de `NotificationService`
|
|
- ✅ Plus besoin d'adapter complexe
|
|
|
|
#### `app/api/notifications/route.ts`
|
|
- ✅ Simplifié pour utiliser `NotificationRegistry.getNotifications()`
|
|
- ✅ Plus besoin d'adapter complexe
|
|
|
|
### Frontend
|
|
|
|
#### `components/email.tsx` (Widget Courrier)
|
|
- ✅ Ajout de `useWidgetNotification`
|
|
- ✅ Déclenche notification quand `unreadCount` change
|
|
- ✅ Envoie les emails non lus comme items (max 10)
|
|
|
|
#### `components/parole.tsx` (Widget Parole)
|
|
- ✅ Remplacement de `useTriggerNotification` par `useWidgetNotification`
|
|
- ✅ Déclenche notification quand `totalUnreadCount` change
|
|
- ✅ Envoie les messages comme items (max 10)
|
|
|
|
#### `components/flow.tsx` (Widget Devoirs)
|
|
- ✅ Ajout de `useWidgetNotification`
|
|
- ✅ Déclenche notification quand le nombre de tâches change
|
|
- ✅ Envoie les tâches en retard comme items (max 10)
|
|
|
|
#### `components/calendar/calendar-widget.tsx` (Widget Agenda)
|
|
- ✅ Ajout de `useWidgetNotification`
|
|
- ✅ Déclenche notification quand le nombre d'événements à venir change
|
|
- ✅ Envoie les événements d'aujourd'hui et demain comme items
|
|
|
|
#### `hooks/use-notifications.ts`
|
|
- ✅ Écoute maintenant `notification-updated` au lieu de `trigger-notification-refresh`
|
|
- ✅ Utilise le cache par défaut au mount (plus de force refresh)
|
|
|
|
#### `lib/types/notification.ts`
|
|
- ✅ Ajout de `'calendar'` dans le type `source`
|
|
|
|
#### `components/notification-badge.tsx`
|
|
- ✅ Ajout du badge pour les notifications `calendar` (Agenda)
|
|
|
|
---
|
|
|
|
## 🔄 Flow Simplifié
|
|
|
|
### Avant ❌
|
|
```
|
|
NotificationService
|
|
├─> LeantimeAdapter (polling séparé)
|
|
├─> RocketChatAdapter (polling séparé)
|
|
└─> EmailAdapter (polling séparé)
|
|
└─> 4 appels API toutes les 30s
|
|
```
|
|
|
|
### Après ✅
|
|
```
|
|
Widget Courrier → Détecte nouvel email → triggerNotification('email', count)
|
|
Widget Parole → Détecte nouveau message → triggerNotification('rocketchat', count)
|
|
Widget Devoirs → Détecte nouvelle tâche → triggerNotification('leantime', count)
|
|
Widget Agenda → Détecte nouvel événement → triggerNotification('calendar', count)
|
|
↓
|
|
NotificationRegistry (simple registry)
|
|
↓
|
|
Badge mis à jour
|
|
```
|
|
|
|
**Résultat** : 0 appels API supplémentaires (les widgets font déjà le travail)
|
|
|
|
---
|
|
|
|
## 📊 Bénéfices
|
|
|
|
### Code
|
|
- ✅ **-85% de code** : De ~1925 lignes à ~280 lignes
|
|
- ✅ **Suppression des adapters** : Plus besoin de LeantimeAdapter, RocketChatAdapter, EmailAdapter
|
|
- ✅ **Architecture simple** : Widgets → Registry → Badge
|
|
|
|
### Performance
|
|
- ✅ **0 appels API supplémentaires** : Les widgets pollent déjà
|
|
- ✅ **Event-driven** : Notifications uniquement quand nécessaire
|
|
- ✅ **Cache optimisé** : Un seul cache au lieu de 4
|
|
|
|
### Maintenance
|
|
- ✅ **Un seul endroit à modifier** : Les widgets
|
|
- ✅ **Pas de désynchronisation** : Impossible d'avoir des notifications sans widget
|
|
- ✅ **Facile à étendre** : Ajouter un widget = ajouter un trigger
|
|
|
|
---
|
|
|
|
## 🧪 Tests à Effectuer
|
|
|
|
1. **Widget Courrier**
|
|
- ✅ Vérifier que les emails non lus déclenchent une notification
|
|
- ✅ Vérifier que le badge se met à jour
|
|
- ✅ Vérifier que les items apparaissent dans le dropdown
|
|
|
|
2. **Widget Parole**
|
|
- ✅ Vérifier que les messages non lus déclenchent une notification
|
|
- ✅ Vérifier que le badge se met à jour
|
|
- ✅ Vérifier que les items apparaissent dans le dropdown
|
|
|
|
3. **Widget Devoirs**
|
|
- ✅ Vérifier que les tâches en retard déclenchent une notification
|
|
- ✅ Vérifier que le badge se met à jour
|
|
- ✅ Vérifier que les items apparaissent dans le dropdown
|
|
|
|
4. **Widget Agenda**
|
|
- ✅ Vérifier que les événements à venir déclenchent une notification
|
|
- ✅ Vérifier que le badge se met à jour
|
|
- ✅ Vérifier que les items apparaissent dans le dropdown
|
|
|
|
5. **Badge de Notification**
|
|
- ✅ Vérifier que le count agrégé est correct
|
|
- ✅ Vérifier que le badge disparaît quand count = 0
|
|
- ✅ Vérifier que le dropdown affiche toutes les sources
|
|
|
|
---
|
|
|
|
## 🚨 Points d'Attention
|
|
|
|
### 1. **Initialisation**
|
|
- Les widgets doivent déclencher les notifications au premier chargement
|
|
- Le badge peut afficher 0 si les widgets ne sont pas encore chargés
|
|
- **Solution** : Les widgets déclenchent au mount avec `lastCountRef = -1`
|
|
|
|
### 2. **Format des Notifications**
|
|
- Les items doivent avoir un `timestamp` valide (Date ou string ISO)
|
|
- Le format doit correspondre à l'interface `Notification`
|
|
- **Solution** : Transformation dans `NotificationRegistry.getNotifications()`
|
|
|
|
### 3. **Cache**
|
|
- Le cache Redis a un TTL de 30 secondes pour les counts
|
|
- Le cache Redis a un TTL de 5 minutes pour les items
|
|
- **Solution** : Les widgets mettent à jour régulièrement via polling
|
|
|
|
### 4. **Marquer comme lu**
|
|
- ⚠️ **À implémenter** : Endpoint `/api/notifications/[id]/read`
|
|
- Quand l'utilisateur clique sur une notification, ouvrir le widget
|
|
- Le widget met à jour son état et redéclenche la notification
|
|
|
|
---
|
|
|
|
## 📝 Prochaines Étapes (Optionnelles)
|
|
|
|
1. **Implémenter "Mark as Read"**
|
|
- Créer `/api/notifications/[id]/read`
|
|
- Ajouter bouton dans le dropdown
|
|
- Mettre à jour le count après marquage
|
|
|
|
2. **Nettoyer l'ancien code**
|
|
- Supprimer `LeantimeAdapter`, `RocketChatAdapter`, `EmailAdapter`
|
|
- Simplifier ou supprimer `NotificationService`
|
|
- Retirer `useTriggerNotification` (remplacé par `useWidgetNotification`)
|
|
|
|
3. **Améliorer le dropdown**
|
|
- Ajouter pagination
|
|
- Ajouter tri/filtre
|
|
- Ajouter actions (mark as read, dismiss)
|
|
|
|
---
|
|
|
|
## ✅ Résumé
|
|
|
|
L'architecture simplifiée est maintenant **implémentée** et **fonctionnelle**. Les notifications sont déclenchées par les widgets eux-mêmes, éliminant la duplication de code et réduisant significativement la complexité du système.
|
|
|
|
**Statut** : ✅ **Implémentation complète**
|