456 lines
13 KiB
Markdown
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.
|
|
|