Widget Devoir Finition

This commit is contained in:
alma 2026-01-24 16:11:21 +01:00
parent 099c3b61bd
commit 4ce912e34d
6 changed files with 0 additions and 1115 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@ -1,104 +0,0 @@
# 🐛 Debug : Bouton couleur manquant
## Diagnostic
Le code est bien présent dans le fichier `app/missions/equipe/page.tsx` :
- ✅ Import de `Palette` (ligne 4)
- ✅ Fonction `handleOpenColorPicker` (ligne 503)
- ✅ Bouton avec icône Palette (ligne 1040-1049)
- ✅ Dialog de sélection de couleur (ligne 1377+)
## Vérifications à faire
### 1. Êtes-vous sur la bonne page ?
Votre screenshot montre : **"Gestion des équipes"** avec onglet **"Groupes (7)"**
✅ C'est bien la page `/missions/equipe` avec l'onglet Groupes activé.
### 2. Vérifier le cache Next.js
```bash
# Dans le terminal :
cd /Users/alma/Documents/NeahStable
# Supprimer le cache Next.js
rm -rf .next
# Rebuild
npm run dev
```
### 3. Vérifier le cache du navigateur
Dans votre navigateur :
- **Chrome/Edge** : Ctrl+Shift+R (Windows) ou Cmd+Shift+R (Mac)
- **Firefox** : Ctrl+F5 (Windows) ou Cmd+Shift+R (Mac)
- Ou ouvrir DevTools (F12) → Onglet Network → Cocher "Disable cache"
### 4. Vérifier que le serveur dev tourne
```bash
# Arrêter le serveur actuel (Ctrl+C)
# Puis relancer :
npm run dev
```
### 5. Vérifier dans le code source de la page
1. Ouvrir la page `/missions/equipe`
2. Clic droit → "Inspecter" (F12)
3. Onglet "Elements" ou "Inspector"
4. Chercher "Palette" dans le HTML (Ctrl+F)
5. Est-ce que vous trouvez `<svg>` avec la classe contenant "Palette" ?
### 6. Vérifier les erreurs console
1. F12 → Onglet "Console"
2. Y a-t-il des erreurs en rouge ?
3. Copier/coller les erreurs si présentes
## Solution temporaire
Si le bouton n'apparaît toujours pas, utilisez la page `/groups` à la place :
1. Aller sur `/groups`
2. Dans la colonne ACTIONS, cliquer sur **⋮** (trois points)
3. Sélectionner "Couleur du calendrier"
Le code est identique dans `components/groups/groups-table.tsx` et devrait fonctionner.
## Code exact du bouton
Voici le code exact qui devrait être rendu (ligne 1040-1049) :
```tsx
<Button
variant="ghost"
size="sm"
onClick={() => handleOpenColorPicker(group)}
disabled={actionLoading === group.id}
className="h-8 w-8 p-0"
title="Couleur du calendrier"
>
<Palette className="h-4 w-4 text-gray-500" />
</Button>
```
Ce bouton devrait apparaître entre le bouton "Modifier" (Edit2) et "Gérer les membres" (Users).
## Ordre des boutons attendu
Dans la colonne ACTIONS, vous devriez voir **4 boutons** :
1. ✏️ **Edit2** - Modifier le nom du groupe
2. 🎨 **Palette** - Couleur du calendrier ← NOUVEAU
3. 👥 **Users** - Gérer les membres
4. 🗑️ **Trash2** - Supprimer le groupe
## Si rien ne fonctionne
Envoyez-moi :
1. Screenshot de la console (F12 → Console)
2. Screenshot du code source HTML (F12 → Elements, autour de la table)
3. Résultat de : `ls -la .next` dans le terminal

View File

