veza/apps/web/AUDIT_FRONTEND_GAP_ANALYSIS.md

13 KiB

Rapport d'État des Lieux du Frontend — Gap Analysis

Date : 2025-01-27
Version Backend : 1.2.0 (selon FRONTEND_INTEGRATION.md)
Objectif : Identifier les écarts entre le Frontend actuel et les exigences du Backend


1. État des Lieux

Stack Technique

Framework & Build :

  • Vite 7.1.5 (build tool moderne)
  • React 18.2.0 (framework UI)
  • TypeScript 5.3.3 (type safety)
  • Tailwind CSS 4.0.0 (styling)

State Management :

  • Zustand 4.5.0 (state management léger)
  • React Query (TanStack Query) 5.17.0 (server state)

HTTP Client :

  • Axios 1.6.7 (client HTTP)
  • ⚠️ Problème : Deux instances Axios différentes (voir section 2.1)

Validation & Forms :

  • Zod 3.25.76 (schema validation)
  • React Hook Form 7.49.3 (form management)

Routing :

  • React Router DOM 6.22.0 (routing)

Testing :

  • Vitest 3.2.4 (unit tests)
  • Playwright 1.41.2 (e2e tests)
  • MSW 2.11.2 (API mocking)

Architecture :

  • Feature-based structure (src/features/)
  • Path aliases configurés (@/, @components/, @features/, etc.)
  • TypeScript strict mode activé

Score de Maturité : 75%

Points Positifs :

  • Stack moderne et bien configurée
  • Structure de dossiers scalable (feature-based)
  • Outillage complet (ESLint, Prettier, TypeScript strict)
  • Tests configurés (unit + e2e)
  • PWA support (service worker, manifest)

Points d'Amélioration :

  • ⚠️ Duplication de code (clients API, stores auth)
  • ⚠️ Incohérences dans les types TypeScript
  • ⚠️ Variables d'environnement non alignées avec la doc
  • ⚠️ Format de réponse API non standardisé

2. Analyse de la "Plomberie" (Core Layer)

🔴 Client API : CRITIQUE — Incohérences Majeures

Problème 1 : Deux Clients API Différents

Client 1 : src/lib/apiClient.ts

baseURL: '/api/v1'  // URL relative
  • Utilise une URL relative (ne fonctionne pas avec VITE_API_URL)
  • Intercepteur de refresh token basique
  • ⚠️ Utilisé par src/features/auth/store/authStore.ts

Client 2 : src/services/api/client.ts

baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8080/api/v1'
  • Utilise une variable d'environnement
  • Intercepteur de refresh token avec queue
  • Utilisé par src/services/api/auth.ts

Impact : Code dupliqué, maintenance difficile, comportements différents.

Problème 2 : Variables d'Environnement Incohérentes

Documentation Backend (FRONTEND_INTEGRATION.md) :

VITE_API_URL=http://localhost:8080/api/v1
VITE_WS_URL=ws://localhost:8081/ws
VITE_STREAM_URL=ws://localhost:8082/stream

Code Frontend (src/config/env.ts) :

VITE_API_BASE_URL  // ❌ Devrait être VITE_API_URL
VITE_WS_BASE_URL    // ❌ Devrait être VITE_WS_URL
VITE_STREAM_URL     // ✅ Correct

Impact : Les développeurs doivent utiliser des noms de variables différents de la doc, confusion.

Problème 3 : Format de Réponse API Non Standardisé

Backend retourne (selon FRONTEND_INTEGRATION.md) :

{
  "success": true,
  "data": { ... },
  "error": null
}

Code Frontend :

  • src/services/api.ts (ligne 173) : Parse response.data.data
  • src/services/api/auth.ts (ligne 60) : Parse response.data directement
  • src/services/api/client.ts : Ne parse pas le wrapper

Impact : Erreurs silencieuses, données non parsées correctement.


🔴 Auth Management : CRITIQUE — Duplication

Problème : Deux Stores d'Authentification

Store 1 : src/stores/auth.ts

  • Utilise apiService (ancien service)
  • Gère user, isAuthenticated, isLoading, error
  • Utilise tokenManager pour les tokens

Store 2 : src/features/auth/store/authStore.ts

  • Utilise apiClient (nouveau client)
  • Gère user, accessToken, refreshToken, isAuthenticated
  • Stocke directement dans Zustand persist

Impact : Confusion sur quel store utiliser, état d'auth désynchronisé.

Problème : Format de Réponse Login Incohérent

