'use client'; import { useState, useEffect } from 'react'; import { getAllBookings } from '@/lib/api/admin'; interface Booking { id: string; bookingNumber?: string; bookingId?: string; type?: string; status: string; // CSV bookings use these fields origin?: string; destination?: string; carrierName?: string; // Regular bookings use these fields originPort?: { code: string; name: string; }; destinationPort?: { code: string; name: string; }; carrier?: string; containerType: string; quantity?: number; price?: number; primaryCurrency?: string; totalPrice?: { amount: number; currency: string; }; createdAt?: string; updatedAt?: string; requestedAt?: string; organizationId: string; userId: string; } export default function AdminBookingsPage() { const [bookings, setBookings] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selectedBooking, setSelectedBooking] = useState(null); const [showDetailsModal, setShowDetailsModal] = useState(false); const [filterStatus, setFilterStatus] = useState('all'); const [searchTerm, setSearchTerm] = useState(''); // Helper function to get formatted quote number const getQuoteNumber = (booking: Booking): string => { if (booking.type === 'csv') { return `#${booking.bookingId || booking.id.slice(0, 8).toUpperCase()}`; } return booking.bookingNumber || `#${booking.id.slice(0, 8).toUpperCase()}`; }; useEffect(() => { fetchBookings(); }, []); const fetchBookings = async () => { try { setLoading(true); const response = await getAllBookings(); setBookings(response.bookings || []); setError(null); } catch (err: any) { setError(err.message || 'Failed to load bookings'); } finally { setLoading(false); } }; const getStatusColor = (status: string) => { const colors: Record = { draft: 'bg-gray-100 text-gray-800', pending: 'bg-yellow-100 text-yellow-800', confirmed: 'bg-blue-100 text-blue-800', in_transit: 'bg-purple-100 text-purple-800', delivered: 'bg-green-100 text-green-800', cancelled: 'bg-red-100 text-red-800', }; return colors[status.toLowerCase()] || 'bg-gray-100 text-gray-800'; }; const filteredBookings = bookings .filter(booking => filterStatus === 'all' || booking.status.toLowerCase() === filterStatus) .filter(booking => { if (searchTerm === '') return true; const searchLower = searchTerm.toLowerCase(); const quoteNumber = getQuoteNumber(booking).toLowerCase(); return ( quoteNumber.includes(searchLower) || booking.bookingNumber?.toLowerCase().includes(searchLower) || booking.carrier?.toLowerCase().includes(searchLower) || booking.carrierName?.toLowerCase().includes(searchLower) || booking.origin?.toLowerCase().includes(searchLower) || booking.destination?.toLowerCase().includes(searchLower) ); }); if (loading) { return (

Loading bookings...

); } return (
{/* Header */}

Booking Management

View and manage all bookings across the platform

{/* Filters */}
setSearchTerm(e.target.value)} className="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:border-blue-500 focus:ring-blue-500 focus:outline-none" />
{/* Stats Cards */}
Total Réservations
{bookings.length}
En Attente
{bookings.filter(b => b.status.toUpperCase() === 'PENDING').length}
Acceptées
{bookings.filter(b => b.status.toUpperCase() === 'ACCEPTED').length}
Rejetées
{bookings.filter(b => b.status.toUpperCase() === 'REJECTED').length}
{/* Error Message */} {error && (
{error}
)} {/* Bookings Table */}
{filteredBookings.map(booking => ( ))}
Numéro de devis Route Transporteur Conteneur Statut Prix Actions
{getQuoteNumber(booking)}
{new Date(booking.createdAt || booking.requestedAt || '').toLocaleDateString()}
{booking.originPort ? `${booking.originPort.code} → ${booking.destinationPort?.code}` : `${booking.origin} → ${booking.destination}`}
{booking.originPort ? `${booking.originPort.name} → ${booking.destinationPort?.name}` : ''}
{booking.carrier || booking.carrierName || 'N/A'}
{booking.containerType}
{booking.quantity ? `Qty: ${booking.quantity}` : ''}
{booking.status} {booking.totalPrice ? `${booking.totalPrice.amount.toLocaleString()} ${booking.totalPrice.currency}` : booking.price ? `${booking.price.toLocaleString()} ${booking.primaryCurrency || 'USD'}` : 'N/A' }
{/* Details Modal */} {showDetailsModal && selectedBooking && (

Booking Details

{getQuoteNumber(selectedBooking)}
{selectedBooking.status}

Route Information

{selectedBooking.originPort ? ( <>
{selectedBooking.originPort.code}
{selectedBooking.originPort.name}
) : (
{selectedBooking.origin}
)}
{selectedBooking.destinationPort ? ( <>
{selectedBooking.destinationPort.code}
{selectedBooking.destinationPort.name}
) : (
{selectedBooking.destination}
)}

Shipping Details

{selectedBooking.carrier || selectedBooking.carrierName || 'N/A'}
{selectedBooking.containerType}
{selectedBooking.quantity && (
{selectedBooking.quantity}
)}

Pricing

{selectedBooking.totalPrice ? `${selectedBooking.totalPrice.amount.toLocaleString()} ${selectedBooking.totalPrice.currency}` : selectedBooking.price ? `${selectedBooking.price.toLocaleString()} ${selectedBooking.primaryCurrency || 'USD'}` : 'N/A' }

Timeline

{new Date(selectedBooking.createdAt || selectedBooking.requestedAt || '').toLocaleString()}
{selectedBooking.updatedAt && (
{new Date(selectedBooking.updatedAt).toLocaleString()}
)}
)}
); }