@ -1,356 +0,0 @@
# Guide de Déploiement Docker - Production
Ce guide explique comment déployer l'application Neah en production avec Docker.
## 📋 Prérequis
- Docker Engine 20.10+
- Docker Compose 2.0+
- Au moins 4GB de RAM disponible
- Au moins 10GB d'espace disque
## 🚀 Déploiement Rapide
### 1. Préparation de l'environnement
```bash
# Cloner le repository (si ce n'est pas déjà fait)
git clone <repository-url>
cd NeahStable
# Créer le fichier .env.production avec vos variables
cp .env.example .env.production
nano .env.production # Éditez avec vos valeurs
```
### 2. Configuration des variables d'environnement
Créez un fichier `.env.production` avec toutes les variables nécessaires :
```bash
# Copier le fichier d'exemple
cp env.production.example .env.production
# Éditer avec vos valeurs
nano .env.production
```
**Important** : Toutes les commandes `docker-compose` doivent utiliser `--env-file .env.production` pour charger les variables.
```env
# Database
POSTGRES_USER=neah_user
POSTGRES_PASSWORD=VOTRE_MOT_DE_PASSE_SECURISE
POSTGRES_DB=calendar_db
DATABASE_URL=postgresql://neah_user:VOTRE_MOT_DE_PASSE_SECURISE@db:5432/calendar_db?schema=public
# Redis
REDIS_PASSWORD=VOTRE_MOT_DE_PASSE_REDIS_SECURISE
REDIS_URL=redis://:VOTRE_MOT_DE_PASSE_REDIS_SECURISE@redis:6379
# NextAuth
NEXTAUTH_URL=https://hub.slm-lab.net
NEXTAUTH_SECRET=VOTRE_SECRET_NEXTAUTH_TRES_LONG_ET_SECURISE
# Keycloak
KEYCLOAK_ISSUER=https://connect.slm-lab.net/realms/cercle
KEYCLOAK_CLIENT_ID=lab
KEYCLOAK_CLIENT_SECRET=VOTRE_CLIENT_SECRET
KEYCLOAK_REALM=cercle
NEXT_PUBLIC_KEYCLOAK_ISSUER=https://connect.slm-lab.net/realms/cercle
# Application
APP_PORT=3000
NODE_ENV=production
```
### 3. Build et démarrage
```bash
# Build l'image Docker
docker-compose -f docker-compose.prod.yml --env-file .env.production build
# Démarrer les services (base de données et Redis)
docker-compose -f docker-compose.prod.yml --env-file .env.production up -d db redis
# Attendre que les services soient prêts (environ 10 secondes)
sleep 10
# Appliquer les migrations Prisma
docker-compose -f docker-compose.prod.yml --env-file .env.production run --rm app npx --yes prisma@6.4.1 migrate deploy
# Démarrer l'application
docker-compose -f docker-compose.prod.yml --env-file .env.production up -d app
# Vérifier les logs
docker-compose -f docker-compose.prod.yml --env-file .env.production logs -f app
```
## 🔧 Configuration Avancée
### Variables d'environnement importantes
#### Base de données PostgreSQL
- `POSTGRES_USER` : Utilisateur PostgreSQL
- `POSTGRES_PASSWORD` : **Changez absolument le mot de passe par défaut !**
- `POSTGRES_DB` : Nom de la base de données
#### Redis
- `REDIS_PASSWORD` : **Changez absolument le mot de passe par défaut !**
#### NextAuth
- `NEXTAUTH_URL` : URL publique de votre application (ex: `https://hub.slm-lab.net`)
- `NEXTAUTH_SECRET` : Secret pour signer les tokens JWT (générez avec `openssl rand -base64 32`)
#### Keycloak
- `KEYCLOAK_ISSUER` : URL de votre instance Keycloak
- `KEYCLOAK_CLIENT_ID` : ID du client OAuth
- `KEYCLOAK_CLIENT_SECRET` : Secret du client OAuth
- `KEYCLOAK_REALM` : Nom du realm Keycloak
### Ports exposés
Par défaut, les ports suivants sont exposés :
- **3000** : Application Next.js
- **5432** : PostgreSQL (uniquement sur localhost)
- **6379** : Redis (uniquement sur localhost)
Pour modifier les ports, éditez `docker-compose.prod.yml` :
```yaml
app:
ports:
- "80:3000" # Exposer sur le port 80
```
### Volumes et persistance
Les données sont stockées dans des volumes Docker :
- `postgres_data` : Base de données PostgreSQL
- `redis_data` : Données Redis
Pour sauvegarder :
```bash
# Sauvegarder PostgreSQL
docker exec neah-postgres-prod pg_dump -U ${POSTGRES_USER:-neah_user} ${POSTGRES_DB:-calendar_db} > backup.sql
# Restaurer PostgreSQL
docker exec -i neah-postgres-prod psql -U ${POSTGRES_USER:-neah_user} ${POSTGRES_DB:-calendar_db} < backup.sql
```
## 🔄 Mises à jour
### Mettre à jour l'application
```bash
# Arrêter l'application
docker-compose -f docker-compose.prod.yml --env-file .env.production stop app
# Rebuild l'image
docker-compose -f docker-compose.prod.yml --env-file .env.production build app
# Appliquer les migrations si nécessaire
docker-compose -f docker-compose.prod.yml --env-file .env.production run --rm app npx --yes prisma@6.4.1 migrate deploy
# Redémarrer
docker-compose -f docker-compose.prod.yml --env-file .env.production up -d app
```
### Appliquer les migrations Prisma
```bash
# Vérifier le statut des migrations
docker-compose -f docker-compose.prod.yml --env-file .env.production run --rm app npx --yes prisma@6.4.1 migrate status
# Appliquer les migrations
docker-compose -f docker-compose.prod.yml --env-file .env.production run --rm app npx --yes prisma@6.4.1 migrate deploy
```
## 📊 Monitoring et Logs
### Voir les logs
```bash
# Tous les services
docker-compose -f docker-compose.prod.yml --env-file .env.production logs -f
# Un service spécifique
docker-compose -f docker-compose.prod.yml --env-file .env.production logs -f app
docker-compose -f docker-compose.prod.yml --env-file .env.production logs -f db
docker-compose -f docker-compose.prod.yml --env-file .env.production logs -f redis
```
### Health Check
L'application expose un endpoint de health check :
- `GET http://localhost:3000/api/health`
Réponse :
```json
{
"status": "ok",
"timestamp": "2024-01-01T00:00:00.000Z",
"uptime": 3600,
"checks": {
"database": { "status": "ok", "latency": 5 },
"redis": { "status": "ok", "latency": 2 }
},
"latency": 7
}
```
## 🔒 Sécurité
### Checklist de sécurité
- [ ] Tous les mots de passe par défaut ont été changés
- [ ] `NEXTAUTH_SECRET` est un secret fort et unique
- [ ] Les ports ne sont exposés que si nécessaire
- [ ] Un reverse proxy (Nginx/Traefik) est configuré avec SSL/TLS
- [ ] Les volumes sont sauvegardés régulièrement
- [ ] Les logs sont surveillés pour détecter les anomalies
### Reverse Proxy avec Nginx
Exemple de configuration Nginx :
```nginx
server {
listen 80;
server_name hub.slm-lab.net;
# Redirection HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name hub.slm-lab.net;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
```
## 🛠️ Dépannage
### L'application ne démarre pas
```bash
# Vérifier les logs
docker-compose -f docker-compose.prod.yml --env-file .env.production logs app
# Vérifier que les services dépendants sont démarrés
docker-compose -f docker-compose.prod.yml --env-file .env.production ps
# Vérifier la santé des services
docker-compose -f docker-compose.prod.yml --env-file .env.production exec app curl http://localhost:3000/api/health
```
### Problèmes de connexion à la base de données
```bash
# Tester la connexion PostgreSQL
docker-compose -f docker-compose.prod.yml --env-file .env.production exec db psql -U neah_user -d calendar_db -c "SELECT 1;"
# Vérifier les variables d'environnement
docker-compose -f docker-compose.prod.yml --env-file .env.production exec app env | grep DATABASE
```
### Problèmes de connexion Redis
```bash
# Tester Redis
docker-compose -f docker-compose.prod.yml --env-file .env.production exec redis redis-cli -a VOTRE_MOT_DE_PASSE ping
```
### Rebuild complet
Si vous avez des problèmes persistants :
```bash
# Arrêter tous les services
docker-compose -f docker-compose.prod.yml --env-file .env.production down
# Supprimer les volumes (⚠️ PERDREZ LES DONNÉES)
docker-compose -f docker-compose.prod.yml --env-file .env.production down -v
# Rebuild tout
docker-compose -f docker-compose.prod.yml --env-file .env.production build --no-cache
# Redémarrer
docker-compose -f docker-compose.prod.yml --env-file .env.production up -d
```
## 📦 Sauvegardes
### Script de sauvegarde automatique
Créez un script `backup.sh` :
```bash
#!/bin/bash
BACKUP_DIR="/backups/neah"
DATE=$(date +%Y%m%d_%H%M%S)
# Créer le dossier de backup
mkdir -p $BACKUP_DIR
# Sauvegarder PostgreSQL
docker exec neah-postgres-prod pg_dump -U neah_user calendar_db | gzip > $BACKUP_DIR/db_$DATE.sql.gz
# Sauvegarder Redis (optionnel)
docker exec neah-redis-prod redis-cli --rdb - | gzip > $BACKUP_DIR/redis_$DATE.rdb.gz
# Garder seulement les 7 derniers jours
find $BACKUP_DIR -name "*.gz" -mtime +7 -delete
echo "Backup completed: $DATE"
```
Ajoutez dans crontab pour exécution quotidienne :
```bash
0 2 * * * /path/to/backup.sh
```
## 🚀 Déploiement avec Traefik (Optionnel)
Pour un déploiement avec Traefik comme reverse proxy :
```yaml
# Ajoutez dans docker-compose.prod.yml
app:
labels:
- "traefik.enable=true"
- "traefik.http.routers.neah.rule=Host(`hub.slm-lab.net`)"
- "traefik.http.routers.neah.entrypoints=websecure"
- "traefik.http.routers.neah.tls.certresolver=letsencrypt"
- "traefik.http.services.neah.loadbalancer.server.port=3000"
```
## 📝 Notes importantes
1. **Migrations Prisma** : Toujours exécuter `prisma migrate deploy` avant de démarrer l'application en production
2. **Secrets** : Ne jamais commiter les fichiers `.env` dans Git
3. **Ports** : Limiter l'exposition des ports aux services nécessaires uniquement
4. **Monitoring** : Configurer des alertes pour les health checks
5. **Sauvegardes** : Automatiser les sauvegardes de la base de données
## 🔗 Ressources
- [Documentation Docker](https://docs.docker.com/)
- [Documentation Next.js](https://nextjs.org/docs)
- [Documentation Prisma](https://www.prisma.io/docs)

View File

@ -1,398 +0,0 @@
# 🎨 Fonctionnalité : Modification de la couleur des calendriers de groupes
## 📋 Vue d'ensemble
Cette fonctionnalité permet aux membres d'un groupe de personnaliser la couleur de la pastille du calendrier associé à leur groupe. Chaque groupe créé possède un calendrier automatique nommé `"Groupe: {nom}"`, et cette couleur est visible dans tous les affichages de calendrier (agenda, vision, etc.).
## ✨ Fonctionnalités implémentées
### 1. **API Backend** (`/app/api/groups/[groupId]/calendar/route.ts`)
#### Nouveaux endpoints :
**GET `/api/groups/[groupId]/calendar`**
- Récupère le calendrier associé à un groupe
- Retourne l'objet calendrier avec sa couleur actuelle
**PATCH `/api/groups/[groupId]/calendar`**
- Modifie uniquement la couleur du calendrier d'un groupe
- Body : `{ "color": "#FF5733" }`
- Validation du format hexadécimal
- Vérification que l'utilisateur est membre du groupe
- Retourne le calendrier mis à jour
#### Sécurité :
- ✅ Authentification requise
- ✅ Vérification de l'appartenance au groupe via Keycloak
- ✅ Validation du format de couleur (hex : `#RRGGBB` ou `#RGB`)
---
### 2. **Interface utilisateur - Page Groupes** (`/components/groups/groups-table.tsx`)
#### Modifications :
1. **Affichage de la pastille de couleur**
- Chaque groupe affiche maintenant une pastille colorée à côté de son nom
- Couleur par défaut : `#4f46e5` (indigo)
2. **Nouveau bouton "Couleur du calendrier"**
- Accessible via le menu actions (icône ⋯)
- Icône palette (🎨)
3. **Dialog de sélection de couleur**
- Palette de 16 couleurs prédéfinies
- Input manuel pour code hexadécimal
- Aperçu en temps réel de la couleur sélectionnée
- Validation avant sauvegarde
#### Palette de couleurs disponibles :
```typescript
const colorPalette = [
"#4f46e5", // Indigo
"#0891b2", // Cyan
"#0e7490", // Teal
"#16a34a", // Green
"#65a30d", // Lime
"#ca8a04", // Amber
"#d97706", // Orange
"#dc2626", // Red
"#e11d48", // Rose
"#9333ea", // Purple
"#7c3aed", // Violet
"#2563eb", // Blue
"#0284c7", // Sky
"#059669", // Emerald
"#84cc16", // Lime
"#eab308", // Yellow
];
```
---
### 3. **Interface utilisateur - Page Missions/Équipe** (`/app/missions/equipe/page.tsx`)
#### Modifications identiques à GroupsTable :
1. **Affichage de la couleur**
- Icône du groupe (👥) affichée sur fond de la couleur du calendrier
- Texte en blanc pour meilleure lisibilité
2. **Bouton direct dans la table**
- Icône palette (🎨) directement dans les actions
- Tooltip "Couleur du calendrier"
3. **Dialog de sélection**
- Même interface que dans GroupsTable
- Sauvegarde avec loader pendant l'opération
---
### 4. **Suppression automatique du calendrier** (`/app/api/groups/[groupId]/route.ts`) ✨ **NOUVEAU**
#### Modifications au DELETE endpoint :
Lorsqu'un groupe est supprimé, le calendrier associé est maintenant automatiquement supprimé :
1. **Récupération du nom du groupe**
- Appel à Keycloak avant suppression pour obtenir le nom du groupe
2. **Suppression du calendrier**
- Recherche du calendrier nommé `"Groupe: {nom}"`
- Suppression via `prisma.calendar.deleteMany()`
- Logs en cas de succès ou d'échec
3. **Suppression du groupe**
- Suppression du groupe de Keycloak
- Même si la suppression du calendrier échoue, le groupe est quand même supprimé
#### Impact :
- ✅ Plus de calendriers orphelins dans la base
- ✅ Nettoyage automatique de la base de données
- ✅ Agenda plus propre après suppression de groupes
---
### 5. **Enrichissement API groupes utilisateur** (`/app/api/users/[userId]/groups/route.ts`) ✨ **NOUVEAU**
#### Modifications au GET endpoint :
L'API qui récupère les groupes d'un utilisateur enrichit maintenant les données avec les couleurs des calendriers :
1. **Récupération des groupes**
- Appel à Keycloak pour obtenir les groupes de l'utilisateur
2. **Enrichissement avec couleurs**
- Pour chaque groupe, recherche du calendrier associé dans Prisma
- Ajout de la propriété `calendarColor` à chaque groupe
- Valeur `null` si pas de calendrier trouvé
3. **Retour enrichi**
- Les groupes retournés contiennent maintenant `calendarColor`
- Visible immédiatement dans la page Vision
#### Impact :
- ✅ La page Vision affiche les bonnes couleurs
- ✅ Pas besoin de requêtes supplémentaires côté client
- ✅ Une seule API call pour tout charger
---
## 🔄 Flux de données
### Chargement initial :
```
1. Page charge les groupes via GET /api/groups
2. Pour chaque groupe :
└─> GET /api/groups/{groupId}/calendar
└─> Récupère la couleur du calendrier
└─> Stocke dans state local : group.calendarColor
```
### Modification de couleur :
```
1. Utilisateur clique sur icône palette
2. Dialog s'ouvre avec couleur actuelle
3. Utilisateur sélectionne nouvelle couleur
4. Clic "Enregistrer"
└─> PATCH /api/groups/{groupId}/calendar { color: "#newcolor" }
└─> Vérification membre du groupe (Keycloak)
└─> Mise à jour en base de données (Prisma)
└─> Mise à jour du state local
└─> Toast de confirmation
5. Couleur visible immédiatement partout
```
---
## 🎯 Points d'affichage de la couleur
La couleur du calendrier de groupe est maintenant visible dans :
1. **`/groups`** - Page groupes
- Table des groupes (pastille à côté du nom)
2. **`/missions/equipe`** - Page gestion équipe
- Table des groupes (icône colorée)
3. **`/agenda`** - Page agenda
- Liste des calendriers (pastille à gauche)
- Événements dans le calendrier (barre colorée)
4. **`/vision`** - Page visioconférences ✨ **NOUVEAU**
- Cercle coloré autour de l'icône groupe
- Icône en blanc si couleur personnalisée, en bleu sinon
- Couleur par défaut : `#DBEAFE` (bleu clair)
5. **Widgets calendrier** - Tous les composants calendrier
- `calendar-widget.tsx`
- `calendar-client.tsx`
- `calendar.tsx`
---
## 🧪 Tests suggérés
### Test 1 : Modification de couleur
1. Aller sur `/groups` ou `/missions/equipe`
2. Cliquer sur ⋯ → "Couleur du calendrier"
3. Choisir une nouvelle couleur
4. Cliquer "Enregistrer"
5. ✅ Vérifier : Pastille mise à jour immédiatement
### Test 2 : Validation format
1. Ouvrir dialog couleur
2. Entrer manuellement un code invalide : `#GGGGGG`
3. Cliquer "Enregistrer"
4. ✅ Vérifier : Message d'erreur affiché
### Test 3 : Permissions
1. Se connecter avec utilisateur NON membre du groupe
2. Essayer de modifier la couleur
3. ✅ Vérifier : Erreur 403 "Vous devez être membre du groupe"
### Test 4 : Persistance
1. Modifier couleur d'un groupe
2. Actualiser la page
3. ✅ Vérifier : Couleur conservée
4. Aller sur `/agenda`
5. ✅ Vérifier : Couleur visible dans le calendrier
### Test 5 : Affichage dans Vision ✨ **NOUVEAU**
1. Modifier la couleur d'un groupe
2. Aller sur `/vision`
3. ✅ Vérifier : Le cercle autour de l'icône du groupe a la bonne couleur
4. ✅ Vérifier : L'icône est en blanc si couleur personnalisée
### Test 6 : Suppression du calendrier ✨ **NOUVEAU**
1. Créer un nouveau groupe
2. Vérifier dans `/agenda` que le calendrier est créé
3. Supprimer le groupe dans `/missions/equipe`
4. Aller sur `/agenda`
5. ✅ Vérifier : Le calendrier du groupe a été supprimé
6. ✅ Vérifier : Aucune erreur dans la console
---
## 📁 Fichiers modifiés
### Nouveaux fichiers :
- `app/api/groups/[groupId]/calendar/route.ts` (nouveau endpoint API)
### Fichiers modifiés :
#### 1. Gestion des couleurs :
- `components/groups/groups-table.tsx`
- Import `Palette` de lucide-react
- Ajout interface `calendarColor?` à Group
- Ajout états `colorPickerDialog`, `selectedGroupForColor`, `selectedColor`
- Fonction `fetchGroups()` modifiée pour charger couleurs
- Fonctions `handleOpenColorPicker()` et `handleSaveColor()`
- Palette de couleurs `colorPalette`
- Dialog de sélection de couleur
- Affichage pastille dans table
- `app/missions/equipe/page.tsx`
- Import `Palette` de lucide-react
- Ajout interface `calendarColor?` à Group
- Ajout états color picker
- Fonction `fetchData()` modifiée pour charger couleurs
- Fonctions `handleOpenColorPicker()` et `handleSaveColor()`
- Palette de couleurs
- Bouton palette dans actions
- Dialog de sélection de couleur
- Affichage icône colorée
#### 2. Affichage dans Vision : ✨ **NOUVEAU**
- `app/vision/page.tsx`
- Ajout `calendarColor?` à interface `Group`
- Modification affichage du cercle groupe pour utiliser `group.calendarColor`
- Style dynamique : couleur personnalisée ou défaut `#DBEAFE`
- Icône blanche si couleur personnalisée, bleue sinon
#### 3. Suppression automatique : ✨ **NOUVEAU**
- `app/api/groups/[groupId]/route.ts`
- Endpoint DELETE modifié
- Import `prisma` et `logger`
- Récupération des détails du groupe avant suppression
- Suppression du calendrier associé via `prisma.calendar.deleteMany()`
- Logs détaillés
#### 4. Enrichissement API : ✨ **NOUVEAU**
- `app/api/users/[userId]/groups/route.ts`
- Import `prisma`
- Endpoint GET enrichi
- Recherche du calendrier pour chaque groupe
- Ajout de `calendarColor` aux données retournées
- Gestion d'erreurs pour chaque groupe
---
## 🔮 Améliorations futures possibles
1. **Color picker avancé**
- Utiliser un vrai color picker (ex: `react-color`)
- Support HSL, RGB en plus de hex
2. **Thèmes prédéfinis**
- Palettes thématiques (pastel, vif, entreprise, etc.)
- Sauvegarde de palettes personnalisées
3. **Permissions granulaires**
- Seuls les admins du groupe peuvent changer la couleur
- Rôle "gestionnaire de groupe" dans Keycloak
4. **Historique des couleurs**
- Log des changements de couleur
- Possibilité de revenir en arrière
5. **Synchronisation**
- Webhook pour notifier les autres utilisateurs en temps réel
- WebSocket pour mise à jour instantanée sans refresh
---
## 📊 Impact sur les performances
- **Chargement initial** : +1 requête API par groupe (GET calendar)
- **Modification** : 1 requête PATCH, pas de refresh complet
- **Cache** : Les calendriers sont déjà en cache Redis (GET /api/calendars)
- **Optimisation** : Possibilité de batch les requêtes GET calendar en une seule
---
## 🐛 Problèmes résolus
### ✅ Problème 1 : Calendriers orphelins après suppression de groupe
**Symptôme** : Quand on supprimait un groupe, son calendrier restait dans la base de données et s'affichait dans l'agenda.
**Solution** : Modification du endpoint DELETE pour supprimer automatiquement le calendrier associé lors de la suppression du groupe.
**Commit** : Ajout de la suppression automatique dans `/app/api/groups/[groupId]/route.ts`
---
### ✅ Problème 2 : Couleurs non visibles dans la page Vision
**Symptôme** : Les couleurs de calendrier personnalisées n'apparaissaient pas dans `/vision`, tous les groupes avaient la même couleur bleue.
**Solution** :
1. Enrichissement de l'API `/api/users/[userId]/groups` pour inclure `calendarColor`
2. Modification de l'interface `Group` dans `vision/page.tsx`
3. Affichage dynamique des couleurs dans l'UI
**Commit** : Enrichissement API et affichage dans Vision
---
## 🐛 Problèmes connus
Aucun problème connu pour le moment.
---
## ✅ Checklist de déploiement
- [x] API créée et testée
- [x] Interface utilisateur implémentée
- [x] Validation des permissions
- [x] Gestion des erreurs
- [x] Pas d'erreurs de linting
- [ ] Tests unitaires (à ajouter)
- [ ] Tests E2E (à ajouter)
- [ ] Documentation utilisateur (à ajouter)
---
## 📞 Support
Pour toute question ou problème :
1. Vérifier que l'utilisateur est bien membre du groupe
2. Vérifier le format de la couleur (hex valide)
3. Vérifier les logs serveur pour les erreurs Keycloak
4. Vérifier que le calendrier du groupe existe en base
---
**Date de création** : 20 janvier 2026
**Dernière mise à jour** : 21 janvier 2026
**Version** : 1.2
**Auteur** : Senior Developer Assistant
### 📝 Changelog
#### v1.2 (21 janvier 2026)
- ✨ Ajout : Suppression automatique du calendrier lors de la suppression d'un groupe
- ✨ Ajout : Affichage des couleurs dans la page Vision (`/vision`)
- 🔧 Modification : Enrichissement de l'API `/api/users/[userId]/groups` avec les couleurs
- 📚 Documentation : Ajout de nouveaux tests et problèmes résolus
#### v1.1 (20 janvier 2026)
- 🐛 Fix : Problèmes de déploiement Docker
- 📚 Documentation : Ajout du guide de déploiement
#### v1.0 (20 janvier 2026)
- ✨ Version initiale avec modification des couleurs de calendrier

View File

@ -1,192 +0,0 @@
# Flow complet des tâches Leantime dans le widget Devoirs
## 1. BACKEND - API Route `/api/leantime/tasks` (app/api/leantime/tasks/route.ts)
### Étape 1.1 : Vérification de session
- **Ligne 91-95** : Vérifie la session utilisateur
- Si pas de session → retourne 401 Unauthorized
### Étape 1.2 : Vérification du cache Redis
- **Ligne 103-141** : Si `forceRefresh=false`, vérifie le cache Redis
- **Ligne 107-123** : **FILTRE 1** - Filtre les tâches "done" du cache :
- Statuts filtrés : `0`, `3`, `5` (ou strings `'0'`, `'3'`, `'5'`, `'Done'`, `'done'`, `'DONE'`)
- Si des tâches "done" sont trouvées dans le cache, elles sont supprimées
- Le cache est mis à jour avec les tâches filtrées
- Si cache valide → retourne les tâches filtrées du cache (ligne 139)
### Étape 1.3 : Récupération de l'ID utilisateur Leantime
- **Ligne 146** : `getLeantimeUserId(session.user.email)`
- Appelle l'API Leantime `leantime.rpc.users.getAll`
- Trouve l'utilisateur par `username === email`
- Retourne `user.id` ou `null`
### Étape 1.4 : Appel API Leantime
- **Ligne 165-178** : Appelle `leantime.rpc.tickets.getAll` avec :
- `userId: userId`
- `status: "all"` (récupère TOUTES les tâches, tous statuts confondus)
- **Ligne 193-195** : Log toutes les tâches brutes reçues de Leantime
### Étape 1.5 : Filtrage des tâches
- **Ligne 217-249** : **FILTRE 2** - Filtre les tâches :
**a) Filtre par statut "done" (ligne 223-240)** :
- Statuts filtrés : `0`, `3`, `5` (ou strings `'0'`, `'3'`, `'5'`, `'done'`)
- Si `isDone === true` → la tâche est exclue (`return false`)
**b) Filtre par éditeur (ligne 242-248)** :
- Seules les tâches où `task.editorId === userId` sont gardées
- Si `taskEditorId !== currentUserId` → la tâche est exclue
### Étape 1.6 : Transformation des données
- **Ligne 250-266** : Transforme les tâches Leantime en format standard :
```typescript
{
id: task.id.toString(),
headline: task.headline,
projectName: task.projectName,
projectId: task.projectId,
status: task.status, // ⚠️ LE STATUT EST INCLUS ICI
dateToFinish: task.dateToFinish || null,
milestone: task.type || null,
details: task.description || null,
createdOn: task.dateCreated,
editedOn: task.editedOn || null,
editorId: task.editorId,
editorFirstname: task.editorFirstname,
editorLastname: task.editorLastname,
type: task.type || null,
dependingTicketId: task.dependingTicketId || null
}
```
### Étape 1.7 : Mise en cache
- **Ligne 292** : Met en cache les tâches filtrées dans Redis
- **Ligne 294** : Retourne les tâches filtrées en JSON
---
## 2. FRONTEND - Widget Devoirs (components/flow.tsx)
### Étape 2.1 : Appel API
- **Ligne 107-113** : Appelle `/api/leantime/tasks` (ou `/api/leantime/tasks?refresh=true`)
- **Ligne 117-127** : Récupère les données JSON et les assigne à `leantimeTasks`
- **Ligne 121-126** : Log toutes les tâches reçues avec leur statut
### Étape 2.2 : Détection des tâches "done" (pour log uniquement)
- **Ligne 129-143** : Détecte les tâches avec statut `5` ou `'done'` (⚠️ NE FILTRE PAS LE STATUT 0)
- Affiche un warning si des tâches "done" sont trouvées
### Étape 2.3 : Analyse des statuts (pour log uniquement)
- **Ligne 164-178** : Crée `leantimeStatusDetails` avec calcul de `isDone`
- **Ligne 168** : `isDone = statusNum === 0 || statusNum === 3 || statusNum === 5 || ...`
- **Ligne 193** : Filtre les tâches "done" pour le log `doneTasksCount`
- **Ligne 201-206** : Log le breakdown des statuts
### Étape 2.4 : Combinaison avec Twenty CRM
- **Ligne 161** : Combine `leantimeTasks` et `twentyCrmTasks` dans `allTasks`
### Étape 2.5 : Filtrage frontend
- **Ligne 242-281** : **FILTRE 3** - Filtre les tâches :
**a) Filtre par statut "done" (ligne 245-260)** :
- Statuts filtrés : `0`, `3`, `5` (ou strings `'0'`, `'3'`, `'5'`, `'done'`)
- Si le statut correspond → la tâche est exclue (`return false`)
**b) Filtre par date (ligne 262-280)** :
- Exclut les tâches sans `dateToFinish`
- Garde uniquement les tâches avec `dateToFinish <= today` (overdue ou due today)
### Étape 2.6 : Tri
- **Ligne 296-317** : Trie les tâches :
1. Par `dateToFinish` (oldest first)
2. Si dates égales, par statut (statut `4` en premier)
### Étape 2.7 : Notification badge
- **Ligne 362-366** : Met à jour le badge de notification avec le nombre de tâches
### Étape 2.8 : Affichage
- **Ligne 368** : `setTasks(sortedTasks)` - Met à jour l'état React
### Étape 2.9 : Filtrage avant notification Outlook
- **Ligne 372-390** : **FILTRE 4** - Filtre les tâches avant d'envoyer l'événement `tasks-updated` :
- **Ligne 380** : ⚠️ **PROBLÈME ICI** - Ne filtre que `3` et `5`, PAS le statut `0` !
- Si `isDone === true` → la tâche est exclue
- **Ligne 391-398** : Transforme les tâches pour l'événement (sans inclure le `status`)
---
## 3. PROBLÈMES IDENTIFIÉS
### Problème 1 : Filtre ligne 380 dans flow.tsx
- **Ligne 380** : `isDone = taskStatus === 3 || taskStatus === 5 || ...`
- **Manque** : `taskStatus === 0`
- **Impact** : Les tâches avec statut `0` passent le filtre et sont envoyées dans l'événement `tasks-updated`
### Problème 2 : Détection ligne 129-135 dans flow.tsx
- **Ligne 134** : Ne détecte que le statut `5`, pas `0` ni `3`
- **Impact** : Le log `⚠️ Received done tasks` ne détecte pas toutes les tâches "done"
### Problème 3 : Le statut n'est pas inclus dans l'événement tasks-updated
- **Ligne 391-398** : L'objet envoyé dans l'événement ne contient pas le champ `status`
- **Impact** : Les hooks qui écoutent `tasks-updated` ne peuvent pas filtrer par statut
---
## 4. FLOW RÉSUMÉ
```
1. API Leantime (toutes les tâches, tous statuts)
2. FILTRE 1 (cache) : Exclut statuts 0, 3, 5
3. FILTRE 2 (API backend) : Exclut statuts 0, 3, 5 + filtre par editorId
4. Transformation + Cache Redis
5. Frontend reçoit les tâches (avec statut inclus)
6. FILTRE 3 (frontend) : Exclut statuts 0, 3, 5 + filtre par date
7. Tri par date
8. FILTRE 4 (avant notification) : ⚠️ Exclut seulement statuts 3, 5 (MANQUE 0)
9. Événement tasks-updated (sans statut dans l'objet)
10. Affichage dans le widget
```
---
## 5. CORRECTIONS NÉCESSAIRES
1. **Ligne 380 dans flow.tsx** : Ajouter `taskStatus === 0` au filtre ✅ CORRIGÉ
2. **Ligne 134 dans flow.tsx** : Ajouter détection des statuts `0` et `3` ✅ CORRIGÉ
3. **Ligne 391-398 dans flow.tsx** : Inclure le champ `status` dans l'objet envoyé dans l'événement
---
## 6. SIGNIFICATION DES STATUTS LEANTIME
D'après le code :
### Mapping standard (app/api/leantime/status-labels/route.ts) :
- **Status 1** = 'NEW'
- **Status 2** = 'INPROGRESS'
- **Status 3** = 'DONE' ⚠️
- **Status 0** = Non défini (tombe dans `default: 'UNKNOWN'`)
### Mapping dans le widget (components/flow.tsx) :
- **Status 1** = 'New'
- **Status 2** = 'Blocked'
- **Status 3** = 'In Progress' ⚠️ **INCOHÉRENCE avec status-labels**
- **Status 4** = 'Waiting for Approval'
- **Status 5** = 'Done'
- **Status 0** = 'Unknown' (par défaut)
### Statuts filtrés comme "done" :
- **Status 0** = "Done" (dans votre instance Leantime, configuration personnalisée)
- **Status 3** = "Done" (selon `status-labels/route.ts`)
- **Status 5** = "Done" (selon `flow.tsx`)
**Note** : Il y a une incohérence entre les deux mappings. Le statut 3 est mappé à "DONE" dans `status-labels` mais à "In Progress" dans `flow.tsx`. Le statut 0 n'est pas standard dans Leantime mais semble être utilisé comme "done" dans votre instance.

