feat(mejoras): 22 mejoras UX en todos los módulos
Mi día: cancelación con motivo, conteo escrituración real, cita sin retroceder, calendario completo Cobranza: MoraDashboard respeta alcance, hoy dinámico, cancelar con motivo Landing: contactos paginados, error vs vacío diferenciado Dashboards: KPI renombrado, drill-down planes activos Chat: historial recarga, preguntas rotativas, error solo toast Transversal: shadow-sm corrupto corregido en 9 archivos 553 API tests + 7 apps construidas
This commit is contained in:
@@ -29,6 +29,7 @@ import {
|
||||
sumarMeses,
|
||||
} from '../lib/cobranza'
|
||||
import { formatoFechaCorta, formatoMoneda, formatoPorcentaje } from '../lib/formatters'
|
||||
import { useHoy } from '../lib/useHoy'
|
||||
import MoraDashboard from "../components/MoraDashboard"
|
||||
import KpiCard from '../components/KpiCard'
|
||||
import SemaforoDot, { semaforoPlan } from '../components/Semaforo'
|
||||
@@ -62,7 +63,9 @@ export default function DashboardPage() {
|
||||
// param, los vendedores arrancan en "Mis planes" y el resto en "Todos"
|
||||
const paramVista = searchParams.get('vista')
|
||||
const mios = paramVista !== null ? paramVista === 'mios' : miosPorDefecto(getSesion()?.usuario.rol)
|
||||
const hoy = useMemo(() => new Date(), [])
|
||||
// "Hoy" se recalcula al enfocar la ventana (evita atrasos congelados si la
|
||||
// pestaña queda abierta de un día para otro)
|
||||
const hoy = useHoy()
|
||||
|
||||
useEffect(() => {
|
||||
let activo = true
|
||||
@@ -81,6 +84,7 @@ export default function DashboardPage() {
|
||||
}, [mios])
|
||||
|
||||
const planes = useMemo(() => resultado?.planes ?? [], [resultado])
|
||||
const idsPlan = useMemo(() => new Set(planes.map((p) => p.id)), [planes])
|
||||
|
||||
const actualizarParams = (cambios: Record<string, string | null>) => {
|
||||
setSearchParams(
|
||||
@@ -237,7 +241,7 @@ export default function DashboardPage() {
|
||||
)}
|
||||
|
||||
{/* KPIs */}
|
||||
<div className="grid grid-cols-2 gap-4 md:grid-cols-3 md:gap-6 lg:grid-cols-4 xl:grid-cols-5">
|
||||
<div className="grid grid-cols-2 gap-4 md:grid-cols-3 md:gap-6 lg:grid-cols-4">
|
||||
<KpiCard titulo="Planes activos" valor={activos.length} />
|
||||
<KpiCard
|
||||
titulo="Al corriente / con atraso"
|
||||
@@ -295,7 +299,7 @@ export default function DashboardPage() {
|
||||
</div>
|
||||
|
||||
{/* Tarjeta unificada: toolbar de filtros/búsqueda + tabla de planes */}
|
||||
<div className="overflow-hidden rounded-xl border border-[#E5E7EB] bg-white shadow dark:border-[#1E293B] dark:bg-[#1E293B] -sm">
|
||||
<div className="overflow-hidden rounded-xl border border-[#E5E7EB] bg-white shadow-sm dark:border-[#1E293B] dark:bg-[#1E293B]">
|
||||
{/* Filtros */}
|
||||
<div className="flex flex-wrap items-center gap-3 border-b border-[#E5E7EB] p-4 md:gap-4 md:px-5">
|
||||
{/* Toggle Mis planes / Todos (?mios=1 filtra en el API por el vendedor del token) */}
|
||||
@@ -426,7 +430,7 @@ export default function DashboardPage() {
|
||||
</div>
|
||||
</div>
|
||||
<section className="mt-8">
|
||||
<MoraDashboard />
|
||||
<MoraDashboard alcance={mios ? 'mios' : 'global'} planIds={idsPlan} />
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user