'use client'; import { useState, useEffect } from 'react'; import { useTranslations, useLocale } from 'next-intl'; 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 t = useTranslations('dashboard.admin.bookings'); const locale = useLocale(); const dateLocale = locale === 'fr' ? 'fr-FR' : 'en-US'; 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(t('confirmDelete'))) return; setDeletingId(bookingId); try { await deleteAdminBooking(bookingId); setBookings(prev => prev.filter(b => b.id !== bookingId)); } catch (err: any) { setError(err.message || t('deleteError')); } finally { setDeletingId(null); } }; const handleValidateTransfer = async (bookingId: string) => { if (!window.confirm(t('confirmValidate'))) return; setValidatingId(bookingId); try { await validateBankTransfer(bookingId); await fetchBookings(); } catch (err: any) { setError(err.message || t('validateError')); } finally { setValidatingId(null); } }; const fetchBookings = async () => { try { setLoading(true); const response = await getAllBookings(); setBookings(response.bookings || []); setError(null); } catch (err: any) { setError(err.message || t('loadError')); } 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 key = status.toUpperCase(); const allowed = ['PENDING_PAYMENT', 'PENDING_BANK_TRANSFER', 'PENDING', 'ACCEPTED', 'REJECTED', 'CANCELLED']; if (allowed.includes(key)) { return t(`status.${key}` as any); } return 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 (

{t('loading')}

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

{t('title')}

{t('subtitle')}

{/* Stats Cards */}
{t('stats.total')}
{bookings.length}
{t('stats.pendingBankTransfer')}
{bookings.filter(b => b.status.toUpperCase() === 'PENDING_BANK_TRANSFER').length}
{t('stats.pendingCarrier')}
{bookings.filter(b => b.status.toUpperCase() === 'PENDING').length}
{t('stats.accepted')}
{bookings.filter(b => b.status.toUpperCase() === 'ACCEPTED').length}
{t('stats.rejected')}
{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 */} )) )}
{t('table.bookingNumber')} {t('table.route')} {t('table.cargo')} {t('table.carrier')} {t('table.status')} {t('table.date')} {t('table.actions')}
{t('table.empty')}
{booking.bookingNumber && (
{booking.bookingNumber}
)}
{getShortId(booking)}
{booking.origin} → {booking.destination}
{booking.containerType} {booking.palletCount != null && ( · {booking.palletCount} {t('table.pallets')} )}
{booking.weightKG != null && {booking.weightKG.toLocaleString(dateLocale)} kg} {booking.volumeCBM != null && {booking.volumeCBM} CBM}
{booking.carrierName || '—'} {getStatusLabel(booking.status)} {new Date(booking.requestedAt || booking.createdAt || '').toLocaleDateString(dateLocale)}
{/* 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 && (

{t('modal.title')}

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

{t('modal.routeSection')}

{selectedBooking.origin || t('modal.none')}
{selectedBooking.destination || t('modal.none')}

{t('modal.cargoSection')}

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

{t('modal.priceSection')}

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

{t('modal.datesSection')}

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