import { useCallback, useEffect, useState, type FormEvent } from 'react' import KpiCard from '../components/KpiCard' import BannerModoLocal from '../components/BannerModoLocal' import DarkModeToggle from '../components/DarkModeToggle' import { SkeletonList } from "../components/Skeleton" import toast from "react-hot-toast" import ChipPendienteSync from '../components/ChipPendienteSync' import type { AccionesSesion } from '../components/AuthGate' import { esActividadVencida, esRolConEquipo, formatoFechaCorta, hoyLocal, DESARROLLOS_LEAD, ETIQUETA_FASE_APARTADO, ETIQUETA_FASE_OPORTUNIDAD, FASES_APARTADO, MOTIVOS_NO_COMPRA, ORIGENES_LEAD, SLOTS_DOCS_APARTADO, SUBCATEGORIAS_NO_COMPRA, componerTelefono, LADAS, textoDiasRestantes, urlAfluenciaParaOportunidad, urlCotizadorParaOportunidad, type ApartadoMiDia, type ClaveLada, type FaseApartado, type LeadMiDia, type MotivoNoCompra, type OportunidadMiDia, type ResumenMiDia, type SlotDocApartado, } from '../lib/mi-dia' import { cambiarEstadoApartado, cambiarEstadoLead, cambiarEtapaOportunidad, convertirLead, crearLead, descartarLead, fetchResumenMiDia, listarDocumentosApartado, subirDocumentoApartado, type DocumentoApartado, } from '../services/mi-dia' import { guardarResumen, cargarResumenLocal } from '../services/offline-db' import { suscribirPush } from '../services/push' import { exportarLeads, exportarOportunidades, exportarApartados } from '../services/exportar' import { NotasApartado } from '../components/NotasApartado' import { FiltrosAvanzados, aplicarFiltros, type FiltrosCRM } from '../components/FiltrosAvanzados' import { getSesion } from '../services/auth' import DashboardVendedor from '../components/DashboardVendedor' import ScoreBadge, { calcularScore } from '../components/ScoreBadge' import KanbanView from '../components/KanbanView' import TimelineLead, { type EventoLead } from '../components/TimelineLead' function TituloSeccion({ children }: { children: string }) { return

{children}

} /** Banner de resumen matutino: saludo + KPIs del día */ function ResumenMatutino({ nombre, leadsNuevos, oportunidadesActivas, apartadosPorVencer, }: { nombre: string leadsNuevos: number oportunidadesActivas: number apartadosPorVencer: number }) { const hora = new Date().getHours() const esManana = hora < 12 const saludo = esManana ? 'Buenos días' : 'Buenas tardes' const icono = esManana ? '☀️' : '🌙' return (
{icono}

{saludo}, {nombre}

Tienes {leadsNuevos} lead{leadsNuevos !== 1 ? 's' : ''} nuevos hoy,{' '} {oportunidadesActivas} oportunidade{oportunidadesActivas !== 1 ? 's' : ''} activa{oportunidadesActivas !== 1 ? 's' : ''},{' '} {apartadosPorVencer} apartado{apartadosPorVencer !== 1 ? 's' : ''} por vencer

) } function EstadoVacio({ mensaje }: { mensaje: string }) { return (

{mensaje}

) } const CLASE_BOTON_ACCION = 'rounded-lg border border-[#D1D5DB] bg-white px-3 dark:border-[#334155] dark:bg-[#0F172A] dark:text-[#E2E8F0] py-1.5 text-xs font-medium text-accent shadow-sm transition-all duration-100 ease-out hover:bg-blue-50 disabled:opacity-50' const CLASE_INPUT = 'w-full rounded-lg border border-[#D1D5DB] bg-white px-3 dark:border-[#334155] dark:bg-[#0F172A] dark:text-[#E2E8F0] py-2.5 text-sm transition-colors focus:border-accent focus:outline-none focus:ring-2 focus:ring-accent/20' const CLASE_LABEL = 'mb-2 block text-xs font-medium text-[#4B5563] dark:text-[#CBD5E1]' /** Modal de descarte: motivo + subcategoría (catálogo Monday) + comentario opcional */ function ModalDescartar({ lead, onCancelar, onConfirmar, enviando, }: { lead: { id: string; nombre: string } onCancelar: () => void onConfirmar: (motivo: MotivoNoCompra, subcategoria: string | undefined, comentario: string) => void enviando: boolean }) { const [motivo, setMotivo] = useState(MOTIVOS_NO_COMPRA[0]) const [subcategoria, setSubcategoria] = useState('') const [comentario, setComentario] = useState('') const subcategorias = SUBCATEGORIAS_NO_COMPRA[motivo] return (

Descartar lead

{lead.nombre}

{ e.preventDefault() onConfirmar(motivo, subcategoria === '' ? undefined : subcategoria, comentario.trim()) }} >