import React, { useEffect, useState, useRef } from 'react';
import { useAuth } from '../context/AuthContext';
import { Network, Server, Cpu, Database, Activity, ArrowRight, Zap, GitBranch, MessageSquare, TrendingUp, RefreshCw } from 'lucide-react';
const API_BASE = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/api';
// Animated counter hook
function useCountUp(target: number, duration = 1200) {
const [val, setVal] = useState(0);
const prev = useRef(0);
useEffect(() => {
if (target === 0) { setVal(0); return; }
const start = prev.current;
const diff = target - start;
const startTime = performance.now();
const tick = (now: number) => {
const t = Math.min((now - startTime) / duration, 1);
const ease = 1 - Math.pow(1 - t, 3);
setVal(Math.round(start + diff * ease));
if (t < 1) requestAnimationFrame(tick);
else prev.current = target;
};
requestAnimationFrame(tick);
}, [target]);
return val;
}
const StatCounter: React.FC<{ value: number | string; label: string; suffix?: string }> = ({ value, label, suffix = '' }) => {
const numVal = typeof value === 'number' ? value : parseInt(String(value)) || 0;
const animated = useCountUp(numVal);
return (
{typeof value === 'number' ? animated : value}{suffix}
{label}
);
};
const Home: React.FC = () => {
const { token, logout, user } = useAuth();
const [health, setHealth] = useState(null);
const [stats, setStats] = useState(null);
const [myStats, setMyStats] = useState(null);
const [loading, setLoading] = useState(true);
const [lastRefresh, setLastRefresh] = useState(new Date());
const fetchData = async () => {
setLoading(true);
try {
const [healthRes, statsRes, myStatsRes] = await Promise.all([
fetch(`${API_BASE}/system/health`),
fetch(`${API_BASE}/system/stats`, { headers: { Authorization: `Bearer ${token}` } }),
fetch(`${API_BASE}/system/my-stats`, { headers: { Authorization: `Bearer ${token}` } }).catch(() => null),
]);
if (statsRes.status === 401) { logout(); return; }
if (healthRes.ok) setHealth(await healthRes.json());
if (statsRes.ok) setStats(await statsRes.json());
if (myStatsRes?.ok) setMyStats(await myStatsRes.json());
} catch (err) {
console.error('Failed to fetch system data', err);
} finally {
setLoading(false);
setLastRefresh(new Date());
}
};
useEffect(() => {
fetchData();
const interval = setInterval(fetchData, 30000);
return () => clearInterval(interval);
}, [token]);
const isOnline = (v: boolean | undefined) => v === true;
const systemOk = health ? (isOnline(health.neo4j_connected) && isOnline(health.redis_connected)) : false;
return (
{/* ── Hero ─────────────────────────────────────── */}
CORTEX PLATFORM
Agentic Knowledge
Intelligence
Production-grade knowledge graph · Real-time extraction · Multi-hop reasoning
{loading ? 'CHECKING...' : systemOk ? 'SYSTEM OPERATIONAL' : 'SYSTEM DEGRADED'}
{[
{ label: 'NEO4J', ok: isOnline(health?.neo4j_connected) },
{ label: 'REDIS', ok: isOnline(health?.redis_connected) },
{ label: `${health?.workers_active ?? 0} WORKERS`, ok: true, neutral: true },
{ label: 'API', ok: true },
].map(s => (
{s.label}
{s.neutral ? 'ACTIVE' : s.ok ? 'CONNECTED' : 'OFFLINE'}
))}
{/* ── Platform Metrics ─────────────────────────── */}
PLATFORM METRICS
{stats?.ontology_version ?? '—'}
ONTOLOGY VER
{/* ── Main Grid ────────────────────────────────── */}
{/* Quick Actions */}
{[
{ href: '/process', icon:
, label: 'INGEST DOCUMENTS', desc: 'Upload PDFs, text, or crawl URLs' },
{ href: '/interact', icon: , label: 'QUERY KNOWLEDGE', desc: 'Ask questions across the graph' },
{ href: '/simulate', icon: , label: 'EXPLORE NODES', desc: 'Interactive D3 force visualization' },
{ href: '/ontology', icon: , label: 'MANAGE ONTOLOGY', desc: 'Edit schema & run AI refinement' },
{ href: '/insights', icon: ,label: 'INSIGHTS', desc: 'Quality metrics & AI reports' },
].map(a => (
{a.icon}
))}
{/* Right column: My Activity + Feature cards */}
{/* User Activity */}
MY ACTIVITY
{user && @{user.username}}
{myStats?.conversation_count ?? '—'}
CONVERSATIONS
{myStats?.message_count ?? '—'}
QUERIES SENT
{myStats?.last_active ? new Date(myStats.last_active).toLocaleDateString() : '—'}
LAST ACTIVE
{!myStats && (
Start querying the graph to build your activity history.
)}
{/* Graph intelligence card */}
KNOWLEDGE GRAPH
Neo4j-powered semantic knowledge graph. Multi-hop reasoning, entity enrichment, and community detection built in.
{['Entities', 'Relationships', 'Communities', 'Graph Export'].map(tag => (
{tag}
))}
{/* ── Feature Showcase ─────────────────────────── */}
PLATFORM CAPABILITIES
{[
{
icon:
,
title: 'DOCUMENT INGESTION',
desc: 'Ingest PDFs, text files, Markdown, and web URLs. Celery workers extract entities and relationships into the knowledge graph automatically via LLM pipelines.',
color: '#2563eb',
},
{
icon: ,
title: 'GRAPH INTELLIGENCE',
desc: 'Neo4j-powered knowledge graph with rich entity relationships. Query across documents globally or per-source with full ontology control.',
color: '#7c3aed',
},
{
icon: ,
title: 'AGENTIC LOGIC',
desc: 'Multi-step ReACT reasoning agent that searches the graph, retrieves relevant chunks, and streams answers with confidence scoring in real time.',
color: '#059669',
},
{
icon: ,
title: 'LLM-AS-JUDGE',
desc: 'Inline faithfulness evaluation using heuristic scoring. Detects hallucination risk, context precision, and answer quality on every response.',
color: '#d97706',
},
{
icon: ,
title: 'LIVE SIMULATION',
desc: 'Interactive D3 force graph with color-coded entity types, physics controls, fullscreen mode, PNG export, and node detail modals.',
color: '#dc2626',
},
{
icon: ,
title: 'ONTOLOGY DRIFT',
desc: 'Automated schema drift detection that spots when new data no longer fits the current ontology. Propose and approve schema expansions.',
color: '#0891b2',
},
].map(f => (
{f.icon}
{f.title}
{f.desc}
))}
{/* Footer bar */}
CORTEX_PLATFORM
Last refreshed: {lastRefresh.toLocaleTimeString()}
v{health ? '1.0' : '—'} · Neo4j + Redis + Celery
);
};
export default Home;