158 lines
4.8 KiB
Markdown
158 lines
4.8 KiB
Markdown
# Architecture Frontend — Next.js 14
|
|
|
|
---
|
|
|
|
## Structure
|
|
|
|
```
|
|
apps/frontend/
|
|
├── app/ # Next.js App Router
|
|
│ ├── [locale]/ # i18n wrapper (fr, en) — next-intl
|
|
│ │ ├── about/
|
|
│ │ ├── blog/
|
|
│ │ ├── booking/ # Flux de réservation
|
|
│ │ ├── careers/
|
|
│ │ ├── carrier/ # Portail carrier (magic link)
|
|
│ │ ├── compliance/
|
|
│ │ ├── contact/
|
|
│ │ ├── dashboard/ # Application protégée
|
|
│ │ │ ├── bookings/
|
|
│ │ │ ├── csv-bookings/
|
|
│ │ │ ├── search/
|
|
│ │ │ ├── settings/
|
|
│ │ │ ├── admin/
|
|
│ │ │ └── wiki/
|
|
│ │ ├── docs/
|
|
│ │ ├── forgot-password/
|
|
│ │ ├── login/
|
|
│ │ ├── pricing/
|
|
│ │ ├── register/
|
|
│ │ ├── reset-password/
|
|
│ │ └── verify-email/
|
|
│ └── api/v1/ # API routes Next.js (proxy)
|
|
│
|
|
├── src/
|
|
│ ├── components/ # Composants React
|
|
│ │ ├── admin/
|
|
│ │ ├── blog/
|
|
│ │ ├── bookings/
|
|
│ │ ├── docs/
|
|
│ │ ├── layout/
|
|
│ │ ├── organization/
|
|
│ │ ├── rate-search/
|
|
│ │ └── ui/ # Composants shadcn/ui (Radix UI)
|
|
│ ├── hooks/ # Custom hooks (TanStack Query)
|
|
│ ├── lib/
|
|
│ │ ├── api/ # Client fetch avec auto-refresh JWT
|
|
│ │ │ ├── client.ts # get/post/patch/del/upload/download
|
|
│ │ │ ├── auth.ts
|
|
│ │ │ ├── bookings.ts
|
|
│ │ │ ├── rates.ts
|
|
│ │ │ └── ...
|
|
│ │ ├── context/ # AuthContext, CookieContext
|
|
│ │ └── providers/ # QueryProvider (TanStack Query)
|
|
│ ├── types/ # Types TypeScript
|
|
│ └── utils/ # Export Excel, PDF
|
|
│
|
|
├── i18n/ # Config next-intl
|
|
├── messages/
|
|
│ ├── fr.json # Traductions français
|
|
│ └── en.json # Traductions anglais
|
|
└── middleware.ts # Auth + i18n routing
|
|
```
|
|
|
|
---
|
|
|
|
## i18n (Internationalisation)
|
|
|
|
Le frontend supporte **français** (par défaut) et **anglais** via `next-intl`.
|
|
|
|
Routes : `/fr/login`, `/en/login`, etc.
|
|
|
|
```typescript
|
|
// i18n/routing.ts
|
|
export const routing = defineRouting({
|
|
locales: ['fr', 'en'],
|
|
defaultLocale: 'fr',
|
|
});
|
|
```
|
|
|
|
Le middleware `middleware.ts` combine la protection d'auth **et** le routing i18n.
|
|
|
|
---
|
|
|
|
## Client API
|
|
|
|
`src/lib/api/client.ts` — wrapper fetch avec auto-refresh JWT :
|
|
|
|
```typescript
|
|
// Toutes les requêtes passent par ces fonctions
|
|
export const get = <T>(url: string): Promise<T>
|
|
export const post = <T>(url: string, body: unknown): Promise<T>
|
|
export const patch = <T>(url: string, body: unknown): Promise<T>
|
|
export const del = <T>(url: string): Promise<T>
|
|
export const upload = <T>(url: string, formData: FormData): Promise<T>
|
|
export const download = (url: string): Promise<Blob>
|
|
```
|
|
|
|
- Sur 401 : refresh automatique du token, retry de la requête
|
|
- Tokens : localStorage ET cookie `accessToken` (pour le middleware Next.js)
|
|
|
|
---
|
|
|
|
## State management
|
|
|
|
- **Données serveur** : TanStack Query v5 (`@tanstack/react-query`)
|
|
- **État global UI** : zustand (minimal)
|
|
- **Formulaires** : react-hook-form + zod
|
|
|
|
```typescript
|
|
// Pattern hook standard
|
|
export function useBookings(filters?: BookingFilters) {
|
|
return useQuery({
|
|
queryKey: ['bookings', filters],
|
|
queryFn: () => bookingsApi.list(filters),
|
|
});
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Protection des routes
|
|
|
|
`middleware.ts` vérifie le cookie `accessToken` avant chaque route.
|
|
|
|
**Routes publiques exactes** : `/fr`, `/en`, `/`
|
|
|
|
**Routes publiques par préfixe** :
|
|
`/login`, `/register`, `/forgot-password`, `/reset-password`, `/verify-email`,
|
|
`/about`, `/blog`, `/pricing`, `/contact`, `/careers`, `/press`, `/security`,
|
|
`/privacy`, `/terms`, `/cookies`, `/compliance`, `/carrier`
|
|
|
|
Toutes les autres routes → redirection `/login?redirect=<pathname>`
|
|
|
|
---
|
|
|
|
## Design system
|
|
|
|
| Élément | Valeur |
|
|
|---------|--------|
|
|
| Couleur primaire | Navy `#10183A` |
|
|
| Couleur accent | Turquoise `#34CCCD` |
|
|
| Succès | Green `#067224` |
|
|
| Fond neutre | Gray `#F2F2F2` |
|
|
| Font headings | Manrope |
|
|
| Font body | Montserrat |
|
|
| UI components | shadcn/ui (Radix UI) |
|
|
| Icônes | lucide-react |
|
|
|
|
---
|
|
|
|
## Conventions
|
|
|
|
- Pas de fetch direct — toujours via `src/lib/api/*.ts`
|
|
- Les hooks wrappent TanStack Query, pas de `useEffect` pour les données
|
|
- `strict: false` en frontend (contrairement au backend)
|
|
- Alias `@/*` → `./src/*`
|
|
- La landing page est en **français**
|