'use client'; import { useEffect, useState, useCallback } from 'react'; import { useSearchParams } from 'next/navigation'; import { useRouter } from '@/i18n/navigation'; import { useTranslations, useLocale } from 'next-intl'; import { searchCsvRatesWithOffers } from '@/lib/api/rates'; import type { CsvRateSearchResult } from '@/types/rates'; import { Search, Lightbulb, DollarSign, Scale, Zap, Trophy, XCircle, AlertTriangle, } from 'lucide-react'; interface BestOptions { eco: CsvRateSearchResult; standard: CsvRateSearchResult; fast: CsvRateSearchResult; } export default function SearchResultsPage() { const t = useTranslations('dashboard.rateSearch.results'); const locale = useLocale(); const dateLocale = locale === 'fr' ? 'fr-FR' : 'en-US'; const router = useRouter(); const searchParams = useSearchParams(); const [results, setResults] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const origin = searchParams.get('origin') || ''; const destination = searchParams.get('destination') || ''; const volumeCBM = parseFloat(searchParams.get('volumeCBM') || '0'); const weightKG = parseFloat(searchParams.get('weightKG') || '0'); const palletCount = parseInt(searchParams.get('palletCount') || '0'); const performSearch = useCallback(async () => { setIsLoading(true); setError(null); try { const response = await searchCsvRatesWithOffers({ origin, destination, volumeCBM, weightKG, hasDangerousGoods: searchParams.get('hasDangerousGoods') === 'true', }); setResults(response.results); } catch (err) { console.error('Search error:', err); setError(err instanceof Error ? err.message : t('errorGeneric')); } finally { setIsLoading(false); } }, [origin, destination, volumeCBM, weightKG, palletCount, searchParams, t]); useEffect(() => { if (!origin || !destination || !volumeCBM || !weightKG) { router.push('/dashboard/search-advanced'); return; } performSearch(); }, [origin, destination, volumeCBM, weightKG, performSearch, router]); const getBestOptions = (): BestOptions | null => { if (results.length === 0) return null; const economic = results.find(r => r.serviceLevel === 'ECONOMIC'); const standard = results.find(r => r.serviceLevel === 'STANDARD'); const rapid = results.find(r => r.serviceLevel === 'RAPID'); if (economic && standard && rapid) { return { eco: economic, standard: standard, fast: rapid, }; } const sorted = [...results].sort( (a, b) => a.priceBreakdown.totalPriceForSorting - b.priceBreakdown.totalPriceForSorting ); const fastest = [...results].sort( (a, b) => (a.adjustedTransitDays ?? a.transitDays) - (b.adjustedTransitDays ?? b.transitDays) ); return { eco: sorted[0], standard: sorted[Math.floor(sorted.length / 2)] || sorted[0], fast: fastest[0], }; }; const bestOptions = getBestOptions(); const formatPrice = (price: number) => { return new Intl.NumberFormat(dateLocale, { style: 'currency', currency: 'EUR', }).format(price); }; if (isLoading) { return (

{t('loadingTitle')}

{origin} → {destination}

); } if (error) { return (

{t('errorTitle')}

{error}

); } if (results.length === 0) { return (

{t('noResultsTitle')}

{t('noResultsMessage', { origin, destination })}

{t('suggestions')}

  • {t('suggestionPorts')}
  • {t('suggestionVolume')}
  • {t('suggestionWeight')}
); } const optionCards = [ { type: t('options.economic'), option: bestOptions?.eco, colors: { border: 'border-green-200', bg: 'bg-green-50', text: 'text-green-800', button: 'bg-green-600 hover:bg-green-700', }, icon: , badge: t('options.badgeCheapest'), }, { type: t('options.standard'), option: bestOptions?.standard, colors: { border: 'border-blue-200', bg: 'bg-blue-50', text: 'text-blue-800', button: 'bg-blue-600 hover:bg-blue-700', }, icon: , badge: t('options.badgeBalanced'), }, { type: t('options.fast'), option: bestOptions?.fast, colors: { border: 'border-purple-200', bg: 'bg-purple-50', text: 'text-purple-800', button: 'bg-purple-600 hover:bg-purple-700', }, icon: , badge: t('options.badgeFastest'), }, ]; return (
{/* Header */}

{t('resultsTitle')}

{origin} →{' '} {destination} •{' '} {palletCount > 0 ? t('summaryWithPallets', { volume: volumeCBM, weight: weightKG, count: palletCount, }) : t('summary', { volume: volumeCBM, weight: weightKG })}

{t('ratesFound')}

{results.length}

{/* Best Options */} {bestOptions && (

{t('bestChoices')}

{optionCards.map(card => { if (!card.option) return null; return (
{card.icon}

{card.type}

{card.badge}

{t('totalPrice')}

{formatPrice(card.option.priceBreakdown.totalPriceForSorting)}

{t('carrier')} {card.option.companyName}
{t('transit')} {t('transitDays', { days: card.option.adjustedTransitDays ?? card.option.transitDays, })}
{t('type')} {card.option.containerType}
); })}
)} {/* All Results */}

{t('allResults', { count: results.length })}

{results.map((result, index) => (

{result.companyName}

{result.origin} → {result.destination} • {result.containerType}

{formatPrice(result.priceBreakdown.totalPriceForSorting)}

{t('totalPrice')}

Fret ({result.priceBreakdown.freightCurrency})

{formatPrice(result.priceBreakdown.totalFreight)}

FOB ({result.priceBreakdown.fobCurrency})

{formatPrice(result.priceBreakdown.totalFob)}

Routage

{result.routing}

{t('priceBreakdown.transit')}

{t('transitDays', { days: result.adjustedTransitDays ?? result.transitDays })}

{t('validUntil', { date: new Date(result.validUntil).toLocaleDateString(dateLocale), })} {result.dgSurchargeStatus === 'not_accepted' && ( DG non accepté )} {result.dgSurchargeStatus === 'on_request' && ( DG sur demande )}
))}
); }