/* ============================================================ CodeSection.jsx — "Como desenvolvemos" Editor com simulação de codificação AO VIVO: o código é digitado caractere a caractere (cursor + rolagem automática), ciclando pelas abas agente.ts · fluxo.n8n.json · supabase.sql. Clicar numa aba reinicia a digitação dela. ============================================================ */ /* cores de token */ const CS_COL = { kw: '#3D8BFF', fn: '#00D4FF', str: '#1FD17B', com: '#6B7591', punc: '#A7B0C5', txt: '#C9D3E8', num: '#FFB020' }; /* Cada programa: lista de linhas; cada linha: lista de tokens [texto, corKey?]. Token sem corKey → cor padrão (txt). Linha vazia [] = quebra em branco. */ const CS_PROGRAMS = [ { name: 'agente.ts', lines: [ [['// Agente de atendimento da AR — multicanal', 'com']], [['import', 'kw'], [' { '], ['criarAgente', 'fn'], [' } '], ['from', 'kw'], [' '], ['"@ar/core"', 'str'], [';']], [['import', 'kw'], [' { '], ['whatsapp', 'fn'], [', '], ['crm', 'fn'], [' } '], ['from', 'kw'], [' '], ['"@ar/canais"', 'str'], [';']], [], [['export const', 'kw'], [' '], ['agente', 'fn'], [' = '], ['criarAgente', 'fn'], ['({']], [[' nome: '], ['"Atendimento AR"', 'str'], [',']], [[' modelo: '], ['"claude / gpt"', 'str'], [',']], [[' canais: ['], ['whatsapp', 'fn'], [', '], ['crm', 'fn'], ['],']], [[' '], ['aoReceber', 'fn'], ['('], ['msg', 'punc'], [') {']], [[' '], ['const', 'kw'], [' intent = '], ['await', 'kw'], [' '], ['classificar', 'fn'], ['(msg);']], [[' '], ['if', 'kw'], [' (intent.lead) '], ['enviarParaCRM', 'fn'], ['(msg);']], [[' '], ['return', 'kw'], [' '], ['responder', 'fn'], ['(msg, { contexto: '], ['true', 'num'], [' });']], [[' },']], [['});']], [], [['// → deploy automático via GitHub Actions', 'com']], ], }, { name: 'fluxo.n8n.json', lines: [ [['{', 'punc']], [[' '], ['"workflow"', 'str'], [': '], ['"qualificacao-de-leads"', 'str'], [',']], [[' '], ['"trigger"', 'str'], [': '], ['"webhook:whatsapp"', 'str'], [',']], [[' '], ['"nodes"', 'str'], [': [']], [[' { '], ['"type"', 'str'], [': '], ['"ai.classificar"', 'str'], [' },']], [[' { '], ['"type"', 'str'], [': '], ['"supabase.insert"', 'str'], [' },']], [[' { '], ['"type"', 'str'], [': '], ['"crm.criarOportunidade"', 'str'], [' },']], [[' { '], ['"type"', 'str'], [': '], ['"notificar.equipe"', 'str'], [' }']], [[' ],']], [[' '], ['"agendamento"', 'str'], [': '], ['"realtime"', 'str'], [',']], [[' '], ['"retry"', 'str'], [': '], ['3', 'num'], [',']], [[' '], ['"ativo"', 'str'], [': '], ['true', 'num']], [['}', 'punc']], ], }, { name: 'supabase.sql', lines: [ [['-- Base de leads qualificados (Supabase)', 'com']], [['create table', 'kw'], [' '], ['leads', 'fn'], [' (']], [[' id '], ['uuid', 'kw'], [' '], ['primary key', 'kw'], [' '], ['default', 'kw'], [' '], ['gen_random_uuid', 'fn'], ['(),']], [[' nome '], ['text', 'kw'], [',']], [[' canal '], ['text', 'kw'], [' '], ['check', 'kw'], [' (canal '], ['in', 'kw'], [' ('], ["'whatsapp'", 'str'], [','], ["'site'", 'str'], [')),']], [[' intent '], ['text', 'kw'], [',']], [[' score '], ['int', 'kw'], [' '], ['default', 'kw'], [' '], ['0', 'num'], [',']], [[' criado_em '], ['timestamptz', 'kw'], [' '], ['default', 'kw'], [' '], ['now', 'fn'], ['()']], [[');']], [], [['create index', 'kw'], [' '], ['on', 'kw'], [' '], ['leads', 'fn'], [' (score '], ['desc', 'kw'], [');']], ], }, ]; const csLineLen = (line) => line.reduce((a, t) => a + t[0].length, 0); const csTotal = (lines) => lines.reduce((a, l) => a + csLineLen(l) + 1, 0); // +1 = quebra de linha /* devolve as linhas reveladas até `revealed` caracteres + posição do cursor */ function csTypeLines(lines, revealed) { const out = []; let rem = revealed, caretAt = -1; for (let i = 0; i < lines.length; i++) { const line = lines[i], len = csLineLen(line); if (rem >= len) { out.push(line); rem -= len + 1; // consome a linha + sua quebra if (rem < 0) { caretAt = i; break; } } else { const partial = []; let r = rem; for (const t of line) { if (r <= 0) break; if (t[0].length <= r) { partial.push(t); r -= t[0].length; } else { partial.push([t[0].slice(0, r), t[1]]); r = 0; } } out.push(partial); caretAt = i; break; } } if (caretAt === -1 && out.length) caretAt = out.length - 1; return { out, caretAt }; } const CodeSection = () => { const [tab, setTab] = React.useState(0); const [revealed, setRevealed] = React.useState(0); const codeRef = React.useRef(null); const badges = ['Claude Code', 'Codex', 'GPT', 'Git / GitHub', 'n8n', 'Supabase', 'APIs', 'Integrações']; const program = CS_PROGRAMS[tab]; const total = React.useMemo(() => csTotal(program.lines), [tab]); /* motor de digitação: revela caracteres; ao terminar, segura e troca de aba. Exceção consciente à regra #7 (prefers-reduced-motion): esta animação é o coração da seção "Como desenvolvemos", então roda sempre — decisão do cliente. */ React.useEffect(() => { setRevealed(0); let cur = 0, hold = 0; const id = setInterval(() => { if (document.hidden) return; // aba em segundo plano: não gasta CPU nem dispara re-render if (cur >= total) { if (++hold > 55) { clearInterval(id); setTab(t => (t + 1) % CS_PROGRAMS.length); } return; } cur = Math.min(total, cur + 2 + Math.floor(Math.random() * 3)); setRevealed(cur); }, 26); return () => clearInterval(id); }, [tab, total]); /* rolagem automática (código "subindo") */ React.useEffect(() => { if (codeRef.current) codeRef.current.scrollTop = codeRef.current.scrollHeight; }, [revealed]); /* ícones estáticos (barra de título / rodapé) */ React.useEffect(() => { window.lucide && window.lucide.createIcons(); }, [tab]); const { out, caretAt } = csTypeLines(program.lines, revealed); const typing = revealed < total; return (
{/* Editor */}
{/* title bar */}
AR · workspace — agente-atendimento {typing ? 'IA escrevendo…' : 'código gerado'}
{/* tabs */}
{CS_PROGRAMS.map((p, i) => ( ))}
{/* progress bar */}
{/* code body (rola automaticamente) */}
{out.map((_, i) =>
{i + 1}
)}
{out.map((line, i) => (
{line.map((t, j) => {t[0]})} {i === caretAt && }
))}
{/* terminal footer */}
agente ativo 847 atendimentos hoje 94% resolvidos
{/* Copy + badges */}
Da ideia ao ar em semanas — com IA, automação e engenharia moderna} sub="Usamos ferramentas de IA de última geração para entregar mais rápido, com menos custo e mais qualidade — sem que sua empresa precise montar uma equipe de tecnologia." subMobile="IA e engenharia moderna para entregar mais rápido, com menos custo." maxWidth={520} />
{badges.map(b => ( {b} ))}
); }; window.CodeSection = CodeSection;