// sofia-vendedora.jsx — Sofia coach personal para vendedoras premium // Threshold: facturación bruta del mes actual >= $200 → desbloquea // Si no, muestra "paywall" motivacional con cuánto falta (function () { const STORAGE_KEY = 'inova-sofia-vendedora-chat-v1'; const THRESHOLD = 200; // Lista de cédulas con acceso premium bypass (admin/testing) const PREMIUM_BYPASS_CEDULAS = ['21618076']; // Brian function getPremiumStatus(pedidos, vendedora) { const now = new Date(); const thisMonth = (pedidos || []).filter(p => p.fechaCreacion.getMonth() === now.getMonth() && p.fechaCreacion.getFullYear() === now.getFullYear() ); const facturado = thisMonth.reduce((s, p) => s + p.productos.reduce((a, x) => a + (+x.precio || 0) * (+x.cantidad || 0), 0) , 0); // Bypass: admin o cédulas autorizadas → siempre unlocked const bypass = (vendedora?.zona === 'Admin') || PREMIUM_BYPASS_CEDULAS.includes(vendedora?.cedula); const unlocked = bypass || facturado >= THRESHOLD; const falta = unlocked ? 0 : (THRESHOLD - facturado); return { unlocked, facturado, falta, threshold: THRESHOLD, bypass }; } // Sugerencias específicas para vendedora (no admin) const SUGERENCIAS_VENDEDORA = [ '¿Cómo le respondo a una clienta que dice "está caro"?', 'Dame 3 productos para ofrecer a clientas que ya compraron perfume', '¿Cómo cierro una venta cuando la clienta dice "déjame pensarlo"?', 'Tengo 5 clientas que no me compran hace 2 meses, ¿cómo las reactivo?', '¿Qué mensaje le mando a mis clientas para anunciar promociones C09?', 'Mi clienta quiere algo para piel grasa pero no sé qué recomendarle', ]; function SofiaVendedoraScreen({ vendedora, pedidos, onClose }) { const T = window.T; const { Icon } = window; const premium = getPremiumStatus(pedidos, vendedora); if (!premium.unlocked) { return ; } return ; } // ─── Pantalla bloqueada (paywall motivacional) ─────────────────── function SofiaLockedScreen({ vendedora, premium, onClose }) { const T = window.T; const { Icon } = window; const pct = Math.min(100, Math.round(premium.facturado / premium.threshold * 100)); return (
{/* Header */}
Sofia · Coach Premium
{/* Hero locked */}
Sofia
🔒
Tu coach personal de ventas
Sofia te ayuda a cerrar más ventas, recomendar productos, contestar objeciones — 24/7
{/* Progress card */}
Desbloqueá Sofia este mes
${premium.facturado.toFixed(0)}
de ${premium.threshold}
Te faltan ${premium.falta.toFixed(2)} en ventas este mes para desbloquear a tu coach.
{/* Lo que hace Sofia (teaser) */}
Lo que Sofia te ayuda a hacer
{[ { icon: '💬', text: 'Responder objeciones ("está caro", "no me lo puedo permitir", "lo veo después")' }, { icon: '🎯', text: 'Saber qué producto recomendarle a CADA clienta (según lo que ya compró)' }, { icon: '📈', text: 'Subir tu ticket promedio con sets y bundles del catálogo' }, { icon: '🔥', text: 'Reactivar clientas dormidas con mensajes que sí funcionan' }, { icon: '💡', text: 'Aprender técnicas de venta de Alex Hormozi adaptadas a tu negocio' }, ].map((it, i) => (
{it.icon}
{it.text}
))}
{/* CTA */}
Tip de Sofia (gratis): el camino más rápido a $200 es vender 1 set + 2 perfumes a clientas que ya compraron antes. ¡Tú puedes!
); } // ─── Pantalla desbloqueada (chat) ───────────────────────────────── function SofiaUnlockedChat({ vendedora, pedidos, onClose }) { const T = window.T; const { Icon } = window; const [messages, setMessages] = React.useState(() => { try { const raw = localStorage.getItem(STORAGE_KEY + ':' + vendedora?.id); if (raw) return JSON.parse(raw); } catch {} return []; }); const [input, setInput] = React.useState(''); const [loading, setLoading] = React.useState(false); const scrollRef = React.useRef(null); React.useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [messages, loading]); React.useEffect(() => { try { const toSave = messages.slice(-30); localStorage.setItem(STORAGE_KEY + ':' + vendedora?.id, JSON.stringify(toSave)); } catch {} }, [messages, vendedora?.id]); async function ask(pregunta) { if (!pregunta.trim() || loading) return; // Capturamos historial ANTES de agregar el nuevo mensaje const historial = messages.slice(-12).map(m => ({ role: m.role === 'user' ? 'user' : 'sofia', text: (m.text || '').slice(0, 400), })); setMessages(prev => [...prev, { role: 'user', text: pregunta, ts: Date.now() }]); setInput(''); setLoading(true); try { const res = await fetch('/api/sofia/ask', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ pregunta, user_id: 'vendedora-' + vendedora?.id, contexto: `vendedora:${vendedora?.nombre}|zona:${vendedora?.zona}`, nombre_usuario: vendedora?.nombre, historial, incluir_videos: false, }), }); const data = await res.json(); if (!res.ok) throw new Error(data.detail || 'Error'); setMessages(prev => [...prev, { role: 'sofia', text: data.respuesta, fuentes: (data.fuentes_usadas || []).slice(0, 3), acciones: data.acciones || [], ts: Date.now(), }]); } catch (e) { setMessages(prev => [...prev, { role: 'error', text: e.message, ts: Date.now() }]); } setLoading(false); } function clearChat() { if (!confirm('¿Borrar conversación con Sofia?')) return; setMessages([]); try { localStorage.removeItem(STORAGE_KEY + ':' + vendedora?.id); } catch {} } return (
{/* Header */}
Sofia
Sofia
● Tu coach activa
{messages.length > 0 && ( )}
{/* Mensajes */}
{messages.length === 0 && !loading && (
¡Epa {(vendedora?.nombre || '').split(' ')[0]}! Soy Sofia, tu coach personal de ventas. Te ayudo a vender más, cerrar mejor y subir tu ticket promedio. Preguntame lo que sea.
Sugerencias para empezar
{SUGERENCIAS_VENDEDORA.map((s, i) => ( ))}
)} {messages.map((m, i) => )} {loading && (
Sofia está pensando...
)}
{/* Input */}