/** * Rate Results Table Component * * Displays search results in a table format * Shows CSV/API source, prices, transit time, and surcharge details */ 'use client'; import { useState } from 'react'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog'; import { ArrowUpDown, Info } from 'lucide-react'; import type { CsvRateResult } from '@/types/rate-filters'; interface RateResultsTableProps { results: CsvRateResult[]; currency?: 'USD' | 'EUR'; onBooking?: (result: CsvRateResult) => void; } type SortField = 'price' | 'transit' | 'company' | 'matchScore'; type SortOrder = 'asc' | 'desc'; export function RateResultsTable({ results, currency = 'USD', onBooking }: RateResultsTableProps) { const [sortField, setSortField] = useState('price'); const [sortOrder, setSortOrder] = useState('asc'); const handleSort = (field: SortField) => { if (sortField === field) { setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc'); } else { setSortField(field); setSortOrder('asc'); } }; const sortedResults = [...results].sort((a, b) => { let aValue: number | string; let bValue: number | string; switch (sortField) { case 'price': aValue = currency === 'USD' ? a.priceUSD : a.priceEUR; bValue = currency === 'USD' ? b.priceUSD : b.priceEUR; break; case 'transit': aValue = a.transitDays; bValue = b.transitDays; break; case 'company': aValue = a.companyName; bValue = b.companyName; break; case 'matchScore': aValue = a.matchScore; bValue = b.matchScore; break; default: return 0; } if (sortOrder === 'asc') { return aValue > bValue ? 1 : -1; } else { return aValue < bValue ? 1 : -1; } }); const formatPrice = (priceUSD: number, priceEUR: number) => { if (currency === 'USD') { return `$${priceUSD.toFixed(2)}`; } else { return `€${priceEUR.toFixed(2)}`; } }; const SortButton = ({ field, label }: { field: SortField; label: string }) => ( ); if (results.length === 0) { return (

Aucun tarif trouvé pour cette recherche.

Essayez d'ajuster vos critères de recherche ou vos filtres.

); } return (
Source Trajet Surcharges Validité Actions {sortedResults.map((result, index) => ( {/* Compagnie */} {result.companyName} {/* Source (CSV/API) */} {result.source} {/* Trajet */}
{result.origin} → {result.destination}
{result.containerType}
{/* Prix */}
{formatPrice(result.priceUSD, result.priceEUR)}
{result.hasSurcharges && (
+ surcharges
)}
{/* Surcharges */} {result.hasSurcharges ? ( Détails des surcharges {result.companyName} - {result.origin} → {result.destination}

{result.surchargeDetails}

) : ( All-in )}
{/* Transit */}
{result.transitDays} jours
{/* Validité */}
Jusqu'au {new Date(result.validUntil).toLocaleDateString('fr-FR')}
{/* Score */}
= 90 ? 'text-green-600' : result.matchScore >= 75 ? 'text-yellow-600' : 'text-gray-600' }`} > {result.matchScore}%
{/* Actions */}
))}
{/* Summary footer */}
{results.length} tarif{results.length > 1 ? 's' : ''} trouvé {results.length > 1 ? 's' : ''}
Prix affichés en {currency}
); }