// Ejecutora — CRM de Clientes Completo const CRMScreen = () => { const [view, setView] = React.useState('tabla'); // tabla | kanban | detalle const [clienteActivo, setClienteActivo] = React.useState(null); const [showModal, setShowModal] = React.useState(false); const [busqueda, setBusqueda] = React.useState(''); const [filtroEtapa, setFiltroEtapa] = React.useState('todas'); const [clientes, setClientes] = React.useState([ { id: 1, nombre: 'Carla Méndez', email: 'carla@negocio.com', whatsapp: '+58 412 555 0101', sector: 'Coach negocios', etapa: 'cierre', valor: 2400, notas: 'Interesada en programa Completo. Llamada el martes.', ultimoContacto: '30 abr', compraAnterior: 'Mentoria individual $500', seguimientos: 2, activa: true }, { id: 2, nombre: 'Laura González', email: 'laura@marca.co', whatsapp: '+58 414 555 0202', sector: 'Diseñadora', etapa: 'seguimiento', valor: 1200, notas: 'Enviada propuesta. Pendiente respuesta.', ultimoContacto: '29 abr', compraAnterior: '', seguimientos: 1, activa: true }, { id: 3, nombre: 'Paola Reyes', email: 'paola@studio.io', whatsapp: '+58 416 555 0303', sector: 'Infoproductora', etapa: 'propuesta', valor: 3800, notas: 'Quiere el pack VIP. Espera cobro.', ultimoContacto: '28 abr', compraAnterior: 'Ebook $37', seguimientos: 3, activa: true }, { id: 4, nombre: 'María Fernández', email: 'maria@emprende.net', whatsapp: '+58 424 555 0404', sector: 'Pastelería', etapa: 'contacto', valor: 900, notas: 'Nueva lead de Instagram.', ultimoContacto: '27 abr', compraAnterior: '', seguimientos: 0, activa: true }, { id: 5, nombre: 'Sofía Castillo', email: 'sofia@brand.com', whatsapp: '+58 412 555 0505', sector: 'Coach bienestar', etapa: 'ganado', valor: 5000, notas: 'Clienta VIP, programa 6 meses.', ultimoContacto: '25 abr', compraAnterior: 'Curso base $197', seguimientos: 0, activa: false }, { id: 6, nombre: 'Andrea Torres', email: 'andrea@ventas.net', whatsapp: '+58 416 555 0606', sector: 'Infoproductora', etapa: 'inactiva', valor: 0, notas: 'No respondió en 2 meses. Reactivar.', ultimoContacto: '15 feb', compraAnterior: 'Ebook $37', seguimientos: 0, activa: false }, { id: 7, nombre: 'Valentina Ríos', email: 'vale@marca.co', whatsapp: '+58 424 555 0707', sector: 'Diseñadora', etapa: 'cierre', valor: 1800, notas: 'Esperando contrato. Muy interesada.', ultimoContacto: '1 may', compraAnterior: '', seguimientos: 1, activa: true }, { id: 8, nombre: 'Carolina Blanco', email: 'caro@studio.io', whatsapp: '+58 412 555 0808', sector: 'Entrenadora', etapa: 'seguimiento', valor: 1500, notas: 'Preguntó por el programa mensual.', ultimoContacto: '30 abr', compraAnterior: 'Reto gratis', seguimientos: 2, activa: true }, ]); const [nuevoCliente, setNuevoCliente] = React.useState({ nombre: '', email: '', whatsapp: '', sector: '', etapa: 'contacto', valor: '', notas: '' }); const etapas = { contacto: { label: 'Contacto', color: EJ.muted, bg: EJ.bgApp, emoji: '👋' }, seguimiento: { label: 'Seguimiento', color: EJ.cyan, bg: EJ.cyanLight, emoji: '💬' }, propuesta: { label: 'Propuesta', color: EJ.violet, bg: EJ.violetLight, emoji: '📋' }, cierre: { label: 'Cierre', color: EJ.pink, bg: EJ.pinkLight, emoji: '🔥' }, ganado: { label: 'Ganado ✓', color: EJ.green, bg: EJ.greenLight, emoji: '🎉' }, inactiva: { label: 'Inactiva', color: '#C0C0C8', bg: '#F4F4F8', emoji: '💤' }, }; const sectores = ['Coach negocios', 'Coach bienestar', 'Diseñadora', 'Infoproductora', 'Pastelería', 'Entrenadora', 'Otro']; const clientesFiltrados = clientes.filter(c => { const matchBusqueda = c.nombre.toLowerCase().includes(busqueda.toLowerCase()) || c.email.toLowerCase().includes(busqueda.toLowerCase()) || c.sector.toLowerCase().includes(busqueda.toLowerCase()); const matchEtapa = filtroEtapa === 'todas' || c.etapa === filtroEtapa; return matchBusqueda && matchEtapa; }); const totalPipeline = clientes.filter(c => c.etapa !== 'inactiva').reduce((s, c) => s + c.valor, 0); const tasaCierre = Math.round((clientes.filter(c => c.etapa === 'ganado').length / clientes.length) * 100); const guardarCliente = () => { if (!nuevoCliente.nombre) return; setClientes(prev => [...prev, { ...nuevoCliente, id: Date.now(), valor: Number(nuevoCliente.valor) || 0, seguimientos: 0, activa: true, ultimoContacto: 'hoy', compraAnterior: '' }]); setNuevoCliente({ nombre: '', email: '', whatsapp: '', sector: '', etapa: 'contacto', valor: '', notas: '' }); setShowModal(false); }; const actualizarEtapa = (id, etapa) => { setClientes(prev => prev.map(c => c.id === id ? { ...c, etapa } : c)); }; const copyWA = (c) => { const texto = c.compraAnterior ? `Hola ${c.nombre.split(' ')[0]} 🌸 Hace tiempo que no hablamos y me acordé de ti — la última vez me pediste ${c.compraAnterior}. Esta semana tengo una oferta especial para mis clientas anteriores. ¿Tienes un momento? 💜` : `Hola ${c.nombre.split(' ')[0]} ✨ Vi tu consulta y me encantaría ayudarte. ¿Podemos hablar un momento? 💜`; navigator.clipboard.writeText(texto).catch(() => {}); alert('Copy copiado al portapapeles ✓'); }; // Vista tabla const VistaTabla = () => ( {['Cliente', 'Sector', 'Etapa', 'Valor', 'Último contacto', 'Seguim.', ''].map(h => ( ))} {clientesFiltrados.map((c, i) => { const etapa = etapas[c.etapa]; return ( e.currentTarget.style.background = EJ.bgApp} onMouseLeave={e => e.currentTarget.style.background = 'transparent'} > ); })}
{h}
{c.nombre}
{c.email}
{c.sector} {etapa.emoji} {etapa.label} 0 ? EJ.navy : EJ.muted, fontFamily: 'JetBrains Mono, monospace' }}> {c.valor > 0 ? `$${c.valor.toLocaleString()}` : '—'} {c.ultimoContacto} {c.seguimientos > 0 && {c.seguimientos} pend.}
{ setClienteActivo(c); setView('detalle'); }}>Ver → copyWA(c)}>WA
); // Vista Kanban const VistaKanban = () => (
{Object.entries(etapas).map(([etapaKey, etapa]) => { const grupo = clientesFiltrados.filter(c => c.etapa === etapaKey); return (
{etapa.emoji} {etapa.label} {grupo.length}
{grupo.map(c => (
{ setClienteActivo(c); setView('detalle'); }} >
{c.nombre}
{c.sector}
{c.valor > 0 &&
${c.valor.toLocaleString()}
} {c.seguimientos > 0 && {c.seguimientos} seguim.}
))}
); })}
); // Vista detalle const VistaDetalle = ({ c }) => { const [etapaLocal, setEtapaLocal] = React.useState(c.etapa); const [notasLocal, setNotasLocal] = React.useState(c.notas); return (
{c.nombre}
{c.sector}
{[{ icon: '📧', val: c.email }, { icon: '📱', val: c.whatsapp }, { icon: '📅', val: `Último contacto: ${c.ultimoContacto}` }].map((r, i) => (
{r.icon} {r.val}
))} {c.compraAnterior && (
Compra anterior
{c.compraAnterior}
)}
Mover de etapa
{Object.entries(etapas).map(([key, et]) => ( ))}
Notas y seguimiento