504 lines
14 KiB
Markdown
504 lines
14 KiB
Markdown
# Analyse approfondie du système Missions - Code Review Senior
|
|
|
|
## 📋 Vue d'ensemble
|
|
|
|
Ce document présente une analyse complète du système de gestion des missions, incluant la page de liste, les détails de mission, et l'architecture backend associée.
|
|
|
|
---
|
|
|
|
## 🏗️ Architecture générale
|
|
|
|
### Structure des fichiers
|
|
|
|
```
|
|
app/
|
|
├── missions/
|
|
│ ├── page.tsx # Page principale de liste des missions
|
|
│ ├── layout.tsx # Layout avec sidebar CAP
|
|
│ ├── new/
|
|
│ │ └── page.tsx # Création de nouvelle mission
|
|
│ └── [missionId]/
|
|
│ ├── page.tsx # Page de détails de mission
|
|
│ └── edit/
|
|
│ └── page.tsx # Édition de mission
|
|
│
|
|
├── api/
|
|
│ └── missions/
|
|
│ ├── route.ts # GET/POST missions
|
|
│ ├── [missionId]/
|
|
│ │ ├── route.ts # GET/PUT/DELETE mission spécifique
|
|
│ │ ├── close/route.ts # Clôture de mission
|
|
│ │ └── generate-plan/ # Génération plan d'action IA
|
|
│ └── ...
|
|
│
|
|
components/
|
|
└── missions/
|
|
├── missions-frame.tsx # Iframe wrapper
|
|
├── missions-admin-panel.tsx # Panel de création/édition
|
|
└── ...
|
|
```
|
|
|
|
---
|
|
|
|
## 📄 Page de liste des missions (`app/missions/page.tsx`)
|
|
|
|
### Points forts ✅
|
|
|
|
1. **Interface utilisateur claire**
|
|
- Design en grille responsive (1/2/3 colonnes)
|
|
- Cartes de mission bien structurées
|
|
- Indicateurs visuels pour missions clôturées
|
|
- Recherche en temps réel
|
|
|
|
2. **Gestion d'état**
|
|
- Utilisation appropriée de `useState` et `useEffect`
|
|
- Gestion des états de chargement
|
|
- Filtrage côté client efficace
|
|
|
|
3. **Affichage des données**
|
|
- Logos avec fallback gracieux
|
|
- Badges ODD avec icônes
|
|
- Affichage conditionnel des services
|
|
- Formatage des dates en français
|
|
|
|
### Points d'amélioration 🔧
|
|
|
|
1. **Performance**
|
|
```typescript
|
|
// ❌ Problème: Filtrage côté client uniquement
|
|
const filteredMissions = missions.filter(mission =>
|
|
mission.name.toLowerCase().includes(searchTerm.toLowerCase()) || ...
|
|
);
|
|
|
|
// ✅ Suggestion: Pagination et recherche côté serveur
|
|
// Utiliser les query params dans l'API
|
|
```
|
|
|
|
2. **Gestion d'erreurs**
|
|
```typescript
|
|
// ⚠️ Actuel: Toast générique
|
|
toast({
|
|
title: "Erreur",
|
|
description: "Impossible de charger les missions",
|
|
variant: "destructive",
|
|
});
|
|
|
|
// ✅ Suggestion: Messages d'erreur plus spécifiques
|
|
// + Retry automatique pour erreurs réseau
|
|
```
|
|
|
|
3. **Console.log en production**
|
|
```typescript
|
|
// ❌ Lignes 59, 199-203: console.log en production
|
|
console.log("Mission data with intention:", data.missions);
|
|
|
|
// ✅ Suggestion: Utiliser un logger conditionnel
|
|
if (process.env.NODE_ENV === 'development') {
|
|
console.log(...);
|
|
}
|
|
```
|
|
|
|
4. **Accessibilité**
|
|
- Manque d'attributs ARIA sur les cartes
|
|
- Navigation clavier non optimisée
|
|
- Pas de skip links
|
|
|
|
---
|
|
|
|
## 📄 Page de détails de mission (`app/missions/[missionId]/page.tsx`)
|
|
|
|
### Points forts ✅
|
|
|
|
1. **Architecture en onglets**
|
|
- Organisation claire: Général, Plan d'actions, Équipe, Ressources
|
|
- Compteurs visuels sur les onglets (équipe, documents)
|
|
- Navigation intuitive
|
|
|
|
2. **Fonctionnalités avancées**
|
|
- Génération de plan d'action par IA (N8N)
|
|
- Édition inline du plan avec sauvegarde
|
|
- Gestion des gardiens de l'intention
|
|
- Clôture de mission avec intégration N8N
|
|
|
|
3. **Gestion d'état complexe**
|
|
- Suivi des modifications non sauvegardées
|
|
- États de chargement multiples (generating, saving, deleting, closing)
|
|
- Synchronisation avec le backend
|
|
|
|
### Points d'amélioration critiques 🔴
|
|
|
|
1. **Sécurité - Validation côté client uniquement**
|
|
```typescript
|
|
// ⚠️ Ligne 192: Confirmation simple avec confirm()
|
|
if (!confirm("Êtes-vous sûr de vouloir supprimer cette mission ?")) {
|
|
return;
|
|
}
|
|
|
|
// ✅ Suggestion: Modal de confirmation avec détails
|
|
// + Vérification des permissions côté serveur (déjà fait ✅)
|
|
```
|
|
|
|
2. **Gestion des erreurs réseau**
|
|
```typescript
|
|
// ⚠️ Pas de retry automatique
|
|
// Pas de gestion des timeouts
|
|
// Pas de fallback si l'API est down
|
|
|
|
// ✅ Suggestion: Implémenter retry avec exponential backoff
|
|
// + Cache local pour données critiques
|
|
```
|
|
|
|
3. **Performance - Re-renders inutiles**
|
|
```typescript
|
|
// ⚠️ Ligne 112-116: useEffect qui se déclenche à chaque changement
|
|
useEffect(() => {
|
|
if (mission) {
|
|
setIsPlanModified(editedPlan !== (mission.actionPlan || ""));
|
|
}
|
|
}, [editedPlan, mission]);
|
|
|
|
// ✅ Suggestion: Utiliser useMemo pour éviter recalculs
|
|
const isPlanModified = useMemo(() => {
|
|
return mission ? editedPlan !== (mission.actionPlan || "") : false;
|
|
}, [editedPlan, mission?.actionPlan]);
|
|
```
|
|
|
|
4. **Textarea auto-resize - Code fragile**
|
|
```typescript
|
|
// ⚠️ Lignes 676-688: Manipulation directe du DOM
|
|
e.target.style.height = 'auto';
|
|
e.target.style.height = e.target.scrollHeight + 'px';
|
|
|
|
// ✅ Suggestion: Utiliser une librairie dédiée (react-textarea-autosize)
|
|
// ou un hook personnalisé réutilisable
|
|
```
|
|
|
|
5. **Duplication de code**
|
|
```typescript
|
|
// ⚠️ Fonctions helper dupliquées entre page.tsx et [missionId]/page.tsx
|
|
// getMissionTypeLabel, getDurationLabel, getNiveauLabel, etc.
|
|
|
|
// ✅ Suggestion: Extraire dans lib/mission-helpers.ts
|
|
```
|
|
|
|
---
|
|
|
|
## 🔌 API Routes - Analyse Backend
|
|
|
|
### `app/api/missions/route.ts` (GET/POST)
|
|
|
|
#### Points forts ✅
|
|
|
|
1. **Sécurité**
|
|
- Vérification d'authentification systématique
|
|
- Validation des champs requis
|
|
- Gestion des permissions
|
|
|
|
2. **Gestion des fichiers**
|
|
- Upload vers Minio/S3 bien structuré
|
|
- Vérification d'existence des fichiers avant N8N
|
|
- Cleanup en cas d'erreur (lignes 460-474)
|
|
|
|
3. **Intégration N8N**
|
|
- Workflow asynchrone pour création
|
|
- Gestion des erreurs non-bloquantes
|
|
- Logging détaillé
|
|
|
|
#### Points d'amélioration 🔧
|
|
|
|
1. **Transaction database**
|
|
```typescript
|
|
// ⚠️ Pas de transaction Prisma
|
|
const mission = await prisma.mission.create({...});
|
|
await prisma.missionUser.createMany({...});
|
|
|
|
// ✅ Suggestion: Utiliser $transaction pour atomicité
|
|
await prisma.$transaction(async (tx) => {
|
|
const mission = await tx.mission.create({...});
|
|
await tx.missionUser.createMany({...});
|
|
return mission;
|
|
});
|
|
```
|
|
|
|
2. **Validation des données**
|
|
```typescript
|
|
// ⚠️ Validation basique (lignes 230-235)
|
|
if (!body.name || !body.oddScope) {
|
|
return NextResponse.json({ error: 'Missing required fields' }, { status: 400 });
|
|
}
|
|
|
|
// ✅ Suggestion: Utiliser Zod ou Yup pour validation stricte
|
|
const MissionSchema = z.object({
|
|
name: z.string().min(3).max(100),
|
|
oddScope: z.array(z.string().regex(/^odd-\d+$/)),
|
|
// ...
|
|
});
|
|
```
|
|
|
|
3. **Gestion des erreurs N8N**
|
|
```typescript
|
|
// ⚠️ Ligne 439: Erreur N8N bloque la création
|
|
if (!workflowResult.success) {
|
|
throw new Error(workflowResult.error || 'N8N workflow failed');
|
|
}
|
|
|
|
// ✅ Suggestion: Mode "best effort" - créer la mission même si N8N échoue
|
|
// + Queue de retry pour N8N (BullMQ, etc.)
|
|
```
|
|
|
|
### `app/api/missions/[missionId]/route.ts` (GET/PUT/DELETE)
|
|
|
|
#### Points forts ✅
|
|
|
|
1. **DELETE bien implémenté**
|
|
- Cleanup Minio avant suppression DB
|
|
- Intégration N8N pour rollback
|
|
- Gestion des erreurs non-bloquantes
|
|
|
|
2. **Permissions granulaires**
|
|
- Vérification créateur/admin pour DELETE
|
|
- Gardiens peuvent modifier (PUT)
|
|
|
|
#### Points d'amélioration 🔧
|
|
|
|
1. **GET - Performance**
|
|
```typescript
|
|
// ⚠️ Ligne 38: findFirst au lieu de findUnique
|
|
const mission = await (prisma as any).mission.findFirst({
|
|
where: {
|
|
id: missionId,
|
|
OR: [
|
|
{ creatorId: userId },
|
|
{ missionUsers: { some: { userId } } }
|
|
]
|
|
},
|
|
// ...
|
|
});
|
|
|
|
// ✅ Suggestion: findUnique + vérification permissions séparée
|
|
// Plus performant avec index sur id
|
|
```
|
|
|
|
2. **PUT - Validation partielle**
|
|
```typescript
|
|
// ⚠️ Pas de validation des données mises à jour
|
|
// Pas de vérification de cohérence (ex: oddScope doit être array)
|
|
|
|
// ✅ Suggestion: Validation stricte avec schéma
|
|
```
|
|
|
|
---
|
|
|
|
## 🎨 Composants UI
|
|
|
|
### `components/missions/missions-admin-panel.tsx`
|
|
|
|
#### Points forts ✅
|
|
|
|
1. **Interface complète**
|
|
- Formulaire multi-onglets bien organisé
|
|
- Gestion des gardiens et volontaires
|
|
- Upload de fichiers intégré
|
|
|
|
2. **UX soignée**
|
|
- Validation en temps réel
|
|
- Indicateurs visuels de progression
|
|
- Messages d'erreur contextuels
|
|
|
|
#### Points d'amélioration critiques 🔴
|
|
|
|
1. **Fichier trop volumineux (1570 lignes)**
|
|
```typescript
|
|
// ❌ Un seul composant fait tout
|
|
// Difficile à maintenir, tester, et réutiliser
|
|
|
|
// ✅ Suggestion: Découper en sous-composants
|
|
// - MissionGeneralForm
|
|
// - MissionDetailsForm
|
|
// - MissionAttachmentsForm
|
|
// - MissionMembersForm
|
|
// - MissionSkillsForm
|
|
```
|
|
|
|
2. **Gestion d'état complexe**
|
|
```typescript
|
|
// ⚠️ Trop de useState (15+)
|
|
const [selectedServices, setSelectedServices] = useState<string[]>([]);
|
|
const [selectedProfils, setSelectedProfils] = useState<string[]>([]);
|
|
// ... 13 autres
|
|
|
|
// ✅ Suggestion: Utiliser useReducer ou Zustand
|
|
const [state, dispatch] = useReducer(missionReducer, initialState);
|
|
```
|
|
|
|
3. **Logique métier dans le composant**
|
|
```typescript
|
|
// ⚠️ Lignes 400-408: Conversion base64 dans le composant
|
|
const convertFileToBase64 = (file: File): Promise<string> => {
|
|
// ...
|
|
};
|
|
|
|
// ✅ Suggestion: Extraire dans lib/file-utils.ts
|
|
```
|
|
|
|
4. **Console.log en production**
|
|
```typescript
|
|
// ❌ Lignes 412, 422, 428, 451, 465, 492, 504, 514, 541, 559
|
|
// Trop de logs de debug
|
|
|
|
// ✅ Suggestion: Logger conditionnel ou supprimer
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 Flux de données
|
|
|
|
### Création de mission
|
|
|
|
```
|
|
1. User remplit formulaire (missions-admin-panel.tsx)
|
|
↓
|
|
2. POST /api/missions
|
|
↓
|
|
3. Création DB (Prisma)
|
|
↓
|
|
4. Upload fichiers (Minio)
|
|
↓
|
|
5. Vérification fichiers
|
|
↓
|
|
6. Trigger N8N workflow
|
|
↓
|
|
7. N8N crée intégrations (Gitea, Leantime, etc.)
|
|
↓
|
|
8. Callback /api/missions/mission-created
|
|
↓
|
|
9. Mise à jour mission avec IDs externes
|
|
```
|
|
|
|
**Problème potentiel**: Si N8N échoue après création DB, la mission existe sans intégrations.
|
|
|
|
**Solution**: Queue de retry ou mode "best effort" avec notification.
|
|
|
|
### Affichage de mission
|
|
|
|
```
|
|
1. GET /api/missions/[missionId]
|
|
↓
|
|
2. Prisma query avec includes
|
|
↓
|
|
3. Génération URLs publiques (logo, attachments)
|
|
↓
|
|
4. Affichage dans page.tsx
|
|
```
|
|
|
|
**Optimisation possible**: Cache Redis pour missions fréquemment consultées.
|
|
|
|
---
|
|
|
|
## 🐛 Bugs potentiels identifiés
|
|
|
|
1. **Race condition sur plan d'action**
|
|
```typescript
|
|
// Si l'utilisateur modifie pendant la génération
|
|
// Les modifications peuvent être écrasées
|
|
```
|
|
|
|
2. **Memory leak potentiel**
|
|
```typescript
|
|
// Textarea auto-resize avec ref callback
|
|
// Pas de cleanup dans useEffect
|
|
```
|
|
|
|
3. **Type safety**
|
|
```typescript
|
|
// Utilisation de (prisma as any) dans plusieurs endroits
|
|
// Indique que le schema Prisma n'est pas à jour
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Métriques de code
|
|
|
|
### Complexité cyclomatique
|
|
|
|
- `missions-admin-panel.tsx`: **Très élevée** (>50)
|
|
- `[missionId]/page.tsx`: **Élevée** (~30)
|
|
- `page.tsx`: **Moyenne** (~15)
|
|
|
|
### Taille des fichiers
|
|
|
|
- `missions-admin-panel.tsx`: **1570 lignes** ⚠️
|
|
- `[missionId]/page.tsx`: **920 lignes** ⚠️
|
|
- `route.ts` (POST): **480 lignes** ⚠️
|
|
|
|
**Recommandation**: Découper les fichiers >500 lignes.
|
|
|
|
---
|
|
|
|
## ✅ Recommandations prioritaires
|
|
|
|
### 🔴 Critique (À faire immédiatement)
|
|
|
|
1. **Sécurité**
|
|
- Ajouter validation stricte avec Zod
|
|
- Implémenter rate limiting sur API
|
|
- Ajouter CSRF protection
|
|
|
|
2. **Performance**
|
|
- Implémenter pagination côté serveur
|
|
- Ajouter cache Redis
|
|
- Optimiser les requêtes Prisma (select spécifiques)
|
|
|
|
3. **Maintenabilité**
|
|
- Découper `missions-admin-panel.tsx`
|
|
- Extraire helpers dans lib/
|
|
- Supprimer console.log de production
|
|
|
|
### 🟡 Important (À planifier)
|
|
|
|
1. **Tests**
|
|
- Unit tests pour helpers
|
|
- Integration tests pour API routes
|
|
- E2E tests pour flux critiques
|
|
|
|
2. **Documentation**
|
|
- JSDoc pour fonctions complexes
|
|
- Diagrammes de séquence pour flux N8N
|
|
- Guide de contribution
|
|
|
|
3. **Monitoring**
|
|
- Sentry pour erreurs frontend
|
|
- Logging structuré backend
|
|
- Métriques de performance
|
|
|
|
### 🟢 Amélioration (Nice to have)
|
|
|
|
1. **UX**
|
|
- Optimistic updates
|
|
- Skeleton loaders
|
|
- Animations de transition
|
|
|
|
2. **Accessibilité**
|
|
- ARIA labels complets
|
|
- Navigation clavier
|
|
- Support lecteurs d'écran
|
|
|
|
---
|
|
|
|
## 🎯 Conclusion
|
|
|
|
Le système de missions est **fonctionnel et bien structuré** avec une architecture claire. Les principales améliorations à apporter concernent:
|
|
|
|
1. **Maintenabilité**: Découpage des gros composants
|
|
2. **Performance**: Optimisation des requêtes et pagination
|
|
3. **Robustesse**: Meilleure gestion d'erreurs et retry logic
|
|
4. **Sécurité**: Validation stricte et rate limiting
|
|
|
|
Le code montre une bonne compréhension de Next.js, Prisma, et des patterns React modernes. Avec les améliorations suggérées, le système sera prêt pour la production à grande échelle.
|
|
|
|
---
|
|
|
|
**Date de review**: $(date)
|
|
**Reviewer**: Senior Developer
|
|
**Version analysée**: Current codebase
|