Le statut PENDING_PAYMENT ne designe plus un paiement en attente mais un devis : une reservation construite dont les frais de booking ne sont pas encore regles. L'enum backend devient QUOTE, converti en place par migration. Les deux onglets se partagent desormais la meme liste : - « Reservations » n'affiche que PENDING, ACCEPTED et REJECTED ; - « Historique des devis » regroupe QUOTE, PENDING_BANK_TRANSFER et CANCELLED, avec les actions propres a un devis (modifier, payer, supprimer). La table, l'export et les filtres sont extraits dans BookingListView pour eviter de dupliquer la page entre les deux vues. Tableau de bord : - l'alerte « Paiement en attente » disparait des points a traiter, les devis non regles ne bloquant aucun envoi en cours ; - « Sans reponse du transporteur » devient « En attente du transporteur ». Migration verifiee en transaction annulee sur la base de dev : les lignes PENDING_PAYMENT deviennent QUOTE, l'enum et le defaut de colonne suivent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NZJ5aowZJVAcyPZw5TiNEm |
||
|---|---|---|
| .. | ||
| app | ||
| e2e | ||
| i18n | ||
| lib | ||
| messages | ||
| public | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .eslintrc.json | ||
| .gitignore | ||
| DESIGN_QUICK_START.md | ||
| DESIGN_SYSTEM.md | ||
| Dockerfile | ||
| FRONTEND_API_CONNECTION_COMPLETE.md | ||
| IMPLEMENTATION_COMPLETE.md | ||
| jest.config.js | ||
| jest.setup.ts | ||
| LOGIN_PAGE_COMPLETE.md | ||
| middleware.ts | ||
| next.config.js | ||
| package-lock.json | ||
| package.json | ||
| playwright.config.ts | ||
| postcss.config.js | ||
| README.md | ||
| tailwind.config.ts | ||
| tsconfig.json | ||
| tsconfig.test.json | ||
Xpeditis Frontend
Application Next.js 14 pour la plateforme de réservation de fret maritime Xpeditis.
✅ Status Actuel: INFRASTRUCTURE COMPLÈTE
| Domaine | Status | Notes |
|---|---|---|
| API Integration | ✅ 100% | 60 endpoints connectés |
| Design System | ✅ 100% | Couleurs + Typos + Composants CSS |
| TypeScript Types | ✅ 100% | Types complets pour toutes les API |
| Assets Structure | ✅ 100% | Dossiers + utilitaires + docs |
| Documentation | ✅ 100% | 5 guides complets |
Infrastructure Frontend: PRODUCTION READY ✅
🎨 Design System Xpeditis
Couleurs de Marque ✅
| Couleur | Hex | Usage |
|---|---|---|
| Navy Blue | #10183A |
Headers, titres principaux |
| Turquoise | #34CCCD |
CTAs, liens, accents |
| Green | #067224 |
Success states, confirmations |
| Light Gray | #F2F2F2 |
Backgrounds, sections |
| White | #FFFFFF |
Cards, backgrounds principaux |
Typographies ✅
- Manrope (Google Fonts) - Titres H1-H6, navigation, boutons
- Montserrat (Google Fonts) - Corps de texte, formulaires, UI
Classes Tailwind Pré-configurées ✅
// Couleurs
bg-brand-navy, bg-brand-turquoise, bg-brand-green
text-accent, text-success
// Typographie
font-heading (Manrope), font-body (Montserrat)
text-h1, text-h2, text-body, text-body-sm, text-label
// Composants
btn-primary, btn-secondary, btn-success, btn-outline
card, badge-success, badge-info, link, input, label
📚 Documentation: DESIGN_SYSTEM.md | Quick Start
🔌 API Client (60 Endpoints) ✅
Tous les endpoints backend connectés avec types TypeScript:
import { login, searchCsvRates, createBooking } from '@/lib/api';
// Recherche avec pricing détaillé
const rates = await searchCsvRates({
origin: 'FRFOS',
destination: 'CNSHA',
volumeCBM: 6,
weightKG: 2500,
requiresSpecialHandling: true
});
// rates[0].priceBreakdown → basePrice, volumeCharge, surcharges[], totalPrice
Modules disponibles: auth (5), rates (4), bookings (7), users (6), organizations (4), notifications (7), audit (5), webhooks (7), gdpr (6), admin (5)
📚 Documentation: FRONTEND_API_CONNECTION_COMPLETE.md
🏗️ Tech Stack
- Framework: Next.js 14 (App Router)
- Language: TypeScript 5+
- Styling: Tailwind CSS v4 + shadcn/ui
- Fonts: Google Fonts (Manrope + Montserrat) ✅
- State Management: TanStack Query + Zustand
- Forms: react-hook-form + zod
- HTTP Client: Fetch API (custom wrapper) ✅
- Icons: lucide-react
- Testing: Jest + React Testing Library + Playwright
🚀 Quick Start
Install Dependencies
npm install
Setup Environment
cp .env.example .env
Default values work for local development!
Start Development Server
npm run dev
Open: http://localhost:3000
📝 Available Scripts
Development
npm run dev- Start development server (port 3000)npm run build- Build for productionnpm run start- Start production servernpm run lint- Lint codenpm test- Run testsnpm run test:watch- Run tests in watch modenpm run test:e2e- Run Playwright E2E tests
📁 Project Structure
app/
├── layout.tsx # Root layout
├── page.tsx # Home page
├── globals.css # Global styles
├── (routes)/ # Route groups
│ ├── search/ # Rate search
│ ├── bookings/ # Booking management
│ ├── dashboard/ # User dashboard
│ └── auth/ # Authentication
└── api/ # API routes (if needed)
components/
├── ui/ # shadcn/ui components
├── search/ # Search-specific components
├── bookings/ # Booking-specific components
└── shared/ # Shared components
lib/
├── api/ # API client & hooks
├── hooks/ # Custom React hooks
├── types/ # TypeScript types
├── utils.ts # Utility functions
└── validators/ # Zod schemas
🎨 Styling
Tailwind CSS
Using Tailwind CSS with custom theme configuration.
CSS Variables (defined in globals.css):
--background,--foreground--primary,--secondary--muted,--accent--destructive,--border- etc.
shadcn/ui Components
Pre-built accessible components:
- Buttons, Cards, Dialogs
- Forms, Inputs, Selects
- Tables, Tabs, Dropdowns
- And more...
Adding components:
npx shadcn-ui@latest add button
npx shadcn-ui@latest add card
# etc.
🔌 API Integration
API Client Setup
// lib/api/client.ts
import axios from 'axios';
const apiClient = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:4000',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
export default apiClient;
React Query Hooks
// lib/api/rates.ts
import { useQuery } from '@tanstack/react-query';
import apiClient from './client';
export function useSearchRates(params: RateSearchParams) {
return useQuery({
queryKey: ['rates', params],
queryFn: async () => {
const { data } = await apiClient.post('/api/v1/rates/search', params);
return data;
},
});
}
Usage in Components
// components/search/SearchResults.tsx
import { useSearchRates } from '@/lib/api/rates';
export function SearchResults({ params }: Props) {
const { data, isLoading, error } = useSearchRates(params);
if (isLoading) return <LoadingSkeleton />;
if (error) return <ErrorMessage error={error} />;
return <RatesList rates={data} />;
}
📋 Forms
Using react-hook-form + zod for type-safe form validation.
Example:
// lib/validators/search.ts
import { z } from 'zod';
export const searchSchema = z.object({
origin: z.string().min(3, 'Invalid port code'),
destination: z.string().min(3, 'Invalid port code'),
containerType: z.enum(['20DRY', '40DRY', '40HC']),
departureDate: z.string().datetime(),
});
export type SearchFormData = z.infer<typeof searchSchema>;
// components/search/SearchForm.tsx
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { searchSchema, SearchFormData } from '@/lib/validators/search';
export function SearchForm() {
const { register, handleSubmit, formState: { errors } } = useForm<SearchFormData>({
resolver: zodResolver(searchSchema),
});
const onSubmit = (data: SearchFormData) => {
// Handle submission
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* Form fields */}
</form>
);
}
🧪 Testing
Unit Tests (Jest + React Testing Library)
npm test
Example:
// components/ui/Button.test.tsx
import { render, screen } from '@testing-library/react';
import { Button } from './Button';
describe('Button', () => {
it('renders children', () => {
render(<Button>Click me</Button>);
expect(screen.getByText('Click me')).toBeInTheDocument();
});
});
E2E Tests (Playwright)
npm run test:e2e
Example:
// e2e/search.spec.ts
import { test, expect } from '@playwright/test';
test('search for rates', async ({ page }) => {
await page.goto('/search');
await page.fill('[name="origin"]', 'NLRTM');
await page.fill('[name="destination"]', 'CNSHA');
await page.click('button[type="submit"]');
await expect(page.locator('.rate-card')).toBeVisible();
});
🔒 Authentication
Authentication will be handled with:
- JWT tokens from backend
- NextAuth.js (optional)
- Protected routes with middleware
Example (to be implemented):
// middleware.ts
export { default } from 'next-auth/middleware';
export const config = {
matcher: ['/dashboard/:path*', '/bookings/:path*'],
};
📱 Responsive Design
Mobile-first approach with Tailwind breakpoints:
<div className="
flex flex-col // Mobile: column
md:flex-row // Tablet: row
lg:gap-8 // Desktop: larger gap
xl:max-w-7xl // Extra large: max width
">
{/* Content */}
</div>
Breakpoints:
sm: 640pxmd: 768pxlg: 1024pxxl: 1280px2xl: 1536px
🎯 Performance
- Code splitting: Automatic with Next.js App Router
- Image optimization: Using Next.js
<Image>component - React Query caching: Automatic caching of API responses
- Bundle analysis:
npm run buildshows bundle sizes
🌐 Environment Variables
# API
NEXT_PUBLIC_API_URL=http://localhost:4000
NEXT_PUBLIC_API_PREFIX=api/v1
# Auth (NextAuth)
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-secret
# OAuth
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
Note: Variables prefixed with NEXT_PUBLIC_ are exposed to the browser.
📖 Further Reading
🤝 Contributing
- Follow React/Next.js best practices
- Use TypeScript strict mode
- Write tests for components
- Ensure accessibility (WCAG 2.1 AA)
- Format with Prettier
- Lint with ESLint
📝 License
Proprietary - All rights reserved
Built with ❤️ using Next.js 14 and React 18