'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, palletCount, hasDangerousGoods: searchParams.get('hasDangerousGoods') === 'true', requiresSpecialHandling: searchParams.get('requiresSpecialHandling') === 'true', requiresTailgate: searchParams.get('requiresTailgate') === 'true', requiresStraps: searchParams.get('requiresStraps') === 'true', requiresThermalCover: searchParams.get('requiresThermalCover') === 'true', hasRegulatedProducts: searchParams.get('hasRegulatedProducts') === 'true', requiresAppointment: searchParams.get('requiresAppointment') === '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.priceEUR - b.priceEUR); const fastest = [...results].sort((a, b) => a.transitDays - 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.priceEUR)}

{t('carrier')} {card.option.companyName}
{t('transit')} {t('transitDays', { days: 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.priceEUR)}

{t('totalPrice')}

{t('priceBreakdown.base')}

{formatPrice(result.priceBreakdown.basePrice)}

{t('priceBreakdown.volume')}

{formatPrice(result.priceBreakdown.volumeCharge)}

{t('priceBreakdown.weight')}

{formatPrice(result.priceBreakdown.weightCharge)}

{t('priceBreakdown.transit')}

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

{t('validUntil', { date: new Date(result.validUntil).toLocaleDateString(dateLocale) })} {result.hasSurcharges && ( {t('surcharges')} )}
))}
); }