Clarify RFM period metrics
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m29s

This commit is contained in:
Cauê Faleiros
2026-06-15 13:16:26 -03:00
parent 1956e62697
commit b416154868

View File

@@ -171,10 +171,11 @@ const Rfm = () => {
const totals = useMemo(() => {
const totalRevenue = clients.reduce((sum, client) => sum + client.monetary, 0);
const periodClientCount = clients.filter(client => client.frequency > 0 || client.monetary > 0).length;
const activeSegments = segments.filter(segment => segment.count > 0).length;
const topSegment = [...segments].sort((a, b) => b.totalRevenue - a.totalRevenue)[0];
return { totalRevenue, activeSegments, topSegment };
return { totalRevenue, periodClientCount, activeSegments, topSegment };
}, [clients, segments]);
const segmentInsights = useMemo(() => {
@@ -215,9 +216,9 @@ const Rfm = () => {
Frequencia: client.frequencyScore,
Monetario: client.monetaryScore,
'Dias desde ultima compra': client.recencyDays,
Pedidos: client.frequency,
'Ticket medio (R$)': (client.frequency ? client.monetary / client.frequency : 0).toFixed(2).replace('.', ','),
'Total gasto (R$)': client.monetary.toFixed(2).replace('.', ','),
'Pedidos no periodo': client.frequency,
'Ticket medio no periodo (R$)': (client.frequency ? client.monetary / client.frequency : 0).toFixed(2).replace('.', ','),
'Receita no periodo (R$)': client.monetary.toFixed(2).replace('.', ','),
'Ultima compra': formatDate(client.lastPurchaseDate)
}));
@@ -252,18 +253,19 @@ const Rfm = () => {
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div className="bg-dark-card p-6 rounded-2xl border border-dark-border shadow-sm">
<p className="text-dark-muted text-sm font-medium mb-1">Clientes Classificados</p>
<p className="text-dark-muted text-sm font-medium mb-1">Base RFM</p>
<h3 className="text-3xl font-bold text-dark-text">{clients.length}</h3>
<p className="mt-1 text-xs font-semibold text-dark-muted">{totals.periodClientCount} com compra no período</p>
</div>
<div className="bg-dark-card p-6 rounded-2xl border border-dark-border shadow-sm">
<p className="text-dark-muted text-sm font-medium mb-1">Receita no Período</p>
<h3 className="text-3xl font-bold text-dark-text">{formatCurrency(totals.totalRevenue)}</h3>
</div>
<div className="bg-dark-card p-6 rounded-2xl border border-dark-border shadow-sm">
<p className="text-dark-muted text-sm font-medium mb-1">Segmentos Ativos</p>
<p className="text-dark-muted text-sm font-medium mb-1">Segmentos na Base</p>
<h3 className="text-3xl font-bold text-dark-text">{totals.activeSegments}</h3>
<p className="mt-1 text-xs font-semibold text-dark-muted">
Principal: {totals.topSegment?.label || 'N/A'}
Maior receita no período: {totals.topSegment?.label || 'N/A'}
</p>
</div>
</div>
@@ -273,7 +275,7 @@ const Rfm = () => {
<div className="mb-4 flex flex-col gap-3 lg:flex-row lg:items-end lg:justify-between">
<div>
<h2 className="text-lg font-bold text-dark-text">Matriz RFM</h2>
<p className="text-sm font-medium text-dark-muted">Distribuição dos clientes por recência e valor.</p>
<p className="text-sm font-medium text-dark-muted">Base classificada até o fim do período; valores mostram apenas o período selecionado.</p>
</div>
<div className="flex items-center gap-2 text-xs font-semibold text-dark-muted">
<span>Menor prioridade</span>
@@ -347,7 +349,7 @@ const Rfm = () => {
<p className={`text-xl font-bold leading-none ${style.text}`}>{segment?.count || 0}</p>
</div>
<div>
<p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Receita</p>
<p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Receita período</p>
<p className="truncate text-xs font-bold text-dark-text">{formatCurrency(segment?.totalRevenue || 0)}</p>
</div>
</div>
@@ -386,7 +388,7 @@ const Rfm = () => {
<span className={`text-sm font-bold ${style.text}`}>{segment.count}</span>
</div>
<p className="mt-1 text-xs font-semibold text-dark-muted">
{(segmentInsights[segment.key]?.customerPercent || 0).toFixed(1)}% clientes · {formatCurrency(segment.totalRevenue)}
{(segmentInsights[segment.key]?.customerPercent || 0).toFixed(1)}% clientes · {formatCurrency(segment.totalRevenue)} no período
</p>
</button>
);
@@ -413,11 +415,11 @@ const Rfm = () => {
<p className="mt-1 text-base font-bold text-dark-text">{selectedSegmentInsights.customerPercent.toFixed(1)}%</p>
</div>
<div className="rounded-xl border border-dark-border bg-black/10 p-3">
<p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Receita</p>
<p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Receita período</p>
<p className="mt-1 text-base font-bold text-dark-text">{selectedSegmentInsights.revenuePercent.toFixed(1)}%</p>
</div>
<div className="rounded-xl border border-dark-border bg-black/10 p-3">
<p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Ticket</p>
<p className="text-[10px] font-bold uppercase tracking-wider text-dark-muted">Ticket período</p>
<p className="mt-1 text-base font-bold text-dark-text">{formatCurrency(selectedSegmentInsights.averageTicket)}</p>
</div>
<div className="rounded-xl border border-dark-border bg-black/10 p-3">
@@ -483,9 +485,9 @@ const Rfm = () => {
<th className="px-6 py-4 font-bold uppercase tracking-wider text-[10px]">Segmento</th>
<th className="px-6 py-4 font-bold uppercase tracking-wider text-[10px]">RFM</th>
<th className="px-6 py-4 font-bold uppercase tracking-wider text-[10px]">Última Compra</th>
<th className="px-6 py-4 font-bold uppercase tracking-wider text-[10px]">Pedidos</th>
<th className="px-6 py-4 font-bold uppercase tracking-wider text-[10px]">Ticket Médio</th>
<th className="px-6 py-4 font-bold uppercase tracking-wider text-[10px]">Total Gasto</th>
<th className="px-6 py-4 font-bold uppercase tracking-wider text-[10px]">Pedidos no Período</th>
<th className="px-6 py-4 font-bold uppercase tracking-wider text-[10px]">Ticket no Período</th>
<th className="px-6 py-4 font-bold uppercase tracking-wider text-[10px]">Receita no Período</th>
</tr>
</thead>
<tbody className="divide-y divide-dark-border">