/* Radial orbital integration map — animated nodes orbiting Dominus core */ const { useState: useStateO, useEffect: useEffectO, useRef: useRefO } = React; const INTEGRATIONS = [ { id: 1, key: 'wa', label: 'WhatsApp', glyph: 'WA', color: '#22c55e', desc: 'Atendimento e vendas conversacionais. Mensagens entram, viram leads e ações no CRM.', status: 'completed', energy: 100, relatedIds: [6, 5, 4, 10] }, { id: 2, key: 'ig', label: 'Instagram', glyph: 'IG', color: '#E1306C', desc: 'DMs e comentários capturados como leads, integrados ao funil de vendas.', status: 'completed', energy: 92, relatedIds: [6, 5] }, { id: 3, key: 'gs', label: 'Google Sheets', glyph: 'GS', color: '#0F9D58', desc: 'Leitura e escrita em planilhas para alimentar relatórios e operações simples.', status: 'completed', energy: 86, relatedIds: [5, 4] }, { id: 4, key: 'sb', label: 'Supabase', glyph: 'SB', color: '#3ECF8E', desc: 'Banco de dados e auth em tempo real para sistemas sob medida.', status: 'completed', energy: 98, relatedIds: [5, 6, 1, 12] }, { id: 5, key: 'n8', label: 'n8n', glyph: 'n8', color: '#EA4B71', desc: 'Orquestrador central das automações. Conecta todos os outros nós.', status: 'completed', energy: 100, relatedIds: [1, 2, 3, 4, 6, 11, 12] }, { id: 6, key: 'crm', label: 'CRM', glyph: 'CR', color: '#2563EB', desc: 'Pipeline, contatos, oportunidades e cadência de follow-up unificados.', status: 'completed', energy: 96, relatedIds: [1, 2, 4, 11, 7] }, { id: 7, key: 'site', label: 'Site', glyph: '>',color: '#0B0F19', desc: 'Landing pages rápidas e otimizadas, conectadas ao CRM e ao tracking.', status: 'completed', energy: 90, relatedIds: [8, 9, 6] }, { id: 8, key: 'meta', label: 'Meta Ads', glyph: 'MA', color: '#1877F2', desc: 'Webhook de leads e conversões offline sincronizados em tempo real.', status: 'in-progress', energy: 78, relatedIds: [7, 6] }, { id: 9, key: 'ga', label: 'Google Ads', glyph: 'GA', color: '#EA4335', desc: 'Conversões offline enviadas via API para otimizar campanhas reais.', status: 'in-progress', energy: 74, relatedIds: [7, 6] }, { id: 10, key: 'pr', label: 'Impressora', glyph: 'PR', color: '#6B7280', desc: 'Pedido cai no WhatsApp e imprime direto na cozinha. Zero digitação.', status: 'completed', energy: 88, relatedIds: [1, 5] }, { id: 11, key: 'em', label: 'E-mail', glyph: '@', color: '#C6A15B', desc: 'Disparos transacionais, cadência de follow-up e notificações internas.', status: 'completed', energy: 84, relatedIds: [5, 6] }, { id: 12, key: 'wh', label: 'Webhooks', glyph: 'WH', color: '#5CE1E6', desc: 'Eventos customizados para qualquer sistema externo. Saída e entrada.', status: 'completed', energy: 100, relatedIds: [5, 4] } ]; function RadialOrbital({ data = INTEGRATIONS }) { const [expanded, setExpanded] = useStateO({}); const [rotation, setRotation] = useStateO(0); const [autoRotate, setAutoRotate] = useStateO(true); const [pulse, setPulse] = useStateO({}); const [active, setActive] = useStateO(null); const containerRef = useRefO(null); const orbitRef = useRefO(null); // auto-rotate useEffectO(() => { if (!autoRotate) return; const id = setInterval(() => { setRotation(prev => +((prev + 0.25) % 360).toFixed(3)); }, 50); return () => clearInterval(id); }, [autoRotate]); const handleBg = (e) => { if (e.target === containerRef.current || e.target === orbitRef.current) { setExpanded({}); setActive(null); setPulse({}); setAutoRotate(true); } }; const getRelated = (id) => { const item = data.find(d => d.id === id); return item ? item.relatedIds : []; }; const toggle = (id) => { setExpanded(prev => { const next = {}; // close all others, toggle target const isOpening = !prev[id]; if (isOpening) next[id] = true; return next; }); const isOpening = !expanded[id]; if (isOpening) { setActive(id); setAutoRotate(false); const rel = {}; getRelated(id).forEach(r => rel[r] = true); setPulse(rel); // center node: rotate so this node is at top const idx = data.findIndex(d => d.id === id); const targetAngle = (idx / data.length) * 360; setRotation(270 - targetAngle); } else { setActive(null); setAutoRotate(true); setPulse({}); } }; const isRelated = (id) => { if (!active) return false; return getRelated(active).includes(id); }; const statusBadge = (status) => { if (status === 'completed') return { text: 'ATIVO', bg: '#fff', color: '#0B0F19', border: '#fff' }; if (status === 'in-progress') return { text: 'SINCRONIZANDO', bg: 'transparent', color: '#5CE1E6', border: '#5CE1E6' }; return { text: 'PENDENTE', bg: 'rgba(255,255,255,0.06)', color: 'rgba(255,255,255,0.7)', border: 'rgba(255,255,255,0.3)' }; }; return (
{it.desc}