import { useCallback, useEffect, useState } from 'react' import { getContactoDetalle, type DetalleContacto } from '../services/api' const formatoFecha = (iso: string): string => iso ? new Date(iso).toLocaleString('es-MX', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' }) : '' const formatoMoneda = (n: number): string => n > 0 ? n.toLocaleString('es-MX', { style: 'currency', currency: 'MXN', maximumFractionDigits: 0 }) : '—' interface Props { contactoId: string nombre: string onCerrar: () => void } /** * Modal con perfil completo del contacto: datos personales, contacto, * propiedad, historial pagos, documentos, última actividad. */ export default function PerfilContactoCompleto({ contactoId, nombre, onCerrar }: Props) { const [detalle, setDetalle] = useState(null) const [cargando, setCargando] = useState(true) const [error, setError] = useState('') const cargar = useCallback(async () => { setCargando(true) try { setDetalle(await getContactoDetalle(contactoId)) setError('') } catch { setError('No se pudo cargar el perfil del contacto') } finally { setCargando(false) } }, [contactoId]) useEffect(() => { void cargar() }, [cargar]) // Cerrar con Escape useEffect(() => { const alTeclear = (e: KeyboardEvent) => { if (e.key === 'Escape') onCerrar() } window.addEventListener('keydown', alTeclear) return () => window.removeEventListener('keydown', alTeclear) }, [onCerrar]) const c = detalle?.contacto ?? {} const prop = detalle?.propiedad ?? null const hist = detalle?.historial ?? [] const rels = detalle?.relaciones ?? { leads: [], oportunidades: [], apartados: [] } return (
{ if (e.target === e.currentTarget) onCerrar() }} >
{/* Header */}

Perfil del contacto

{c['nombre'] ?? nombre}

{cargando ? (

Cargando…

) : error ? (

{error}

) : (
{/* Datos personales */}
{/* Propiedad */}
{prop ? ( <> ) : (

Sin propiedad registrada

)}
{/* Relaciones CRM */} {(rels.leads.length + rels.oportunidades.length + rels.apartados.length) > 0 && (
{rels.leads.map((r) => (
Lead: {r.nombre} {r.estado}
))} {rels.oportunidades.map((r) => (
Oportunidad: {r.nombre} {r.estado}
))} {rels.apartados.map((r) => (
Apartado: {r.nombre} {r.estado}
))}
)} {/* Última actividad */}
{hist.length === 0 ? (

Sin actividad registrada

) : (
{hist.slice(0, 10).map((ev, idx) => (

{ev.detalle}

{formatoFecha(ev.fechaISO)} {ev.usuario ? ` · ${ev.usuario}` : ''} {ev.fuente ? ` · ${ev.fuente}` : ''}

))}
)}
)}
) } function Section({ titulo, children }: { titulo: string; children: React.ReactNode }) { return (

{titulo}

{children}
) } function Field({ label, value }: { label: string; value?: string | number | null }) { if (!value && value !== 0) return null return (
{label} {value}
) }