xpeditis2.0/apps/frontend
David 2054e73e78 fix: resolve profile page data persistence and password change issues
Fixed critical issues with the profile page (/dashboard/profile):

1. **Form data not persisting on page refresh**:
   - Added useEffect to update form values when user data loads
   - Forms now properly populate after auth context loads user data

2. **Blank page on refresh**:
   - Added loading and error states for better UX
   - Handle case where user is not loaded yet (loading spinner)
   - Handle case where user fails to load (retry button)

3. **Password change API endpoint correction**:
   - Fixed: POST /api/v1/users/change-password (incorrect)
   - Corrected to: PATCH /api/v1/users/me/password (matches backend)
   - Updated return type to include { message: string }

The root cause was that useForm defaultValues were set once at
component mount when user was still null. The form never updated
when user data was subsequently loaded by the auth context.

Now the form properly resets with user data via useEffect, and
proper loading/error states prevent showing a blank page.

Refs: apps/frontend/app/dashboard/profile/page.tsx:68-78

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-12 18:18:04 +01:00
..
app fix: resolve profile page data persistence and password change issues 2026-01-12 18:18:04 +01:00
e2e feature 2025-11-04 07:30:15 +01:00
lib fix: resolve profile page data persistence and password change issues 2026-01-12 18:18:04 +01:00
public fix icon 2025-12-23 19:14:13 +01:00
src fix: implement password change functionality in profile page 2026-01-12 17:56:10 +01: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 landing page , login , register 2025-10-31 12:38:05 +01: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
LOGIN_PAGE_COMPLETE.md fix landing page , login , register 2025-10-31 12:38:05 +01:00
middleware.ts feature 2025-11-04 07:30:15 +01:00
next.config.js fix landing page , login , register 2025-10-31 12:38:05 +01:00
package-lock.json fix carte 2025-12-03 22:24:48 +01:00
package.json fix carte 2025-12-03 22:24:48 +01: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 feature 2025-11-04 07:30:15 +01:00
tsconfig.json fix 2025-11-12 19:08:35 +01: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