Structure des Features
Nous utilisons une approche Domain-Driven Design (DDD) pour l'organisation des fichiers.
Tout ce qui est lié à un domaine métier spécifique (ex: Caméras) reste groupé dans le dossier features/.
Anatomie d'une Feature
En prenant features/cameras comme exemple :
features/cameras/
├── api.ts # Appels API BRUTS (wrappers fetch/axios)
├── types.ts # Interfaces TypeScript & Enums
├── hooks.ts # Hooks React Query (useCameras, useCamera)
├── components/ # Composants UI spécifiques à cette feature
│ ├── camera-card.tsx
│ ├── camera-form.tsx
│ └── metrics-chart.tsx
└── index.ts # API Publique (Ce qui est exposé au reste de l'app)
1. api.ts
Contient des fonctions asynchrones pures qui retournent des Promesses.
Elles utilisent le apiClient global.
export const fetchCameras = async (params) => {
return apiClient.get("/cameras", { params });
};
2. hooks.ts
Connecte les fonctions api.ts à TanStack Query.
C'est ici que sont définies les stratégies de clés de cache.
export const useCameras = (filters) => {
return useQuery({
queryKey: ["cameras", filters],
queryFn: () => fetchCameras(filters),
});
};
3. components/
Contient les Vues.
- Logique Lourde :
camera-form.tsx(Validation Zod, mutation API). - Présentation :
camera-card.tsx(Affiche une seule caméra). - Analytics :
agitation-trend-chart.tsx,metrics-chart.tsx.
Pourquoi cette structure ?
- Isolation : Vous pouvez supprimer le dossier
features/cameraset seule cette fonctionnalité disparaît. - Découvrabilité : "Où est le code pour la Carte Caméra ?" ->
features/cameras/components. - Scalabilité : Ajouter une nouvelle fonctionnalité n'encombre pas le dossier
componentsglobal.