xpeditis2.0/apps/frontend
David 76d940d73b feat: ajouter l'onglet Historique des devis et remplacer le statut Paiement en attente
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
2026-09-14 11:43:57 +02:00
..
app feat: ajouter l'onglet Historique des devis et remplacer le statut Paiement en attente 2026-09-14 11:43:57 +02:00
e2e fix test 2026-04-04 14:18:41 +02:00
i18n fix blog 2026-05-12 21:01:52 +02:00
lib fix blog 2026-05-12 21:01:52 +02:00
messages feat: ajouter l'onglet Historique des devis et remplacer le statut Paiement en attente 2026-09-14 11:43:57 +02:00
public fix video and landing page 2026-09-01 17:19:01 +02:00
src feat: ajouter l'onglet Historique des devis et remplacer le statut Paiement en attente 2026-09-14 11:43:57 +02:00
.dockerignore fix: enable Tailwind CSS compilation in Docker builds 2025-11-19 13:39:05 +01:00
.env.example feat: add Xpeditis logo as favicon and improve metadata 2025-12-23 13:29:45 +01:00
.eslintrc.json fix 2025-11-12 19:35:13 +01:00
.gitignore first commit 2025-10-07 18:39:32 +02:00
DESIGN_QUICK_START.md fix landing page , login , register 2025-10-31 12:38:05 +01:00
DESIGN_SYSTEM.md fix ui update 2026-08-13 12:26:46 +02:00
Dockerfile feat: Docker multi-stage builds + CI/CD automation for production deployment 2025-10-15 12:15:59 +02:00
FRONTEND_API_CONNECTION_COMPLETE.md add front api connection 2025-10-30 00:47:18 +01:00
IMPLEMENTATION_COMPLETE.md fix landing page , login , register 2025-10-31 12:38:05 +01:00
jest.config.js chore(frontend): ordonner les alias @/i18n avant la regle generique 2026-09-07 21:40:49 +02:00
jest.setup.ts fix test 2026-04-04 15:08:53 +02:00
LOGIN_PAGE_COMPLETE.md fix landing page , login , register 2025-10-31 12:38:05 +01:00
middleware.ts fix admin page 2026-06-13 11:53:27 +02:00
next.config.js fix language 2026-04-21 18:04:02 +02:00
package-lock.json fix ui update 2026-08-13 12:26:46 +02:00
package.json fix ui update 2026-08-13 12:26:46 +02:00
playwright.config.ts feat: Phase 4 - Production-ready security, monitoring & testing infrastructure 2025-10-14 18:46:18 +02:00
postcss.config.js first commit 2025-10-07 18:39:32 +02:00
README.md fix landing page , login , register 2025-10-31 12:38:05 +01:00
tailwind.config.ts fix design 2026-08-13 17:43:11 +02:00
tsconfig.json chore(frontend): ordonner les alias @/i18n avant la regle generique 2026-09-07 21:40:49 +02:00
tsconfig.test.json fix types check 2026-04-04 15:28:13 +02:00

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 production
  • npm run start - Start production server
  • npm run lint - Lint code
  • npm test - Run tests
  • npm run test:watch - Run tests in watch mode
  • npm 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: 640px
  • md: 768px
  • lg: 1024px
  • xl: 1280px
  • 2xl: 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 build shows 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

  1. Follow React/Next.js best practices
  2. Use TypeScript strict mode
  3. Write tests for components
  4. Ensure accessibility (WCAG 2.1 AA)
  5. Format with Prettier
  6. Lint with ESLint

📝 License

Proprietary - All rights reserved


Built with ❤️ using Next.js 14 and React 18