# 🛠️ GUIDE DE DÉVELOPPEMENT - BTPXPRESS FRONTEND ## 📋 Table des matières - [Prérequis](#prérequis) - [Installation](#installation) - [Configuration](#configuration) - [Structure du projet](#structure-du-projet) - [Conventions de code](#conventions-de-code) - [Workflow de développement](#workflow-de-développement) - [Composants](#composants) - [Services API](#services-api) - [Gestion de l'état](#gestion-de-létat) - [Routing](#routing) - [Styling](#styling) - [Debugging](#debugging) - [Bonnes pratiques](#bonnes-pratiques) --- ## 🔧 Prérequis ### **Logiciels requis** | Logiciel | Version | Vérification | |----------|---------|--------------| | **Node.js** | 20.x LTS | `node --version` | | **npm** | 10.x | `npm --version` | | **VS Code** | Latest | Recommandé | ### **Extensions VS Code recommandées** - **ES7+ React/Redux/React-Native snippets** - **Prettier - Code formatter** - **ESLint** - **TypeScript Vue Plugin (Volar)** - **Tailwind CSS IntelliSense** - **Auto Rename Tag** - **Path Intellisense** --- ## 📦 Installation ### **1. Cloner et installer** ```bash cd btpxpress/btpxpress-client npm install ``` ### **2. Configurer les variables d'environnement** Créer `.env.local` : ```bash NEXT_PUBLIC_API_URL=http://localhost:8080/api/v1 NEXT_PUBLIC_KEYCLOAK_URL=http://localhost:8180 NEXT_PUBLIC_KEYCLOAK_REALM=btpxpress NEXT_PUBLIC_KEYCLOAK_CLIENT_ID=btpxpress-frontend ``` ### **3. Lancer le serveur de développement** ```bash npm run dev ``` Ouvrir http://localhost:3000 --- ## ⚙️ Configuration ### **next.config.js** ```javascript /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, swcMinify: true, images: { domains: ['localhost'], }, env: { API_URL: process.env.NEXT_PUBLIC_API_URL, }, } module.exports = nextConfig ``` ### **tsconfig.json** ```json { "compilerOptions": { "target": "ES2020", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, "strict": true, "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "paths": { "@/*": ["./*"], "@/components/*": ["./components/*"], "@/services/*": ["./services/*"], "@/types/*": ["./types/*"], "@/hooks/*": ["./hooks/*"] } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"] } ``` --- ## 📁 Structure du projet ``` btpxpress-client/ ├── app/ # App Router (Next.js 15) │ ├── (auth)/ # Groupe de routes authentifiées │ │ ├── layout.tsx # Layout avec sidebar │ │ ├── dashboard/ │ │ │ └── page.tsx # /dashboard │ │ ├── chantiers/ │ │ │ ├── page.tsx # /chantiers (liste) │ │ │ ├── [id]/ │ │ │ │ └── page.tsx # /chantiers/[id] (détails) │ │ │ └── nouveau/ │ │ │ └── page.tsx # /chantiers/nouveau │ │ └── ... │ ├── login/ │ │ └── page.tsx # /login │ ├── layout.tsx # Layout racine │ ├── page.tsx # / (accueil) │ └── globals.css # Styles globaux ├── components/ │ ├── layout/ │ │ ├── Header.tsx │ │ ├── Sidebar.tsx │ │ └── Footer.tsx │ ├── forms/ │ │ ├── ChantierForm.tsx │ │ └── ClientForm.tsx │ ├── tables/ │ │ └── DataTableWrapper.tsx │ └── common/ │ ├── LoadingSpinner.tsx │ └── ErrorMessage.tsx ├── services/ │ ├── api/ │ │ ├── chantierService.ts │ │ ├── clientService.ts │ │ └── apiClient.ts │ ├── auth/ │ │ └── keycloakService.ts │ └── utils/ │ └── formatters.ts ├── types/ │ ├── models/ │ │ ├── Chantier.ts │ │ └── Client.ts │ └── api/ │ └── responses.ts ├── hooks/ │ ├── useAuth.ts │ ├── useChantiers.ts │ └── useToast.ts ├── contexts/ │ ├── AuthContext.tsx │ └── ThemeContext.tsx └── public/ ├── images/ └── icons/ ``` --- ## 📝 Conventions de code ### **Nommage** | Élément | Convention | Exemple | |---------|------------|---------| | **Composants** | PascalCase | `ChantierForm.tsx` | | **Fichiers** | PascalCase (composants), camelCase (autres) | `Header.tsx`, `apiClient.ts` | | **Variables** | camelCase | `const userName = ...` | | **Constantes** | UPPER_SNAKE_CASE | `const API_URL = ...` | | **Types/Interfaces** | PascalCase | `interface ChantierDTO` | | **Hooks** | camelCase avec `use` | `useAuth()` | ### **Structure d'un composant** ```typescript 'use client'; // Si nécessaire (composant client) import React from 'react'; import { Button } from 'primereact/button'; import type { ChantierDTO } from '@/types/models/Chantier'; interface ChantierFormProps { chantier?: ChantierDTO; onSubmit: (data: ChantierDTO) => void; onCancel: () => void; } export const ChantierForm: React.FC = ({ chantier, onSubmit, onCancel, }) => { // Hooks const [loading, setLoading] = React.useState(false); // Handlers const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); // ... }; // Render return (
{/* JSX */}
); }; ``` --- ## 🔄 Workflow de développement ### **1. Créer une branche** ```bash git checkout -b feature/nom-de-la-fonctionnalite ``` ### **2. Développer** 1. Créer le type TypeScript (`types/models/`) 2. Créer le service API (`services/api/`) 3. Créer le composant (`components/`) 4. Créer la page (`app/`) 5. Tester ### **3. Tester localement** ```bash npm run dev npm run lint npm test ``` ### **4. Commit et Push** ```bash git add . git commit -m "feat: ajout de la fonctionnalité X" git push origin feature/nom-de-la-fonctionnalite ``` --- ## 🧩 Composants ### **Composant fonctionnel avec TypeScript** ```typescript import React from 'react'; interface Props { title: string; count: number; onIncrement: () => void; } export const Counter: React.FC = ({ title, count, onIncrement }) => { return (

{title}

Count: {count}

); }; ``` ### **Composant avec PrimeReact** ```typescript 'use client'; import { DataTable } from 'primereact/datatable'; import { Column } from 'primereact/column'; import { Button } from 'primereact/button'; export const ChantierTable = ({ chantiers }) => { const actionBodyTemplate = (rowData) => { return (