/** * AiOverview — Painel Stack IA (3 Camadas de Execução) * Rota: /ai * @author Descomplicar® | @link descomplicar.pt | @copyright 2026 */ import { useState, useEffect, useCallback } from 'react' import { motion } from 'framer-motion' import { Brain, Cpu, Bot, Zap, Shield, Database, BookOpen, Layers, RefreshCw, CheckCircle2, AlertTriangle, Circle, } from 'lucide-react' // --- Types --- interface AiLayerItem { metric: string value: number detail: string } interface AiLayer { name: string label: string items: AiLayerItem[] } interface TransversalSystem { name: string status: 'active' | 'warning' | 'inactive' detail: string } interface CarlConfig { domains: string[] total_rules: number } interface AiDashboard { layers: AiLayer[] transversal: TransversalSystem[] carl: CarlConfig notebooks: number last_updated: string } // --- Animation variants --- const containerVariants = { hidden: { opacity: 0 }, show: { opacity: 1, transition: { staggerChildren: 0.06 } }, } const itemVariants = { hidden: { opacity: 0, y: 20 }, show: { opacity: 1, y: 0, transition: { type: 'spring' as const, stiffness: 300, damping: 30 }, }, } // --- Configuração visual por camada --- interface LayerConfig { gradient: string border: string badge: string valueCls: string glow: string icon: React.ElementType } const LAYER_CONFIG: Record = { 'Claude Code': { gradient: 'from-violet-500/15 to-purple-500/10', border: 'border-violet-500/25', badge: 'bg-violet-500/20 text-violet-300 border border-violet-500/30', valueCls: 'text-violet-300', glow: 'shadow-[0_0_20px_rgba(139,92,246,0.15)]', icon: Brain, }, 'n8n': { gradient: 'from-amber-500/15 to-orange-500/10', border: 'border-amber-500/25', badge: 'bg-amber-500/20 text-amber-300 border border-amber-500/30', valueCls: 'text-amber-300', glow: 'shadow-[0_0_20px_rgba(245,158,11,0.15)]', icon: Zap, }, 'Paperclip': { gradient: 'from-cyan-500/15 to-teal-500/10', border: 'border-cyan-500/25', badge: 'bg-cyan-500/20 text-cyan-300 border border-cyan-500/30', valueCls: 'text-cyan-300', glow: 'shadow-[0_0_20px_rgba(6,182,212,0.15)]', icon: Bot, }, } // --- Sub-components --- const MetricCard = ({ item, valueCls, }: { item: AiLayerItem valueCls: string }) => ( {item.metric} {item.value} {item.detail} ) const LayerSection = ({ layer }: { layer: AiLayer }) => { const cfg = LAYER_CONFIG[layer.name] ?? LAYER_CONFIG['Claude Code'] const Icon = cfg.icon return ( {/* Cabeçalho da camada */}

{layer.name}

{layer.label}

{/* Cards de métricas */}
{layer.items.map((item) => ( ))}
) } const TransversalStatusIcon = ({ status }: { status: string }) => { if (status === 'active') { return } if (status === 'warning') { return } return } const TransversalCard = ({ sys }: { sys: TransversalSystem }) => { const borderCls = sys.status === 'active' ? 'border-emerald-500/20' : sys.status === 'warning' ? 'border-amber-500/20' : 'border-white/8' return (

{sys.name}

{sys.detail}

) } const DomainPill = ({ name }: { name: string }) => ( {name} ) // --- Página principal --- export default function AiOverview() { const [data, setData] = useState(null) const [loading, setLoading] = useState(true) const [refreshing, setRefreshing] = useState(false) const fetchData = useCallback(async () => { setRefreshing(true) try { const response = await fetch('/api/ai') if (!response.ok) throw new Error('Failed to fetch /api/ai') const json = await response.json() setData(json) } catch { console.error('Falha ao carregar dados do stack IA') } finally { setLoading(false) setRefreshing(false) } }, []) useEffect(() => { fetchData() }, [fetchData]) const formatDate = (iso: string) => { // Converter YYYY-MM-DD para DD-MM-YYYY const [y, m, d] = iso.split('-') return `${d}-${m}-${y}` } if (loading) { return (

A carregar stack IA...

) } if (!data) { return (

Não foi possível carregar os dados.

) } return (
{/* Cabeçalho */}

Stack IA — 3 Camadas de Execução

Inventário completo do sistema IA Descomplicar®

Última actualização: {formatDate(data.last_updated)}
{/* Sumário global — pill badges */} {data.notebooks} Notebooks NotebookLM {data.carl.total_rules} Regras CARL {data.carl.domains.length} Domínios contextuais {/* 3 Camadas */} {data.layers.map((layer) => ( ))} {/* Sistemas Transversais */}

Sistemas Transversais

{data.transversal.length} sistemas
{data.transversal.map((sys) => ( ))}
{/* CARL — domínios contextuais */}

CARL — Contexto Adaptativo

{/* Métricas CARL */}

{data.carl.domains.length}

Domínios

{data.carl.total_rules}

Regras

{/* Divisor */}
{/* Domínios como pills */} {data.carl.domains.map((domain) => ( ))}
{/* Knowledge Notebooks */}

Knowledge Base

{data.notebooks}

Notebooks NotebookLM activos — fonte de conhecimento para todos os agentes

) }