'use client'; import { useState, useEffect } from 'react'; import { getAllBookings, validateBankTransfer, deleteAdminBooking } from '@/lib/api/admin'; interface Booking { id: string; bookingNumber?: string | null; type?: string; status: string; origin?: string; destination?: string; carrierName?: string; containerType: string; volumeCBM?: number; weightKG?: number; palletCount?: number; priceEUR?: number; priceUSD?: number; primaryCurrency?: string; createdAt?: string; requestedAt?: string; updatedAt?: string; organizationId?: string; userId?: string; } export default function AdminBookingsPage() { const [bookings, setBookings] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [filterStatus, setFilterStatus] = useState('all'); const [searchTerm, setSearchTerm] = useState(''); const [validatingId, setValidatingId] = useState(null); const [deletingId, setDeletingId] = useState(null); const [openMenuId, setOpenMenuId] = useState(null); const [menuPosition, setMenuPosition] = useState<{ top: number; left: number } | null>(null); const [selectedBooking, setSelectedBooking] = useState(null); const [showDetailsModal, setShowDetailsModal] = useState(false); useEffect(() => { fetchBookings(); }, []); const handleDeleteBooking = async (bookingId: string) => { if (!window.confirm('Supprimer définitivement cette réservation ?')) return; setDeletingId(bookingId); try { await deleteAdminBooking(bookingId); setBookings(prev => prev.filter(b => b.id !== bookingId)); } catch (err: any) { setError(err.message || 'Erreur lors de la suppression'); } finally { setDeletingId(null); } }; const handleValidateTransfer = async (bookingId: string) => { if (!window.confirm('Confirmer la réception du virement et activer ce booking ?')) return; setValidatingId(bookingId); try { await validateBankTransfer(bookingId); await fetchBookings(); } catch (err: any) { setError(err.message || 'Erreur lors de la validation du virement'); } finally { setValidatingId(null); } }; const fetchBookings = async () => { try { setLoading(true); const response = await getAllBookings(); setBookings(response.bookings || []); setError(null); } catch (err: any) { setError(err.message || 'Impossible de charger les réservations'); } finally { setLoading(false); } }; const getStatusColor = (status: string) => { const colors: Record = { pending_payment: 'bg-orange-100 text-orange-800', pending_bank_transfer: 'bg-amber-100 text-amber-900', pending: 'bg-yellow-100 text-yellow-800', accepted: 'bg-green-100 text-green-800', rejected: 'bg-red-100 text-red-800', cancelled: 'bg-red-100 text-red-800', }; return colors[status.toLowerCase()] || 'bg-gray-100 text-gray-800'; }; const getStatusLabel = (status: string) => { const labels: Record = { PENDING_PAYMENT: 'Paiement en attente', PENDING_BANK_TRANSFER: 'Virement à valider', PENDING: 'En attente transporteur', ACCEPTED: 'Accepté', REJECTED: 'Rejeté', CANCELLED: 'Annulé', }; return labels[status.toUpperCase()] || status; }; const getShortId = (booking: Booking) => `#${booking.id.slice(0, 8).toUpperCase()}`; const filteredBookings = bookings .filter(booking => filterStatus === 'all' || booking.status.toLowerCase() === filterStatus) .filter(booking => { if (searchTerm === '') return true; const s = searchTerm.toLowerCase(); return ( booking.bookingNumber?.toLowerCase().includes(s) || booking.id.toLowerCase().includes(s) || booking.carrierName?.toLowerCase().includes(s) || booking.origin?.toLowerCase().includes(s) || booking.destination?.toLowerCase().includes(s) || String(booking.palletCount || '').includes(s) || String(booking.weightKG || '').includes(s) || String(booking.volumeCBM || '').includes(s) || booking.containerType?.toLowerCase().includes(s) ); }); if (loading) { return (

Chargement des réservations...

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

Gestion des réservations

Toutes les réservations de la plateforme

{/* Stats Cards */}
Total
{bookings.length}
Virements à valider
{bookings.filter(b => b.status.toUpperCase() === 'PENDING_BANK_TRANSFER').length}
En attente transporteur
{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}
{/* 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 text-sm" />
{/* Error Message */} {error && (
{error}
)} {/* Bookings Table */}
{filteredBookings.length === 0 ? ( ) : ( filteredBookings.map(booking => ( {/* N° Booking */} {/* Route */} {/* Cargo */} {/* Transporteur */} {/* Statut */} {/* Date */} {/* Actions */} )) )}
N° Booking Route Cargo Transporteur Statut Date Actions
Aucune réservation trouvée
{booking.bookingNumber && (
{booking.bookingNumber}
)}
{getShortId(booking)}
{booking.origin} → {booking.destination}
{booking.containerType} {booking.palletCount != null && ( · {booking.palletCount} pal. )}
{booking.weightKG != null && {booking.weightKG.toLocaleString()} kg} {booking.volumeCBM != null && {booking.volumeCBM} CBM}
{booking.carrierName || '—'} {getStatusLabel(booking.status)} {new Date(booking.requestedAt || booking.createdAt || '').toLocaleDateString('fr-FR')}
{/* Actions Dropdown Menu */} {openMenuId && menuPosition && ( <>
{ setOpenMenuId(null); setMenuPosition(null); }} />
{(() => { const booking = bookings.find(b => b.id === openMenuId); return booking?.status.toUpperCase() === 'PENDING_BANK_TRANSFER' ? ( ) : null; })()}
)} {/* Details Modal */} {showDetailsModal && selectedBooking && (

Détails de la réservation

{selectedBooking.bookingNumber || getShortId(selectedBooking)}
{getStatusLabel(selectedBooking.status)}

Route

{selectedBooking.origin || '—'}
{selectedBooking.destination || '—'}

Cargo & Transporteur

{selectedBooking.carrierName || '—'}
{selectedBooking.containerType}
{selectedBooking.palletCount != null && (
{selectedBooking.palletCount}
)} {selectedBooking.weightKG != null && (
{selectedBooking.weightKG.toLocaleString()} kg
)} {selectedBooking.volumeCBM != null && (
{selectedBooking.volumeCBM} CBM
)}
{(selectedBooking.priceEUR != null || selectedBooking.priceUSD != null) && (

Prix

{selectedBooking.priceEUR != null && (
{selectedBooking.priceEUR.toLocaleString()} €
)} {selectedBooking.priceUSD != null && (
{selectedBooking.priceUSD.toLocaleString()} $
)}
)}

Dates

{new Date(selectedBooking.requestedAt || selectedBooking.createdAt || '').toLocaleString('fr-FR')}
{selectedBooking.updatedAt && (
{new Date(selectedBooking.updatedAt).toLocaleString('fr-FR')}
)}
{selectedBooking.status.toUpperCase() === 'PENDING_BANK_TRANSFER' && (
)}
)}
); }