import { useMemo, useState } from 'react'; import { Link, useOutletContext } from 'react-router-dom'; import { Search, ChevronRight, Filter } from 'lucide-react'; import type { OrderData } from '../types'; import { parseOrderDate } from '../dataService'; type SortOption = 'recent' | 'spent_desc' | 'spent_asc' | 'items_desc' | 'items_asc'; const Clients = () => { const { ordersData } = useOutletContext<{ ordersData: OrderData[] }>(); const [searchTerm, setSearchTerm] = useState(''); const [sortBy, setSortBy] = useState('recent'); const clientsData = useMemo(() => { const orders = ordersData; const clientMap: Record, lastPurchase: number }> = {}; orders.forEach(order => { const clientName = order.Nome_Cliente || `Cliente Desconhecido (Pedido ${order.Valor_Pedido})`; if (!clientMap[clientName]) { clientMap[clientName] = { totalSpent: 0, totalItems: 0, uniqueOrders: new Set(), lastPurchase: 0 }; } // Calculate total spent based on quantity * unit price clientMap[clientName].totalSpent += (order.Quantidade * order.Valor_Unitario); clientMap[clientName].totalItems += order.Quantidade; clientMap[clientName].uniqueOrders.add(`${order.Data_Pedido}_${order.Valor_Pedido}`); const orderTime = parseOrderDate(order.Data_Pedido).getTime(); if (orderTime > clientMap[clientName].lastPurchase) { clientMap[clientName].lastPurchase = orderTime; } }); let result = Object.keys(clientMap).map(name => ({ name, totalSpent: clientMap[name].totalSpent, totalItems: clientMap[name].totalItems, orderCount: clientMap[name].uniqueOrders.size, // Grouped by unique date+value combinations lastPurchase: clientMap[name].lastPurchase })); if (searchTerm) { result = result.filter(c => c.name.toLowerCase().includes(searchTerm.toLowerCase())); } return result.sort((a, b) => { switch (sortBy) { case 'recent': return b.lastPurchase - a.lastPurchase; case 'spent_desc': return b.totalSpent - a.totalSpent; case 'spent_asc': return a.totalSpent - b.totalSpent; case 'items_desc': return b.totalItems - a.totalItems; case 'items_asc': return a.totalItems - b.totalItems; default: return 0; } }); }, [searchTerm, sortBy, ordersData]); const formatCurrency = (value: number) => { return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(value); }; return (

Clientes

Métricas de engajamento e histórico de consumo dos seus clientes.

setSearchTerm(e.target.value)} className="w-full md:w-64 bg-white dark:bg-dark-input border border-zinc-200 dark:border-dark-border text-zinc-900 dark:text-dark-text rounded-xl pl-10 pr-4 py-2.5 focus:outline-none focus:border-brand-primary focus:ring-2 focus:ring-brand-primary/20 transition-all shadow-sm" />
{clientsData.map((client, index) => ( ))}
Posição Nome do Cliente Total Gasto Produtos Comprados Ações
{index + 1} {client.name} {formatCurrency(client.totalSpent)} {client.totalItems} un. ({client.orderCount} {client.orderCount === 1 ? 'pedido' : 'pedidos'}) Ver detalhes
); }; export default Clients;