Backend retourne (selon doc) :

{
  "success": true,
  "data": {
    "access_token": "...",
    "refresh_token": "...",
    "expires_in": 3600,
    "token_type": "Bearer",
    "user": { ... }
  }
}

Code Frontend :

  • src/services/api.ts (ligne 173) : Attend { user, token } dans data
  • src/services/api/auth.ts (ligne 122) : Attend { user, token } directement

Impact : Login ne fonctionne pas correctement.


🟠 Types TypeScript : ATTENTION — Incohérences

Problème 1 : Type User.id Incohérent

Backend : UUID (string) selon FRONTEND_INTEGRATION.md

Frontend :

  • src/types/index.ts : id: string
  • src/types/api.ts : id: string
  • src/features/auth/types/index.ts : id: number
  • src/services/api/auth.ts : id: number

Impact : Erreurs de type, conversion nécessaire.

Problème 2 : Interface ApiError Incomplète

Backend retourne (selon doc) :

{
  code: number,        // 1000, 2000, etc.
  message: string,
  details?: Array<{ field: string; message: string }>,
  request_id?: string,
  timestamp: string,
  context?: Record<string, any>
}

Frontend :

  • src/types/api.ts : code: string (devrait être number)
  • src/types/index.ts : code?: string (devrait être number)
  • Manque request_id, timestamp, context

Impact : Erreurs API mal parsées, perte d'information.

Problème 3 : Interface ApiResponse<T> Incomplète

Backend retourne :

{
  success: boolean,
  data: T | null,
  error?: ApiError,
  message?: string
}

Frontend (src/types/api.ts) :

{
  data: T,           // ❌ Devrait être T | null
  message?: string,
  success: boolean
  // ❌ Manque error?: ApiError
}

Impact : Types incorrects, pas de type safety pour les erreurs.


🟡 Gestion des Erreurs : ATTENTION — Non Standardisée

Problème : Parsing d'Erreurs Incohérent

Backend retourne (selon doc) :

{
  "success": false,
  "data": null,
  "error": {
    "code": 2000,
    "message": "Validation failed",
    "details": [...]
  }
}

Code Frontend :

  • src/services/api.ts : Parse error.response.data directement
  • src/services/api/auth.ts : Parse error.response.data?.error ou message
  • src/features/auth/services/authService.ts : Parse error.response.data?.error

Impact : Messages d'erreur incorrects, détails de validation perdus.


3. Plan d'Action Immédiat (Roadmap)

Priorité 1 : Standardiser le Client API (2-3h)

Tâche 1.1 : Unifier les Variables d'Environnement

Fichier : src/config/env.ts

Action :

  1. Renommer VITE_API_BASE_URLVITE_API_URL
  2. Renommer VITE_WS_BASE_URLVITE_WS_URL
  3. Mettre à jour tous les imports/utilisations

Validation : npm run typecheck passe, tests passent.


Tâche 1.2 : Créer un Client API Unique et Standardisé

Fichier : src/services/api/client.ts (refactoriser)

Action :

  1. Supprimer src/lib/apiClient.ts (ancien client)
  2. Refactoriser src/services/api/client.ts pour :
    • Utiliser env.API_URL (après Tâche 1.1)
    • Parser automatiquement le format { success, data, error }
    • Gérer les erreurs selon le format backend
    • Intercepteur de refresh token (déjà présent )

Code cible :

// Intercepteur de réponse pour parser le format backend
apiClient.interceptors.response.use(
  (response) => {
    // Backend retourne { success: true, data: {...} }
    if (response.data.success === true) {
      return { ...response, data: response.data.data };
    }
    // Si success === false, l'erreur sera gérée par le catch
    return response;
  },
  async (error) => {
    // Parser l'erreur backend { success: false, error: {...} }
    if (error.response?.data?.success === false) {
      const apiError = error.response.data.error;
      // Transformer en ApiError standardisé
      throw new APIError(apiError);
    }
    // ... reste du code refresh token
  }
);

Validation : Tests unitaires pour le parsing, tests d'intégration avec mock backend.


Tâche 1.3 : Créer les Types TypeScript Alignés avec le Backend

Fichier : src/types/api.ts (refactoriser)

Action :

  1. Corriger ApiError :

    export interface ApiError {
      code: number;  // Pas string !
      message: string;
      details?: Array<{ field: string; message: string }>;
      request_id?: string;
      timestamp: string;
      context?: Record<string, any>;
    }
    
  2. Corriger ApiResponse<T> :

    export interface ApiResponse<T> {
      success: boolean;
      data: T | null;
      error?: ApiError;
      message?: string;
    }
    
  3. Corriger User.id partout : string (UUID)

