'use client'; import { useEffect } from 'react'; import { useQuery } from '@tanstack/react-query'; import { dashboardApi } from '@/lib/api'; import { Link, useRouter } from '@/i18n/navigation'; import { useTranslations, useLocale } from 'next-intl'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Package, PackageCheck, PackageX, Clock, Weight, TrendingUp, Plus, ArrowRight, } from 'lucide-react'; import { useSubscription } from '@/lib/context/subscription-context'; import ExportButton from '@/components/ExportButton'; import { PieChart, Pie, Cell, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, } from 'recharts'; export default function DashboardPage() { const router = useRouter(); const { hasFeature, loading: subLoading } = useSubscription(); const t = useTranslations('dashboard.home'); const locale = useLocale(); useEffect(() => { if (!subLoading && !hasFeature('dashboard')) { router.replace('/dashboard/bookings'); } }, [subLoading, hasFeature, router]); const { data: csvKpis, isLoading: csvKpisLoading } = useQuery({ queryKey: ['dashboard', 'csv-booking-kpis'], queryFn: () => dashboardApi.getCsvBookingKPIs(), }); const { data: topCarriers, isLoading: carriersLoading } = useQuery({ queryKey: ['dashboard', 'top-carriers'], queryFn: () => dashboardApi.getTopCarriers(), }); const numberFormat = new Intl.NumberFormat(locale === 'fr' ? 'fr-FR' : 'en-US'); const statusDistribution = csvKpis ? [ { name: t('charts.distribution.accepted'), value: csvKpis.totalAccepted, color: '#10b981' }, { name: t('charts.distribution.rejected'), value: csvKpis.totalRejected, color: '#ef4444' }, { name: t('charts.distribution.pending'), value: csvKpis.totalPending, color: '#f59e0b' }, ] : []; const carrierWeightData = topCarriers ? topCarriers.slice(0, 5).map(c => ({ name: c.carrierName.length > 15 ? c.carrierName.substring(0, 15) + '...' : c.carrierName, [t('charts.weightByCarrier.weight')]: Math.round(c.totalWeightKG), })) : []; const weightDataKey = t('charts.weightByCarrier.weight'); return (

{t('title')}

{t('subtitle')}

v?.toLocaleString(locale === 'fr' ? 'fr-FR' : 'en-US') || '0', }, { key: 'totalVolumeCBM', label: t('export.totalVolume'), format: v => v?.toFixed(2) || '0', }, { key: 'acceptanceRate', label: t('export.acceptanceRate'), format: v => v?.toFixed(1) || '0', }, { key: 'avgPriceUSD', label: t('export.avgPrice'), format: v => v?.toFixed(2) || '0', }, ]} />

{t('kpi.accepted')}

{csvKpisLoading ? (
) : ( <>

{csvKpis?.totalAccepted || 0}

{t('kpi.thisMonth', { count: csvKpis?.acceptedThisMonth || 0 })}

)}

{t('kpi.rejected')}

{csvKpisLoading ? (
) : ( <>

{csvKpis?.totalRejected || 0}

{t('kpi.thisMonth', { count: csvKpis?.rejectedThisMonth || 0 })}

)}

{t('kpi.pending')}

{csvKpisLoading ? (
) : ( <>

{csvKpis?.totalPending || 0}

{t('kpi.acceptanceRate', { rate: (csvKpis?.acceptanceRate ?? 0).toFixed(1) })}

)}

{t('kpi.totalWeight')}

{csvKpisLoading ? (
) : ( <>

{numberFormat.format(csvKpis?.totalWeightAcceptedKG || 0)}

KG • {(csvKpis?.totalVolumeAcceptedCBM || 0).toFixed(1)} CBM

)}
{t('charts.distribution.title')} {t('charts.distribution.description')} {csvKpisLoading ? (
) : ( `${name} ${((percent || 0) * 100).toFixed(0)}%` } outerRadius={70} fill="#8884d8" dataKey="value" > {statusDistribution.map((entry, index) => ( ))} )} {t('charts.weightByCarrier.title')} {t('charts.weightByCarrier.description')} {carriersLoading ? (
) : ( )}

{t('performance.acceptanceRate')}

{csvKpisLoading ? '--' : `${(csvKpis?.acceptanceRate ?? 0).toFixed(1)}%`}

{t('performance.totalBookings')}

{csvKpisLoading ? '--' : (csvKpis?.totalAccepted || 0) + (csvKpis?.totalRejected || 0) + (csvKpis?.totalPending || 0)}

{t('performance.totalVolume')}

{csvKpisLoading ? '--' : `${(csvKpis?.totalVolumeAcceptedCBM || 0).toFixed(1)}`} CBM

{t('topCarriers.title')} {t('topCarriers.description')}
{carriersLoading ? (
{Array.from({ length: 3 }).map((_, i) => (
))}
) : topCarriers && topCarriers.length > 0 ? (
{topCarriers.slice(0, 5).map((carrier, index) => (
{index + 1}

{carrier.carrierName}

{t('topCarriers.bookingsCount', { count: carrier.totalBookings })} {numberFormat.format(carrier.totalWeightKG)} KG
{carrier.acceptedBookings} ✓ {carrier.rejectedBookings > 0 && ( {carrier.rejectedBookings} ✗ )}

{carrier.acceptanceRate.toFixed(0)}% • ${carrier.avgPriceUSD.toFixed(0)}

))}
) : (

{t('topCarriers.empty.title')}

{t('topCarriers.empty.description')}

)}
); }