/* WhatsAppSim.jsx — conversa multimodal animada dentro do celular. Mostra o agente entendendo texto, áudio, imagem e documento. */ const WhatsAppSim = () => { const script = [ { from: 'agent', type: 'text', text: 'Olá! Seja bem-vindo à Agência AR. Como posso ajudar a sua empresa hoje?' }, { from: 'user', type: 'audio', dur: '0:09' }, { from: 'agent', type: 'text', proc: 'audio', procLabel: 'ouvindo áudio', text: 'Entendi seu áudio: você quer automatizar o atendimento da sua loja. Posso cuidar disso para você.' }, { from: 'user', type: 'image', caption: 'foto-produto.jpg' }, { from: 'agent', type: 'text', proc: 'image', procLabel: 'analisando imagem', text: 'Recebi a foto do produto. Já consigo tirar dúvidas sobre ele e indicar para os clientes certos.' }, { from: 'user', type: 'doc', file: 'tabela-precos.pdf', size: '240 KB' }, { from: 'agent', type: 'text', proc: 'doc', procLabel: 'lendo documento', text: 'Li sua tabela de preços. A partir dela, gero orçamentos na hora durante a conversa.' }, { from: 'agent', type: 'text', text: 'Atendo por texto, áudio, imagem e documento — em qualquer canal, 24 horas por dia.' }, ]; const [shown, setShown] = React.useState(0); // messages visible const [typing, setTyping] = React.useState(false); const [typeLabel, setTypeLabel] = React.useState(null); const [started, setStarted] = React.useState(false); const rootRef = React.useRef(null); const phoneRef = React.useRef(null); const feedRef = React.useRef(null); const timers = React.useRef([]); // Start when the phone scrolls into view (scroll-based — robusto neste runtime) React.useEffect(() => { let done = false; const check = () => { if (done) return; const el = phoneRef.current || rootRef.current; if (!el) return; const r = el.getBoundingClientRect(); if (r.top < window.innerHeight * 0.85 && r.bottom > 0) { done = true; setStarted(true); window.removeEventListener('scroll', check); } }; check(); window.addEventListener('scroll', check, { passive: true }); const t = setTimeout(check, 400); return () => { window.removeEventListener('scroll', check); clearTimeout(t); }; }, []); React.useEffect(() => { if (!started) return; const run = () => { timers.current.forEach(clearTimeout); timers.current = []; setShown(0); setTyping(false); setTypeLabel(null); let t = 600; script.forEach((m, i) => { if (m.from === 'agent') { timers.current.push(setTimeout(() => { setTyping(true); setTypeLabel(m.procLabel ? { kind: m.proc, label: m.procLabel } : null); }, t)); t += m.proc ? 1500 : 1150; timers.current.push(setTimeout(() => { setTyping(false); setTypeLabel(null); setShown(i + 1); }, t)); t += 650; } else { // user messages: media gets a touch more dwell time timers.current.push(setTimeout(() => setShown(i + 1), t)); t += (m.type === 'text' ? 1000 : 1350); } }); timers.current.push(setTimeout(run, t + 4600)); }; run(); return () => timers.current.forEach(clearTimeout); }, [started]); React.useEffect(() => { if (feedRef.current) feedRef.current.scrollTop = feedRef.current.scrollHeight; window.lucide && window.lucide.createIcons(); }, [shown, typing, typeLabel]); return (
{/* Copy */}
Conversas que qualificam e convertem, 24 horas por dia} sub="O agente entende a intenção do cliente, responde com o contexto do seu negócio e encaminha as oportunidades certas para a equipe — em qualquer canal." />
{[ ['message-square', 'Respostas naturais', 'Entende perguntas em linguagem real, sem menus engessados.'], ['mic', 'Entende áudio, imagem e PDF', 'Multimodal: ouve áudios, lê imagens e documentos enviados pelo cliente.'], ['filter', 'Qualificação de leads', 'Separa curiosos de oportunidades e prioriza quem está pronto.'], ['share-2', 'Multicanal', 'A mesma inteligência no WhatsApp, Instagram, site e CRM.'], ].map(([ic, t, d], i) => (
{t}
{d}
))}
{/* Phone */}
{/* chat header */}
Agente AR
online
{/* feed */}
{script.slice(0, shown).map((m, i) => )} {typing && }
{/* input */}
Escreva uma mensagem…
); }; /* ---- typing indicator (contextual: ouvindo áudio / analisando imagem / lendo documento) ---- */ const TypingBubble = ({ info }) => { const icon = info ? ({ audio: 'audio-lines', image: 'scan-eye', doc: 'file-search' }[info.kind] || 'sparkles') : null; return (
{info && } {info && {info.label}} {[0, 1, 2].map(d => )}
); }; /* ---- message bubble (text / audio / image / doc) ---- */ const Bubble = ({ m }) => { const agent = m.from === 'agent'; const base = { alignSelf: agent ? 'flex-end' : 'flex-start', maxWidth: '82%', background: agent ? 'linear-gradient(135deg,#005EFF,#00D4FF)' : 'var(--ar-bg-card)', border: agent ? 'none' : '1px solid rgba(255,255,255,0.08)', color: agent ? '#fff' : 'var(--ar-text-main)', borderRadius: agent ? '14px 14px 4px 14px' : '14px 14px 14px 4px', boxShadow: agent ? '0 6px 18px rgba(0,94,255,0.3)' : 'none', }; let inner; if (m.type === 'audio') { const bars = [5, 9, 14, 8, 12, 16, 7, 11, 15, 6, 10, 13, 8, 5, 9, 12, 7]; inner = (
{bars.map((h, i) => )}
{m.dur}
); } else if (m.type === 'image') { inner = (
{/* stylized product scene */}
{m.caption}
); } else if (m.type === 'doc') { inner = (
{m.file}
PDF · {m.size}
); } else { inner =
{m.text}
; } return (
{inner}
); }; const Phone = ({ children }) => (
{children}
); window.WhatsAppSim = WhatsAppSim;