import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import { useAuth } from '../context/AuthContext'; import { LogIn, UserPlus, Eye, EyeOff } from 'lucide-react'; const API_BASE = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/api'; /* ─── Typewriter ─── */ const useTypewriter = (words: string[], speed = 80, pause = 2200) => { const [index, setIndex] = useState(0); const [sub, setSub] = useState(0); const [deleting, setDeleting] = useState(false); const [text, setText] = useState(''); useEffect(() => { const word = words[index % words.length]; const timer = setTimeout(() => { if (!deleting) { setText(word.slice(0, sub + 1)); setSub(s => s + 1); if (sub + 1 === word.length) setTimeout(() => setDeleting(true), pause); } else { setText(word.slice(0, sub - 1)); setSub(s => s - 1); if (sub - 1 === 0) { setDeleting(false); setIndex(i => i + 1); } } }, deleting ? speed / 2 : speed); return () => clearTimeout(timer); }, [sub, deleting, index]); return text; }; const Login: React.FC = () => { const [isRegistering, setIsRegistering] = useState(false); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const [showPassword, setShowPassword] = useState(false); const { login } = useAuth(); const navigate = useNavigate(); const rotatingWords = ['Knowledge Graphs.', 'Logic Engines.', 'LLM Reasoning.', 'Entity Networks.', 'Semantic Search.']; const rotating = useTypewriter(rotatingWords); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(''); setLoading(true); try { if (isRegistering) { const regRes = await fetch(`${API_BASE}/auth/register`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password, scopes: ['read', 'write', 'admin'] }), }); if (!regRes.ok) { const errData = await regRes.json(); throw new Error(errData.detail || 'Registration failed'); } } const loginRes = await fetch(`${API_BASE}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }), }); if (!loginRes.ok) { const errData = await loginRes.json(); throw new Error(errData.detail || 'Login failed'); } const { access_token } = await loginRes.json(); const userRes = await fetch(`${API_BASE}/auth/me`, { headers: { Authorization: `Bearer ${access_token}` }, }); if (!userRes.ok) throw new Error('Failed to fetch user profile'); const user = await userRes.json(); login(access_token, user); navigate('/'); } catch (err: any) { setError(err.message); } finally { setLoading(false); } }; return (
{/* ── Brand mark top-left ── */}
CORTEX
{/* ── Version badge top-right ── */}
v1.0 · PRODUCTION
{/* ── Giant background wordmark ── */}
COR
TEX
{/* ── Hero headline, top-center area ── */}
AGENTIC KNOWLEDGE PLATFORM

Enterprise-grade
{rotating}|

{/* ── Floating stat chips ── */}
Neo4j
GRAPH ENGINE
ReACT
AGENT LOOP
EVAL
SCORING
Multi-hop
REASONING
{/* ── Vertical feature list bottom-left ── */}
CAPABILITIES
{[ 'Document ingestion → Knowledge graph', 'LLM entity & relationship extraction', 'Agentic multi-step query reasoning', 'Hallucination risk scoring', 'Ontology drift detection & governance', 'Entity enrichment & deduplication', 'Interactive D3 force visualization', 'Export: JSON · Cypher · GraphML', ].map((f, i) => (
{f}
))}
{/* ── Horizontal tech stack bottom-center ── */}
{['FastAPI', 'Neo4j', 'Redis', 'Celery', 'Gemini', 'LangChain'].map(t => ( {t} ))}
{/* ── Bottom-right quote ── */}
"Knowledge is only useful
when it can be reasoned over."
{/* ── Decorative rule lines ── */}
{/* ── LOGIN CARD (right side, vertically centered) ── */}

{isRegistering ? 'INITIALIZE ACCESS' : 'SYSTEM AUTH'}

{error &&
{error}
}
setUsername(e.target.value)} required className="mono-text" autoComplete="username" />
setPassword(e.target.value)} required className="mono-text" autoComplete="current-password" />

CORTEX PLATFORM SECURED · ENCRYPTED
); }; export default Login;