/* 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 (
{/* Soft radial backdrop */}
{/* Center hub */}
{/* ping rings */}
Dominus
core
{/* Orbital rings */}
{/* Connection lines SVG */} {data.map((it, i) => { const a = ((i / data.length) * 360 + rotation) % 360; const rad = (a * Math.PI) / 180; const radius = 280; const x = 320 + Math.cos(rad) * radius; const y = 320 + Math.sin(rad) * radius; const isAct = active === it.id; const isRel = isRelated(it.id); const strong = isAct || isRel; return ( ); })} {/* Nodes */} {data.map((it, i) => { const a = ((i / data.length) * 360 + rotation) % 360; const rad = (a * Math.PI) / 180; const radius = 280; const x = Math.cos(rad) * radius; const y = Math.sin(rad) * radius; const zIndex = Math.round(100 + 50 * Math.cos(rad)); const opacity = Math.max(0.55, 0.55 + 0.45 * ((1 + Math.sin(rad)) / 2)); const isExp = !!expanded[it.id]; const isRel = isRelated(it.id); const isPulse = !!pulse[it.id]; const sb = statusBadge(it.status); return (
{ e.stopPropagation(); toggle(it.id); }} style={{ position: 'absolute', transform: `translate(${x}px, ${y}px)`, zIndex: isExp ? 300 : zIndex, opacity: isExp ? 1 : opacity, transition: 'transform 0.5s cubic-bezier(.2,.7,.2,1), opacity 0.5s ease', cursor: 'pointer' }} > {/* Glow halo */}
{/* Node chip */}
{it.glyph}
{it.label}
{/* Expanded card */} {isExp && (
e.stopPropagation()}>
{sb.text} {it.key.toUpperCase()}_{String(it.id).padStart(2, '0')}
{it.label}

{it.desc}

SINCRONIA {it.energy}%
{it.relatedIds.length > 0 && (
Nós conectados
{it.relatedIds.slice(0, 6).map(rid => { const r = data.find(d => d.id === rid); if (!r) return null; return ( ); })}
)}
)}
); })}
); } function ZapIcon() { return ( ); } function LinkIcon() { return ( ); } function ArrowRightTiny() { return ( ); } // Keep window.IntegrationMap as the new orbital function IntegrationMap() { return ; } window.IntegrationMap = IntegrationMap; window.RadialOrbital = RadialOrbital;