veza/apps/web/AUDIT_FRONTEND_GAP_ANALYSIS.md

456 lines
13 KiB
Markdown

# 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`
```typescript
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`
```typescript
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`) :
```bash
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`) :
```typescript
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`) :
```json
{
"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) :
```json
{
"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) :
```typescript
{
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** :
```typescript
{
success: boolean,
data: T | null,
error?: ApiError,
message?: string
}
```
**Frontend** (`src/types/api.ts`) :
```typescript
{
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) :
```json
{
"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_URL``VITE_API_URL`
2. Renommer `VITE_WS_BASE_URL``VITE_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** :
```typescript
// 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` :
```typescript
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>` :
```typescript
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 :
```typescript
// 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** :
```typescript
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_URL` → `VITE_API_URL`)
- Le format de réponse API change (wrapper `{ success, data }`)
- Les types `ApiError.code` changent (`string` → `number`)
**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.