import { useEffect, useState } from 'react';
import { useParams, Link, useOutletContext } from 'react-router-dom';
import { ArrowLeft, User, Tag, Package, DollarSign, Clock, Phone, ChevronLeft, ChevronRight, ShoppingBag, ReceiptText } from 'lucide-react';
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
import DateRangePicker from '../components/DateRangePicker';
import type { ClientDetailsAnalytics, DateRange } from '../types';
import { fetchClientDetailsAnalytics } from '../dataService';
type CustomTooltipProps = {
active?: boolean;
payload?: Array<{ value: number }>;
label?: string;
};
const CustomTooltip = ({ active, payload, label }: CustomTooltipProps) => {
if (active && payload && payload.length) {
return (
{label}
Gasto: {new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(payload[0].value)}
);
}
return null;
};
const ClientDetails = () => {
const { clientToken } = useParams<{ clientToken: string }>();
const decodedClientToken = clientToken ? decodeURIComponent(clientToken) : '';
const { dateRange, setDateRange } = useOutletContext<{
dateRange: DateRange,
setDateRange: (range: DateRange) => void
}>();
const [details, setDetails] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [currentPage, setCurrentPage] = useState(1);
const [ordersPerPage, setOrdersPerPage] = useState(5);
useEffect(() => {
let isMounted = true;
const loadClientDetails = async () => {
if (!decodedClientToken) {
if (isMounted) {
setDetails(null);
setIsLoading(false);
}
return;
}
setIsLoading(true);
const nextDetails = await fetchClientDetailsAnalytics(decodedClientToken, dateRange);
if (isMounted) {
setDetails(nextDetails);
setIsLoading(false);
}
};
void loadClientDetails();
return () => {
isMounted = false;
};
}, [dateRange, decodedClientToken]);
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(value);
};
const formatNumber = (value: number) => {
return new Intl.NumberFormat('pt-BR').format(value);
};
const handleDateRangeChange = (range: DateRange) => {
setCurrentPage(1);
setDateRange(range);
};
if (isLoading) {
return (
);
}
if (!details?.hasClient) {
return (
Cliente não encontrado.
Voltar para clientes
);
}
const {
chartData,
groupedOrders,
allTimeOrderCount,
clientName,
clientPhone,
periodAverageTicket,
periodItems,
periodOrderCount,
periodSpent
} = details;
const displayName = clientName || 'Cliente';
const totalPages = Math.ceil(groupedOrders.length / ordersPerPage);
const safeCurrentPage = Math.min(currentPage, totalPages || 1);
const startIndex = (safeCurrentPage - 1) * ordersPerPage;
const paginatedOrders = groupedOrders.slice(startIndex, startIndex + ordersPerPage);
return (
{/* Header Area */}
Voltar
{displayName}
{formatNumber(allTimeOrderCount)} pedidos no histórico completo
{clientPhone && (
<>
•
{clientPhone}
>
)}
Gasto no Período
{formatCurrency(periodSpent)}
Ticket no Período
{formatCurrency(periodAverageTicket)}
Total Pedidos
{formatNumber(periodOrderCount)}
Itens no Período
{formatNumber(periodItems)}
Gasto por Data
{chartData.length === 0 ? (
Nenhum gasto no período selecionado.
) : (
formatCurrency(Number(value))} />
} cursor={{ fill: '#222222' }} />
)}
{/* Orders List */}
{paginatedOrders.length === 0 ? (
Nenhum pedido no período selecionado.
Altere o filtro de data para ver outros pedidos deste cliente.
) : paginatedOrders.map((group, groupIndex) => (
Pedido ID: {group.orderId}
Total do Pedido: {formatCurrency(group.orderTotal)}
{group.items.map((order, index) => (
ID: {order.ID_Produto}
{order.Data_Pedido && (
Comprado: {order.Data_Pedido}
)}
{order.Descricao_Produto}
Preço: {formatCurrency(order.Valor_Unitario)}
Subtotal
{formatCurrency(order.Quantidade * order.Valor_Unitario)}
))}
))}
Mostrar
pedidos por página
Mostrando {groupedOrders.length > 0 ? startIndex + 1 : 0} a {Math.min(startIndex + ordersPerPage, groupedOrders.length)} de {groupedOrders.length} pedidos
);
};
export default ClientDetails;