# 📅 Semaine 5 - Setup & Structure **Durée** : 20 heures **Objectif** : Poser les fondations techniques et créer la documentation architecturale --- ## 🎯 Objectifs de la Semaine 1. ✅ Initialiser le projet Next.js avec configuration optimale 2. ✅ Mettre en place la structure microservices 3. ✅ Configurer Supabase (base de données, auth, storage) 4. ✅ Créer les 8 documents livrables (cahier des charges) 5. ✅ Setup CI/CD basique 6. ✅ Installer et configurer tous les outils (ESLint, Prettier, Testing) --- ## 📋 Tâches Détaillées ### Jour 1 : Initialisation Next.js & Configuration (4h) #### Tâche 1.1 : Créer le projet Next.js (30 min) ```bash # Créer le projet cd apps/ npx create-next-app@latest modern-app \ --typescript \ --tailwind \ --app \ --src-dir \ --import-alias "@/*" \ --no-eslint cd modern-app # Installer dépendances supplémentaires pnpm add \ @supabase/supabase-js \ @supabase/auth-helpers-nextjs \ zod \ react-hook-form \ @hookform/resolvers \ zustand \ @tanstack/react-query \ date-fns \ clsx \ tailwind-merge # Dépendances dev pnpm add -D \ @types/node \ @types/react \ @types/react-dom \ jest \ @testing-library/react \ @testing-library/jest-dom \ @playwright/test \ eslint-config-prettier \ prettier \ husky \ lint-staged ``` **Critères d'acceptation** : - ✅ Projet Next.js 14 créé avec App Router - ✅ TypeScript configuré en mode strict - ✅ Tailwind CSS fonctionnel - ✅ Toutes les dépendances installées --- #### Tâche 1.2 : Configuration TypeScript strict (30 min) **Fichier** : `tsconfig.json` ```json { "compilerOptions": { "target": "ES2020", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": false, "skipLibCheck": true, "strict": true, "noEmit": true, "esModuleInterop": true, "module": "esnext", "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, "jsx": "preserve", "incremental": true, "plugins": [ { "name": "next" } ], "paths": { "@/*": ["./src/*"], "@/services/*": ["./src/services/*"], "@/components/*": ["./src/components/*"], "@/shared/*": ["./src/shared/*"] }, // Options strictes supplémentaires "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noImplicitReturns": true, "forceConsistentCasingInFileNames": true }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "exclude": ["node_modules"] } ``` **Critères d'acceptation** : - ✅ TypeScript strict mode activé - ✅ Path aliases configurés - ✅ `pnpm tsc --noEmit` passe sans erreur --- #### Tâche 1.3 : Configuration ESLint & Prettier (30 min) **Fichier** : `.eslintrc.json` ```json { "extends": [ "next/core-web-vitals", "plugin:@typescript-eslint/recommended", "prettier" ], "rules": { "@typescript-eslint/no-unused-vars": "error", "@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/explicit-function-return-type": "off", "prefer-const": "error", "no-console": ["warn", { "allow": ["warn", "error"] }] } } ``` **Fichier** : `.prettierrc` ```json { "semi": false, "singleQuote": true, "tabWidth": 2, "trailingComma": "es5", "printWidth": 80, "arrowParens": "always" } ``` **Fichier** : `package.json` (scripts) ```json { "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", "lint:fix": "next lint --fix", "format": "prettier --write \"src/**/*.{ts,tsx,json,md}\"", "type-check": "tsc --noEmit", "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage", "e2e": "playwright test", "e2e:ui": "playwright test --ui" } } ``` **Critères d'acceptation** : - ✅ ESLint configuré avec règles strictes - ✅ Prettier configuré - ✅ `pnpm lint` passe sans erreur - ✅ `pnpm format` fonctionne --- #### Tâche 1.4 : Configuration shadcn/ui (1h) ```bash # Initialiser shadcn/ui pnpm dlx shadcn-ui@latest init # Installer les composants de base pnpm dlx shadcn-ui@latest add button pnpm dlx shadcn-ui@latest add input pnpm dlx shadcn-ui@latest add card pnpm dlx shadcn-ui@latest add dialog pnpm dlx shadcn-ui@latest add form pnpm dlx shadcn-ui@latest add toast pnpm dlx shadcn-ui@latest add table pnpm dlx shadcn-ui@latest add badge pnpm dlx shadcn-ui@latest add avatar pnpm dlx shadcn-ui@latest add select pnpm dlx shadcn-ui@latest add calendar ``` **Fichier** : `src/lib/utils.ts` (créé par shadcn) ```typescript import { type ClassValue, clsx } from 'clsx' import { twMerge } from 'tailwind-merge' export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } ``` **Critères d'acceptation** : - ✅ shadcn/ui initialisé - ✅ Composants de base installés dans `src/components/ui/` - ✅ Tailwind config mise à jour avec les tokens shadcn --- #### Tâche 1.5 : Configuration des tests (Jest) (1h 30min) **Fichier** : `jest.config.js` ```javascript const nextJest = require('next/jest') const createJestConfig = nextJest({ dir: './', }) const customJestConfig = { setupFilesAfterEnv: ['/jest.setup.js'], testEnvironment: 'jest-environment-jsdom', moduleNameMapper: { '^@/(.*)$': '/src/$1', }, collectCoverageFrom: [ 'src/**/*.{ts,tsx}', '!src/**/*.d.ts', '!src/**/*.stories.tsx', '!src/app/**', // Exclure les pages Next.js ], coverageThreshold: { global: { branches: 80, functions: 80, lines: 80, statements: 80, }, }, } module.exports = createJestConfig(customJestConfig) ``` **Fichier** : `jest.setup.js` ```javascript import '@testing-library/jest-dom' ``` **Fichier** : `playwright.config.ts` ```typescript import { defineConfig, devices } from '@playwright/test' export default defineConfig({ testDir: './tests/e2e', fullyParallel: true, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: 'html', use: { baseURL: 'http://localhost:3000', trace: 'on-first-retry', }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] }, }, ], webServer: { command: 'pnpm dev', url: 'http://localhost:3000', reuseExistingServer: !process.env.CI, }, }) ``` **Critères d'acceptation** : - ✅ Jest configuré avec React Testing Library - ✅ Playwright configuré pour E2E - ✅ `pnpm test` exécute les tests unitaires - ✅ `pnpm e2e` exécute les tests E2E --- ### Jour 2 : Structure Microservices & Architecture (4h) #### Tâche 2.1 : Créer la structure des microservices (2h) ```bash # Créer la structure complète mkdir -p src/services/{auth,catalogue,reservation,inventory,payment,notification}/{domain/{entities,repositories,value-objects},application/{use-cases,services},infrastructure/{repositories,external}} mkdir -p src/shared/{domain/{entities,value-objects},infrastructure/{di,events,supabase},utils} mkdir -p src/components/{ui,features,layouts} mkdir -p src/hooks mkdir -p src/lib mkdir -p src/types mkdir -p tests/{unit,integration,e2e} mkdir -p docs ``` **Critères d'acceptation** : - ✅ Structure des 6 microservices créée - ✅ Chaque service suit Clean Architecture (3 couches) - ✅ Dossiers shared/ créés - ✅ Dossiers tests/ créés --- #### Tâche 2.2 : Créer les interfaces de base (Repository Pattern) (2h) **Fichier** : `src/shared/domain/repositories/base.repository.interface.ts` ```typescript export interface IBaseRepository { findById(id: ID): Promise findAll(filters?: Record): Promise create(data: Omit): Promise update(id: ID, data: Partial): Promise delete(id: ID): Promise } ``` **Fichier** : `src/shared/domain/entities/base.entity.ts` ```typescript export abstract class BaseEntity { id: string createdAt: Date updatedAt: Date constructor(id: string, createdAt?: Date, updatedAt?: Date) { this.id = id this.createdAt = createdAt || new Date() this.updatedAt = updatedAt || new Date() } } ``` **Fichier** : `src/shared/domain/value-objects/result.ts` ```typescript // Result Pattern (pour gérer succès/erreur) export class Result { public isSuccess: boolean public isFailure: boolean public error?: string private _value?: T private constructor(isSuccess: boolean, error?: string, value?: T) { this.isSuccess = isSuccess this.isFailure = !isSuccess this.error = error this._value = value } public get value(): T { if (this.isFailure) { throw new Error('Cannot get value from failed result') } return this._value as T } public static ok(value?: U): Result { return new Result(true, undefined, value) } public static fail(error: string): Result { return new Result(false, error) } } ``` **Critères d'acceptation** : - ✅ Interfaces de base créées - ✅ Result Pattern implémenté - ✅ BaseEntity créé --- ### Jour 3 : Configuration Supabase (4h) #### Tâche 3.1 : Créer le projet Supabase (30 min) 1. Aller sur https://supabase.com 2. Créer un nouveau projet : `bricoloc-moderne` 3. Choisir la région : Europe (eu-central-1) 4. Noter les credentials : - Project URL - Anon Key - Service Role Key **Fichier** : `.env.local` ```bash NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` **Critères d'acceptation** : - ✅ Projet Supabase créé - ✅ Variables d'environnement configurées --- #### Tâche 3.2 : Créer le schéma de base de données (2h) **Fichier** : `supabase/migrations/001_initial_schema.sql` ```sql -- Enable UUID extension CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- Table users (étendue de auth.users) CREATE TABLE public.profiles ( id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE, email TEXT NOT NULL, nom TEXT, prenom TEXT, telephone TEXT, adresse TEXT, ville TEXT, code_postal TEXT, is_admin BOOLEAN DEFAULT FALSE, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Table categories CREATE TABLE public.categories ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), nom TEXT NOT NULL, description TEXT, slug TEXT UNIQUE NOT NULL, icone TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Table entrepots CREATE TABLE public.entrepots ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), nom TEXT NOT NULL, ville TEXT NOT NULL, adresse TEXT NOT NULL, code_postal TEXT NOT NULL, telephone TEXT, email TEXT, horaires_ouverture TEXT, latitude DECIMAL(10, 8), longitude DECIMAL(11, 8), created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Table outils CREATE TABLE public.outils ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), nom TEXT NOT NULL, description TEXT, marque TEXT, modele TEXT, categorie_id UUID REFERENCES categories(id) ON DELETE SET NULL, prix_jour DECIMAL(10, 2) NOT NULL, caution DECIMAL(10, 2), puissance TEXT, poids TEXT, dimensions TEXT, specifications JSONB, image_principale TEXT, images TEXT[], reservable_professionnels_seulement BOOLEAN DEFAULT FALSE, actif BOOLEAN DEFAULT TRUE, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Index pour recherche CREATE INDEX idx_outils_nom ON outils USING gin(to_tsvector('french', nom)); CREATE INDEX idx_outils_description ON outils USING gin(to_tsvector('french', description)); CREATE INDEX idx_outils_categorie ON outils(categorie_id); -- Table stocks CREATE TABLE public.stocks ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), outil_id UUID NOT NULL REFERENCES outils(id) ON DELETE CASCADE, entrepot_id UUID NOT NULL REFERENCES entrepots(id) ON DELETE CASCADE, quantite_totale INTEGER NOT NULL DEFAULT 0, quantite_disponible INTEGER NOT NULL DEFAULT 0, quantite_reservee INTEGER NOT NULL DEFAULT 0, seuil_alerte INTEGER DEFAULT 2, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(outil_id, entrepot_id) ); -- Table reservations CREATE TABLE public.reservations ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), utilisateur_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE, outil_id UUID NOT NULL REFERENCES outils(id) ON DELETE RESTRICT, entrepot_id UUID NOT NULL REFERENCES entrepots(id) ON DELETE RESTRICT, date_debut DATE NOT NULL, date_fin DATE NOT NULL, nombre_jours INTEGER NOT NULL, prix_jour DECIMAL(10, 2) NOT NULL, prix_total DECIMAL(10, 2) NOT NULL, caution DECIMAL(10, 2), statut TEXT NOT NULL CHECK (statut IN ('en_attente_paiement', 'confirmee', 'en_cours', 'terminee', 'annulee')), date_retrait TIMESTAMPTZ, date_retour TIMESTAMPTZ, notes TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_reservations_utilisateur ON reservations(utilisateur_id); CREATE INDEX idx_reservations_outil ON reservations(outil_id); CREATE INDEX idx_reservations_dates ON reservations(date_debut, date_fin); CREATE INDEX idx_reservations_statut ON reservations(statut); -- Table transactions (paiements) CREATE TABLE public.transactions ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), reservation_id UUID NOT NULL REFERENCES reservations(id) ON DELETE CASCADE, montant DECIMAL(10, 2) NOT NULL, statut TEXT NOT NULL CHECK (statut IN ('en_attente', 'reussie', 'echouee', 'remboursee')), methode_paiement TEXT, stripe_payment_intent_id TEXT, stripe_charge_id TEXT, metadata JSONB, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- Fonction pour mettre à jour updated_at CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; -- Triggers pour updated_at CREATE TRIGGER update_profiles_updated_at BEFORE UPDATE ON profiles FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_categories_updated_at BEFORE UPDATE ON categories FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_entrepots_updated_at BEFORE UPDATE ON entrepots FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_outils_updated_at BEFORE UPDATE ON outils FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_stocks_updated_at BEFORE UPDATE ON stocks FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_reservations_updated_at BEFORE UPDATE ON reservations FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_transactions_updated_at BEFORE UPDATE ON transactions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); ``` **Exécuter la migration** : ```bash # Via Supabase CLI (optionnel) supabase migration new initial_schema # Copier le SQL ci-dessus dans le fichier généré supabase db push # OU via l'interface Supabase # SQL Editor > Nouvelle requête > Coller le SQL > Exécuter ``` **Critères d'acceptation** : - ✅ Schéma de base de données créé - ✅ 7 tables créées (profiles, categories, entrepots, outils, stocks, reservations, transactions) - ✅ Index de recherche créés - ✅ Triggers updated_at fonctionnels --- #### Tâche 3.3 : Configuration Row Level Security (RLS) (1h) **Fichier** : `supabase/migrations/002_rls_policies.sql` ```sql -- Enable RLS on all tables ALTER TABLE profiles ENABLE ROW LEVEL SECURITY; ALTER TABLE categories ENABLE ROW LEVEL SECURITY; ALTER TABLE entrepots ENABLE ROW LEVEL SECURITY; ALTER TABLE outils ENABLE ROW LEVEL SECURITY; ALTER TABLE stocks ENABLE ROW LEVEL SECURITY; ALTER TABLE reservations ENABLE ROW LEVEL SECURITY; ALTER TABLE transactions ENABLE ROW LEVEL SECURITY; -- Profiles policies CREATE POLICY "Users can view their own profile" ON profiles FOR SELECT USING (auth.uid() = id); CREATE POLICY "Users can update their own profile" ON profiles FOR UPDATE USING (auth.uid() = id); CREATE POLICY "Admins can view all profiles" ON profiles FOR SELECT USING ((SELECT is_admin FROM profiles WHERE id = auth.uid())); -- Categories policies (lecture publique) CREATE POLICY "Categories are viewable by everyone" ON categories FOR SELECT USING (true); CREATE POLICY "Only admins can insert categories" ON categories FOR INSERT WITH CHECK ((SELECT is_admin FROM profiles WHERE id = auth.uid())); CREATE POLICY "Only admins can update categories" ON categories FOR UPDATE USING ((SELECT is_admin FROM profiles WHERE id = auth.uid())); -- Entrepots policies (lecture publique) CREATE POLICY "Entrepots are viewable by everyone" ON entrepots FOR SELECT USING (true); CREATE POLICY "Only admins can manage entrepots" ON entrepots FOR ALL USING ((SELECT is_admin FROM profiles WHERE id = auth.uid())); -- Outils policies (lecture publique) CREATE POLICY "Outils are viewable by everyone" ON outils FOR SELECT USING (actif = true OR (SELECT is_admin FROM profiles WHERE id = auth.uid())); CREATE POLICY "Only admins can manage outils" ON outils FOR ALL USING ((SELECT is_admin FROM profiles WHERE id = auth.uid())); -- Stocks policies (lecture publique) CREATE POLICY "Stocks are viewable by everyone" ON stocks FOR SELECT USING (true); CREATE POLICY "Only admins can manage stocks" ON stocks FOR ALL USING ((SELECT is_admin FROM profiles WHERE id = auth.uid())); -- Reservations policies CREATE POLICY "Users can view their own reservations" ON reservations FOR SELECT USING (utilisateur_id = auth.uid() OR (SELECT is_admin FROM profiles WHERE id = auth.uid())); CREATE POLICY "Users can create reservations" ON reservations FOR INSERT WITH CHECK (utilisateur_id = auth.uid()); CREATE POLICY "Users can update their own reservations" ON reservations FOR UPDATE USING (utilisateur_id = auth.uid() AND statut = 'en_attente_paiement'); CREATE POLICY "Admins can manage all reservations" ON reservations FOR ALL USING ((SELECT is_admin FROM profiles WHERE id = auth.uid())); -- Transactions policies CREATE POLICY "Users can view their own transactions" ON transactions FOR SELECT USING ( (SELECT utilisateur_id FROM reservations WHERE id = reservation_id) = auth.uid() OR (SELECT is_admin FROM profiles WHERE id = auth.uid()) ); CREATE POLICY "Only system can insert transactions" ON transactions FOR INSERT WITH CHECK (false); -- Via API seulement ``` **Critères d'acceptation** : - ✅ RLS activé sur toutes les tables - ✅ Policies créées pour sécuriser l'accès - ✅ Utilisateurs ne peuvent voir que leurs données - ✅ Admins ont accès complet --- #### Tâche 3.4 : Seed data de test (30 min) **Fichier** : `supabase/seed.sql` ```sql -- Insérer des catégories INSERT INTO categories (nom, description, slug) VALUES ('Perceuses', 'Perceuses électriques et sans fil', 'perceuses'), ('Scies', 'Scies circulaires et sauteuses', 'scies'), ('Ponceuses', 'Ponceuses orbitales et excentriques', 'ponceuses'), ('Meuleuses', 'Meuleuses d''angle', 'meuleuses'), ('Échelles', 'Échelles et échafaudages', 'echelles'); -- Insérer des entrepôts INSERT INTO entrepots (nom, ville, adresse, code_postal, telephone, email) VALUES ('BricoLoc Toulouse', 'Toulouse', '15 Avenue de la Gare', '31000', '05 61 00 00 00', 'toulouse@bricoloc.fr'), ('BricoLoc Paris', 'Paris', '42 Rue de Rivoli', '75004', '01 40 00 00 00', 'paris@bricoloc.fr'); -- Insérer quelques outils (seront complétés en Semaine 7) INSERT INTO outils (nom, description, marque, categorie_id, prix_jour, caution, image_principale) VALUES ('Perceuse Bosch Professional', 'Perceuse à percussion 18V', 'Bosch', (SELECT id FROM categories WHERE slug = 'perceuses'), 12.00, 150.00, '/images/outils/perceuse-bosch.jpg'), ('Scie Circulaire Makita', 'Scie circulaire 1200W', 'Makita', (SELECT id FROM categories WHERE slug = 'scies'), 15.00, 200.00, '/images/outils/scie-makita.jpg'); -- Insérer des stocks INSERT INTO stocks (outil_id, entrepot_id, quantite_totale, quantite_disponible) VALUES ((SELECT id FROM outils WHERE nom LIKE 'Perceuse%'), (SELECT id FROM entrepots WHERE ville = 'Toulouse'), 5, 5), ((SELECT id FROM outils WHERE nom LIKE 'Scie%'), (SELECT id FROM entrepots WHERE ville = 'Toulouse'), 3, 3); ``` **Critères d'acceptation** : - ✅ Catégories de test insérées - ✅ Entrepôts de test insérés - ✅ Quelques outils de test insérés --- ### Jour 4 : Documentation Livrables (4h) Créer les 6 documents requis par le cahier des charges. #### Tâche 4.1 : Exigences Non Fonctionnelles (1h) Créer `docs/NON_FUNCTIONAL_REQUIREMENTS.md` - Voir fichier séparé #### Tâche 4.2 : Architecture Logique (1h) Créer `docs/LOGICAL_ARCHITECTURE.md` - Voir fichier séparé #### Tâche 4.3 : Comparaison Styles Architecturaux (1h) Créer `docs/ARCHITECTURE_STYLES_COMPARISON.md` - Voir fichier séparé #### Tâche 4.4 : Matrice de Choix Technologique (1h) Créer `docs/TECHNOLOGY_DECISION_MATRIX.md` - Voir fichier séparé **Critères d'acceptation** : - ✅ 4 documents créés et complets - ✅ Format Markdown professionnel - ✅ Diagrammes Mermaid inclus --- ### Jour 5 : CI/CD & Finalisation (4h) #### Tâche 5.1 : Configuration GitHub Actions (2h) **Fichier** : `.github/workflows/ci.yml` ```yaml name: CI on: push: branches: [main, develop] pull_request: branches: [main, develop] jobs: lint-and-type-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 with: version: 8 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'pnpm' - name: Install dependencies run: pnpm install - name: Lint run: pnpm lint - name: Type check run: pnpm type-check test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 with: version: 8 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'pnpm' - name: Install dependencies run: pnpm install - name: Run tests run: pnpm test:coverage - name: Upload coverage uses: codecov/codecov-action@v3 with: files: ./coverage/lcov.info build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 with: version: 8 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'pnpm' - name: Install dependencies run: pnpm install - name: Build run: pnpm build - name: Check bundle size run: | BUNDLE_SIZE=$(du -sh .next/static | cut -f1) echo "Bundle size: $BUNDLE_SIZE" ``` **Critères d'acceptation** : - ✅ CI configuré sur GitHub Actions - ✅ Lint, type-check, tests et build automatisés - ✅ Pipeline s'exécute sur chaque push/PR --- #### Tâche 5.2 : Configuration Vercel (30 min) 1. Connecter le repo GitHub à Vercel 2. Configurer les variables d'environnement : - `NEXT_PUBLIC_SUPABASE_URL` - `NEXT_PUBLIC_SUPABASE_ANON_KEY` 3. Déploiement automatique sur push `main` **Critères d'acceptation** : - ✅ Projet déployé sur Vercel - ✅ URL de production accessible - ✅ Variables d'environnement configurées --- #### Tâche 5.3 : Documentation README (1h) **Fichier** : `README.md` ```markdown # BricoLoc - Application Moderne Application de location d'outils démontrant une architecture microservices moderne avec Clean Architecture. ## Stack Technique - **Frontend** : Next.js 14, React 18, TypeScript - **UI** : Tailwind CSS, shadcn/ui - **Backend** : Supabase (PostgreSQL, Auth, Realtime, Storage) - **Tests** : Jest, React Testing Library, Playwright - **CI/CD** : GitHub Actions, Vercel ## Architecture Cette application suit une architecture microservices hybride avec 6 services : - Auth Service - Catalogue Service - Reservation Service - Inventory Service - Payment Service - Notification Service Chaque service implémente Clean Architecture avec 3 couches : - Domain Layer (Entities, Business Rules) - Application Layer (Use Cases, Services) - Infrastructure Layer (Repositories, External APIs) ## Installation ```bash # Installer les dépendances pnpm install # Configurer les variables d'environnement cp .env.example .env.local # Éditer .env.local avec vos credentials Supabase # Lancer en développement pnpm dev ``` ## Scripts Disponibles - `pnpm dev` - Lancer le serveur de développement - `pnpm build` - Build de production - `pnpm start` - Lancer le build de production - `pnpm lint` - Linter le code - `pnpm type-check` - Vérifier les types TypeScript - `pnpm test` - Tests unitaires - `pnpm test:coverage` - Tests avec coverage - `pnpm e2e` - Tests E2E avec Playwright ## Documentation - [Roadmap](./docs/ROADMAP_MODERN.md) - [Exigences Non Fonctionnelles](./docs/NON_FUNCTIONAL_REQUIREMENTS.md) - [Architecture Logique](./docs/LOGICAL_ARCHITECTURE.md) - [Comparaison Styles Architecturaux](./docs/ARCHITECTURE_STYLES_COMPARISON.md) - [Matrice de Choix Technologique](./docs/TECHNOLOGY_DECISION_MATRIX.md) ## License MIT ``` **Critères d'acceptation** : - ✅ README complet et professionnel - ✅ Instructions d'installation claires - ✅ Liens vers documentation --- #### Tâche 5.4 : Revue et Tests (30 min) - Vérifier que toutes les commandes fonctionnent - Vérifier que le CI passe - Vérifier que le déploiement Vercel fonctionne - Commit et push final **Critères d'acceptation** : - ✅ Toutes les commandes s'exécutent sans erreur - ✅ CI GitHub Actions au vert - ✅ Application déployée sur Vercel --- ## ✅ Checklist de Fin de Semaine 5 ### Configuration Projet - [x] Next.js 14 initialisé avec App Router ✅ - [x] TypeScript strict mode configuré ✅ - [x] ESLint + Prettier configurés ✅ - [x] shadcn/ui installé et configuré ✅ - [x] Jest + Playwright configurés ✅ ### Structure - [x] Structure microservices créée (6 services) ✅ - [x] Clean Architecture par service (3 couches) ✅ - [x] Shared/ avec DI, Event Bus, utils ✅ - [x] Interfaces de base (Repository, Entity, Result) ✅ ### Supabase - [x] Projet Supabase créé ✅ - [x] Schéma de base de données créé (7 tables) ✅ - [x] RLS policies configurées ✅ - [x] Types TypeScript générés ✅ ### Documentation - [x] NON_FUNCTIONAL_REQUIREMENTS.md ✅ - [x] LOGICAL_ARCHITECTURE.md ✅ - [x] ARCHITECTURE_STYLES_COMPARISON.md ✅ - [x] TECHNOLOGY_DECISION_MATRIX.md ✅ - [x] SUPABASE_SETUP.md ✅ ### CI/CD - [x] GitHub Actions configuré ✅ - [ ] Vercel connecté et déployé (à configurer manuellement) - [x] README.md complet ✅ ### Tests - [x] `pnpm lint` passe ✅ - [x] `pnpm type-check` passe (src/) ✅ - [x] `pnpm build` réussit ✅ - [x] Tests unitaires (14 tests) ✅ - [ ] CI GitHub Actions au vert (nécessite push sur GitHub) - [ ] Déploiement Vercel fonctionnel (nécessite connexion manuelle) --- ## 🚀 Prochaine Étape **Semaine 6** : Implémenter Auth Service avec Supabase Auth Voir : [Semaine 6 - Auth Service](./WEEK_6_AUTH.md) --- **Maintenu par** : Équipe Architecture BricoLoc **Dernière mise à jour** : 31 Octobre 2025