feat: mis clientes en Mi dia + perfilamiento de la afluencia en dashboards
- Cliente.capturadoPorId: el alta (directa y progresiva) registra al usuario que la inicio; el panel Mi dia muestra 'Mis clientes' con su estado (En captura / Cliente) sin depender de Monday. - LeadMonday ahora lee las 11 columnas de perfil del tablero Leads (estado civil, edad, rango salarial, tipo de empleo/economia, califica, credito, modelo, etc.). - GET /api/reportes/resumen agrega leads.perfil con conteos por dimension (valores vacios se omiten; edad en buckets). - /dash/ gana la seccion 'Perfilamiento de la afluencia' con mini-graficas de barras por dimension.
This commit is contained in:
59
apps/dashboards/src/components/Perfilamiento.tsx
Normal file
59
apps/dashboards/src/components/Perfilamiento.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
import { Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'
|
||||
import { EstadoVacio, TituloSeccion } from './comunes'
|
||||
import { rebanadasDe, type ResumenReportes } from '../lib/reportes'
|
||||
|
||||
// Dimensiones del perfilamiento de la afluencia (board Leads) en el orden del tablero
|
||||
const DIMENSIONES: { titulo: string; registro: (perfil: ResumenReportes['leads']['perfil']) => Record<string, number> }[] = [
|
||||
{ titulo: 'Estado civil', registro: (p) => p.porEstadoCivil },
|
||||
{ titulo: 'Rango salarial', registro: (p) => p.porRangoSalarial },
|
||||
{ titulo: 'Edad', registro: (p) => p.porEdad },
|
||||
{ titulo: 'Tipo de empleo', registro: (p) => p.porTipoEmpleo },
|
||||
{ titulo: 'Tipo de economía', registro: (p) => p.porTipoEconomia },
|
||||
{ titulo: 'Califica', registro: (p) => p.porCalifica },
|
||||
{ titulo: 'Crédito', registro: (p) => p.porCredito },
|
||||
{ titulo: 'Desarrollo', registro: (p) => p.porDesarrollo },
|
||||
{ titulo: 'Modelo de interés', registro: (p) => p.porModelo },
|
||||
{ titulo: 'Medio de contacto', registro: (p) => p.porMedioContacto },
|
||||
{ titulo: 'Lo quiere para', registro: (p) => p.porLoQuierePara },
|
||||
]
|
||||
|
||||
function TarjetaDimension({ titulo, datos }: { titulo: string; datos: Record<string, number> }) {
|
||||
const rebanadas = rebanadasDe(datos)
|
||||
return (
|
||||
<div className="border border-neutral-200 p-4">
|
||||
<p className="mb-2 text-xs font-bold uppercase tracking-widest text-neutral-500">{titulo}</p>
|
||||
{rebanadas.length === 0 ? (
|
||||
<EstadoVacio mensaje="Sin datos" />
|
||||
) : (
|
||||
<div className="h-48">
|
||||
<ResponsiveContainer width="100%" height="100%">
|
||||
<BarChart data={rebanadas} layout="vertical" margin={{ top: 4, right: 24, left: 24, bottom: 0 }}>
|
||||
<CartesianGrid strokeDasharray="3 3" horizontal={false} />
|
||||
<XAxis type="number" allowDecimals={false} tick={{ fontSize: 11 }} />
|
||||
<YAxis type="category" dataKey="nombre" width={90} tick={{ fontSize: 11 }} />
|
||||
<Tooltip />
|
||||
<Bar dataKey="valor" name="Leads" fill="#1B4332" isAnimationActive={false} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sección "Perfilamiento de la afluencia": una mini-gráfica de barras
|
||||
* horizontales por dimensión capturada en el board Leads.
|
||||
*/
|
||||
export default function Perfilamiento({ perfil }: { perfil: ResumenReportes['leads']['perfil'] }) {
|
||||
return (
|
||||
<section aria-label="Perfilamiento de la afluencia" className="mt-12">
|
||||
<TituloSeccion>Perfilamiento de la afluencia</TituloSeccion>
|
||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{DIMENSIONES.map((d) => (
|
||||
<TarjetaDimension key={d.titulo} titulo={d.titulo} datos={d.registro(perfil)} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
YAxis,
|
||||
} from 'recharts'
|
||||
import KpiCard from './KpiCard'
|
||||
import Perfilamiento from './Perfilamiento'
|
||||
import SeccionEquipo from './SeccionEquipo'
|
||||
import { EstadoVacio, TituloSeccion } from './comunes'
|
||||
import {
|
||||
@@ -244,6 +245,8 @@ export default function TableroGeneral({ mostrarEquipo }: { mostrarEquipo: boole
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<Perfilamiento perfil={resumen.leads.perfil} />
|
||||
|
||||
{mostrarEquipo && <SeccionEquipo />}
|
||||
</>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user