feat(api,web): detalhamento da carteira do representante
Tela dedicada que abre pelo botao "Detalhar carteira" na listagem de clientes, com leitura acionavel da carteira em vez de so uma tabela. - `/reports/carteira` passa a devolver `faturamentoTotal`, `participacaoPct` e `faturamentoRepTotal`, permitindo medir o peso de cada cliente no faturamento do rep. - `CarteirePage`: cards de resumo (ativos / em risco / inativos / sem pedido), faturamento total e InsightCards que apontam concentracao em poucos clientes, maior cliente em risco, maior inativo e clientes nunca positivados. - Clientes classificados por dias sem comprar (30d em risco, 60d inativo), com navegacao direta para a ficha. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -186,7 +186,13 @@ function CustomerMetrics({ stats }: { stats: PortfolioStats }) {
|
||||
|
||||
// ─── CustomerPortfolioCard ────────────────────────────────────────────────────
|
||||
|
||||
function CustomerPortfolioCard({ stats }: { stats: PortfolioStats }) {
|
||||
function CustomerPortfolioCard({
|
||||
stats,
|
||||
onDetalhar,
|
||||
}: {
|
||||
stats: PortfolioStats;
|
||||
onDetalhar: () => void;
|
||||
}) {
|
||||
const mesAtual = new Date().toLocaleDateString('pt-BR', { month: 'long', year: 'numeric' });
|
||||
const total = stats.ativos + stats.emAlerta + stats.inativos;
|
||||
|
||||
@@ -313,6 +319,7 @@ function CustomerPortfolioCard({ stats }: { stats: PortfolioStats }) {
|
||||
<Divider style={{ margin: '12px 0' }} />
|
||||
<Button
|
||||
block
|
||||
onClick={onDetalhar}
|
||||
style={{ borderRadius: 8, fontWeight: 600, color: '#003B8E', borderColor: '#003B8E' }}
|
||||
>
|
||||
Detalhar carteira
|
||||
@@ -500,7 +507,7 @@ function CustomerDetailsModal({
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Space direction="vertical" size={20} style={{ width: '100%' }}>
|
||||
<Space orientation="vertical" size={20} style={{ width: '100%' }}>
|
||||
{/* Identificação */}
|
||||
<Card
|
||||
style={{ borderRadius: 8, background: '#F8FAFC', border: '1px solid #EBF0F5' }}
|
||||
@@ -544,7 +551,7 @@ function CustomerDetailsModal({
|
||||
>
|
||||
Dados Cadastrais
|
||||
</Text>
|
||||
<Space direction="vertical" size={10} style={{ width: '100%' }}>
|
||||
<Space orientation="vertical" size={10} style={{ width: '100%' }}>
|
||||
<div>
|
||||
<span style={label}>Telefone</span>
|
||||
<Space size={4}>
|
||||
@@ -596,7 +603,7 @@ function CustomerDetailsModal({
|
||||
>
|
||||
Dados Comerciais
|
||||
</Text>
|
||||
<Space direction="vertical" size={10} style={{ width: '100%' }}>
|
||||
<Space orientation="vertical" size={10} style={{ width: '100%' }}>
|
||||
{limiteFormatado !== '—' && (
|
||||
<div>
|
||||
<span style={label}>Limite de Crédito</span>
|
||||
@@ -657,7 +664,7 @@ function CustomerDetailsModal({
|
||||
{loadingOrders ? (
|
||||
<Spin size="small" />
|
||||
) : (
|
||||
<Space direction="vertical" size={6} style={{ width: '100%' }}>
|
||||
<Space orientation="vertical" size={6} style={{ width: '100%' }}>
|
||||
{orders.slice(0, 5).map((p) => (
|
||||
<div
|
||||
key={p.id}
|
||||
@@ -811,7 +818,7 @@ function CustomerAnalysisModal({
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Space direction="vertical" size={20} style={{ width: '100%' }}>
|
||||
<Space orientation="vertical" size={20} style={{ width: '100%' }}>
|
||||
<div>
|
||||
<Space size={8}>
|
||||
<CustomerStatusBadge status={summary.activityStatus} />
|
||||
@@ -1456,7 +1463,10 @@ export function ClientsPage() {
|
||||
{/* ── Portfolio mobile (antes da lista) ─────────────────────────── */}
|
||||
{isMobile && (
|
||||
<>
|
||||
<CustomerPortfolioCard stats={stats} />
|
||||
<CustomerPortfolioCard
|
||||
stats={stats}
|
||||
onDetalhar={() => navigate({ to: '/clientes/carteira' })}
|
||||
/>
|
||||
<div style={{ marginBottom: 16 }} />
|
||||
</>
|
||||
)}
|
||||
@@ -1539,7 +1549,10 @@ export function ClientsPage() {
|
||||
|
||||
{!isMobile && (
|
||||
<Col lg={7}>
|
||||
<CustomerPortfolioCard stats={stats} />
|
||||
<CustomerPortfolioCard
|
||||
stats={stats}
|
||||
onDetalhar={() => navigate({ to: '/clientes/carteira' })}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
|
||||
Reference in New Issue
Block a user