feat: add revenue and top services stats to dashboard

This commit is contained in:
2026-06-11 16:36:42 +01:00
parent c596f7a005
commit 5f42ae839d

View File

@@ -448,13 +448,15 @@ function DashboardInner({ shop }: { shop: BarberShop }) {
<Card className="p-4 sm:p-6">
<div className="flex items-center justify-between mb-2 sm:mb-3">
<div className="p-2 sm:p-3 bg-blue-500 rounded-lg text-white">
<Globe size={20} className="sm:hidden" />
<Globe size={24} className="hidden sm:block" />
<TrendingUp size={20} className="sm:hidden" />
<TrendingUp size={24} className="hidden sm:block" />
</div>
</div>
<p className="text-xs sm:text-sm text-slate-600 mb-0.5 sm:mb-1">Reservas online</p>
<p className="text-2xl sm:text-3xl font-bold text-slate-900">{allShopAppointments.length}</p>
<p className="text-[10px] sm:text-xs text-slate-500 mt-1.5 sm:mt-2">Marcações feitas pela plataforma</p>
<p className="text-xs sm:text-sm text-slate-600 mb-0.5 sm:mb-1">Faturação (Serviços + Produtos)</p>
<p className="text-2xl sm:text-3xl font-bold text-slate-900">
{currency(totalRevenue + allShopAppointments.filter(a => a.status === 'concluido' || a.status === 'confirmado').reduce((s, a) => s + (a.total || 0), 0))}
</p>
<p className="text-[10px] sm:text-xs text-slate-500 mt-1.5 sm:mt-2">Receita no período selecionado</p>
</Card>
<Card className="p-4 sm:p-6">
@@ -525,6 +527,35 @@ function DashboardInner({ shop }: { shop: BarberShop }) {
</div>
</Card>
{/* Serviços Mais Procurados */}
<Card className="p-6">
<h3 className="text-lg font-bold text-slate-900 mb-4">Top Serviços</h3>
{(() => {
const map = new Map<string, { name: string; qty: number }>();
allShopAppointments.forEach(a => {
if (a.status === 'cancelado') return;
const svc = shop.services.find(s => s.id === a.serviceId);
if (!svc) return;
const prev = map.get(a.serviceId)?.qty ?? 0;
map.set(a.serviceId, { name: svc.name, qty: prev + 1 });
});
const top = Array.from(map.values()).sort((a, b) => b.qty - a.qty).slice(0, 4);
if (top.length === 0) return <p className="text-sm text-slate-500 text-center py-4">Sem dados suficientes</p>;
return (
<div className="space-y-3">
{top.map((t, i) => (
<div key={i} className="flex items-center justify-between p-3 border border-slate-100 rounded-lg bg-slate-50">
<span className="font-semibold text-slate-700 text-sm truncate pr-2">{t.name}</span>
<Badge color="indigo" variant="soft">{t.qty} reservas</Badge>
</div>
))}
</div>
);
})()}
</Card>
{/* Próximos Agendamentos */}
<Card className="p-6">
<h3 className="text-lg font-bold text-slate-900 mb-4">Seguinte</h3>