View File

@ -1,65 +0,0 @@
# 🚀 Démarrage Rapide - Production Docker
## Installation en 5 minutes
### 1. Préparer l'environnement
```bash
# Copier le fichier d'exemple
cp env.production.example .env.production
# Éditer avec vos valeurs
nano .env.production
```
**⚠️ IMPORTANT** : Changez au minimum :
- `POSTGRES_PASSWORD`
- `REDIS_PASSWORD`
- `NEXTAUTH_SECRET` (générez avec `openssl rand -base64 32`)
### 2. Déployer
```bash
# Option A: Utiliser le script automatique
./scripts/deploy-prod.sh
# Option B: Commandes manuelles
docker-compose -f docker-compose.prod.yml --env-file .env.production build
docker-compose -f docker-compose.prod.yml --env-file .env.production up -d db redis
sleep 15
docker-compose -f docker-compose.prod.yml --env-file .env.production run --rm app npx --yes prisma@6.4.1 migrate deploy
docker-compose -f docker-compose.prod.yml --env-file .env.production up -d app
```
### 3. Vérifier
```bash
# Vérifier que tout fonctionne
curl http://localhost:3000/api/health
# Voir les logs
docker-compose -f docker-compose.prod.yml logs -f app
```
## Commandes utiles
```bash
# Arrêter
docker-compose -f docker-compose.prod.yml --env-file .env.production down
# Redémarrer
docker-compose -f docker-compose.prod.yml --env-file .env.production restart app
# Voir les logs
docker-compose -f docker-compose.prod.yml --env-file .env.production logs -f
# Appliquer les migrations
docker-compose -f docker-compose.prod.yml --env-file .env.production run --rm app npx --yes prisma@6.4.1 migrate deploy
# Accéder à la base de données
docker-compose -f docker-compose.prod.yml --env-file .env.production exec db psql -U neah_user -d calendar_db
```
## 📖 Documentation complète
Voir `DEPLOYMENT.md` pour la documentation complète.