Validation : npm run typecheck passe, tous les usages mis à jour.


Priorité 2 : Standardiser l'Authentification (2h)

Tâche 2.1 : Unifier les Stores d'Auth

Fichier : src/stores/auth.ts (garder celui-ci, supprimer l'autre)

Action :

  1. Supprimer src/features/auth/store/authStore.ts
  2. Mettre à jour src/stores/auth.ts pour utiliser apiClient (nouveau client unifié)
  3. Adapter le format de réponse login selon la doc backend :
    // Backend retourne { success: true, data: { access_token, refresh_token, user } }
    const response = await apiClient.post('/auth/login', credentials);
    // apiClient.parse() retourne déjà data (grâce à l'intercepteur)
    const { access_token, refresh_token, expires_in, user } = response.data;
    

Validation : Tests d'authentification passent, redirection login/logout fonctionne.


Tâche 2.2 : Adapter les Services Auth au Format Backend

Fichier : src/services/api/auth.ts

Action :

  1. Mettre à jour login() pour parser { success: true, data: { access_token, refresh_token, user } }
  2. Mettre à jour register() de la même manière
  3. Mettre à jour getCurrentUser() pour parser { success: true, data: { ...user } }

Validation : Tests d'intégration auth passent.


Priorité 3 : Créer un Helper de Gestion d'Erreurs (1h)

Tâche 3.1 : Créer src/utils/apiErrorHandler.ts

Action :

  1. Créer une fonction parseApiError(error: AxiosError): ApiError
  2. Créer une fonction formatErrorMessage(error: ApiError): string
  3. Créer une fonction getValidationErrors(error: ApiError): Record<string, string>

Code cible :

export function parseApiError(error: AxiosError): ApiError {
  if (error.response?.data?.success === false) {
    return error.response.data.error;
  }
  // Fallback pour erreurs réseau, etc.
  return {
    code: error.response?.status || 0,
    message: error.message || 'An unexpected error occurred',
    timestamp: new Date().toISOString(),
  };
}

Validation : Tests unitaires pour chaque cas d'erreur.


Priorité 4 : Mettre à Jour les Types Partout (1-2h)

Tâche 4.1 : Audit et Correction des Types

Action :

  1. Chercher tous les usages de User.id et s'assurer que c'est string
  2. Chercher tous les usages de ApiError et s'assurer que code est number
  3. Mettre à jour les schémas Zod si nécessaire

Validation : npm run typecheck passe sans erreurs.


4. Checklist de Validation Finale

Avant de commencer l'intégration des fonctionnalités, vérifier :

  • Client API unique : Un seul apiClient utilisé partout
  • Variables d'env : VITE_API_URL, VITE_WS_URL (pas _BASE_URL)
  • Format de réponse : Toutes les réponses parsent { success, data, error }
  • Types TypeScript : ApiError.code est number, User.id est string
  • Store auth unique : Un seul store d'authentification
  • Gestion d'erreurs : Toutes les erreurs utilisent parseApiError()
  • Tests : Tous les tests passent (npm test)
  • Typecheck : Aucune erreur TypeScript (npm run typecheck)

5. Estimation Totale

Temps estimé : 6-8 heures de travail pour aligner le Frontend sur le Backend.

Ordre d'exécution recommandé :

  1. Tâches 1.1 + 1.3 (Types + Env) : 2h
  2. Tâche 1.2 (Client API) : 2-3h
  3. Tâches 2.1 + 2.2 (Auth) : 2h
  4. Tâche 3.1 (Error Handler) : 1h
  5. Tâche 4.1 (Audit Types) : 1h

6. Notes Importantes

⚠️ Breaking Changes Attendus

  • Les variables d'environnement changent (VITE_API_BASE_URLVITE_API_URL)
  • Le format de réponse API change (wrapper { success, data })
  • Les types ApiError.code changent (stringnumber)

Action : Mettre à jour tous les fichiers qui utilisent ces APIs.

Points Positifs à Préserver

  • La structure feature-based est excellente
  • Les intercepteurs de refresh token sont bien implémentés
  • Les tests sont configurés et fonctionnels
  • Le code est globalement bien organisé

Prochaine Étape : Exécuter les tâches dans l'ordre de priorité, puis valider avec des tests d'intégration contre le Backend réel.