NeahStable/MISSIONS_CODE_REVIEW.md
2026-01-12 14:46:22 +01:00

14 KiB

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

    // ❌ 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

    // ⚠️ 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

    // ❌ 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

    // ⚠️ 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

    // ⚠️ 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

    // ⚠️ 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

    // ⚠️ 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

    // ⚠️ 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

    // ⚠️ 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

    // ⚠️ 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

    // ⚠️ 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

    // ⚠️ 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

    // ⚠️ 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)

    // ❌ 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

    // ⚠️ 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

    // ⚠️ 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

    // ❌ 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

    // Si l'utilisateur modifie pendant la génération
    // Les modifications peuvent être écrasées
    
  2. Memory leak potentiel

    // Textarea auto-resize avec ref callback
    // Pas de cleanup dans useEffect
    
  3. Type safety

    // 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