import { useEffect, useMemo, useState } from 'react'; import { Link, useOutletContext, useParams } from 'react-router-dom'; import { ArrowLeft } from 'lucide-react'; import DateRangePicker from '../components/DateRangePicker'; import PaginationControls from '../components/PaginationControls'; import { fetchSellerDetailsAnalytics } from '../dataService'; import { formatDisplayName, removeTrailingSellerId } from '../displayFormatters'; import type { DateRange, SellerDetailsAnalytics } from '../types'; const formatNumber = (value: number) => new Intl.NumberFormat('pt-BR', { maximumFractionDigits: 0 }).format(value); const formatCurrency = (value: number) => new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(value); const SellerDetailsSkeleton = () => (
{[1, 2, 3, 4].map(item =>
)}
{[1, 2, 3, 4, 5, 6].map(item =>
)}
{[1, 2, 3].map(item =>
)}
{[1, 2].map(item =>
{[1, 2, 3, 4].map(row =>
)}
)}
); const SellerDetails = () => { const { sellerId = '' } = useParams<{ sellerId: string }>(); const { dateRange, setDateRange } = useOutletContext<{ dateRange: DateRange; setDateRange: (range: DateRange) => void }>(); const [details, setDetails] = useState(null); const [isLoading, setIsLoading] = useState(true); const [trendPage, setTrendPage] = useState(1); const trendPageSize = 14; useEffect(() => { let isMounted = true; const load = async () => { setIsLoading(true); const result = await fetchSellerDetailsAnalytics(sellerId, dateRange); if (isMounted) { setDetails(result); setIsLoading(false); } }; void load(); return () => { isMounted = false; }; }, [dateRange, sellerId]); const maxRevenue = useMemo(() => Math.max(...(details?.chartData.map(item => item.revenue) || [1]), 1), [details]); const trendTotalPages = Math.ceil((details?.chartData.length || 0) / trendPageSize); const safeTrendPage = Math.min(trendPage, trendTotalPages || 1); const trendStartIndex = (safeTrendPage - 1) * trendPageSize; const paginatedTrend = details?.chartData.slice(trendStartIndex, trendStartIndex + trendPageSize) || []; if (isLoading && !details) return ; if (!details) return

Vendedor não encontrado no período.

Voltar para vendedores
; const { seller } = details; return (
Vendedores

{formatDisplayName(removeTrailingSellerId(seller.name))}

Carteira, produtos e resultado comercial no período selecionado.

{ setDateRange(range); setTrendPage(1); }} />
{[['Receita', formatCurrency(seller.revenue), 'text-brand-primary'], ['Pedidos', formatNumber(seller.orderCount), 'text-dark-text'], ['Clientes', formatNumber(seller.customerCount), 'text-dark-text'], ['Ticket médio', formatCurrency(seller.averageTicket), 'text-dark-text']].map(([label, value, color]) =>

{label}

{value}

)}

Evolução da receita

Vendas por dia no período.

{details.chartData.length ? <>
{paginatedTrend.map(point =>
{new Date(`${point.date}T12:00:00`).toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit' })}
{formatCurrency(point.revenue)}
)}
setTrendPage(1)} className="border-t border-dark-border px-4 py-3" /> :

Sem vendas no período.

}

Canais

Receita por marketplace.

{details.marketplaces.map(item =>

{item.name}

{formatCurrency(item.revenue)} · {formatNumber(item.orderCount)} pedidos

)}

Produtos mais vendidos

{details.topProducts.map(product =>

{product.name}

{formatNumber(product.quantitySold)} un. vendidas

{formatCurrency(product.revenue)})}

Carteira no período

{details.topClients.map(client =>

{client.name}

{formatNumber(client.orderCount)} pedidos

{formatCurrency(client.totalSpent)})}
); }; export default SellerDetails;