Spaces:
Sleeping
Sleeping
File size: 8,245 Bytes
bb0f10e 084aac3 bb0f10e 6b0e3cb 084aac3 bb0f10e 084aac3 1d7156d bb0f10e 084aac3 bb0f10e 084aac3 bb0f10e 1d7156d bb0f10e 1d7156d 084aac3 1d7156d bb0f10e 1d7156d bb0f10e 084aac3 1d7156d 6b0e3cb 1d7156d bb0f10e 1d7156d bb0f10e 1d7156d bb0f10e 084aac3 1d7156d bb0f10e 6b0e3cb bb0f10e 1d7156d bb0f10e 1d7156d 084aac3 1d7156d bb0f10e 6b0e3cb bb0f10e 1d7156d bb0f10e 1d7156d 6b0e3cb 1d7156d bb0f10e 1d7156d 6b0e3cb bb0f10e 1d7156d bb0f10e 6b0e3cb bb0f10e 1d7156d bb0f10e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | import React, { useState, useEffect, useCallback } from 'react';
import { HashRouter, Routes, Route, Link, useLocation, Navigate, useNavigate } from 'react-router-dom';
import {
Bell, LogOut, Activity, ChevronRight, Cpu, Settings as SettingsIcon, Terminal, Loader2, Key,
ShieldCheck, Zap, ArrowRight, ShieldAlert, Globe, Lock, Database, Shield, ZapOff, Fingerprint, Code,
Server, Layers, Network
} from 'lucide-react';
import { routes } from './views/routes';
import Login from './views/Login';
import Landing from './views/Landing';
import PrivacyPolicy from './views/PrivacyPolicy';
import Documentation from './views/Documentation';
import Airdrop from './views/Airdrop';
import { apiClient } from './services/api';
import { UserSession } from './types/index';
const SidebarItem: React.FC<{ icon: any, label: string, path: string, active: boolean }> = ({ icon: Icon, label, path, active }) => (
<Link
to={path}
className={`flex items-center justify-between px-6 py-4 rounded-2xl transition-all duration-500 group ${
active
? 'bg-white text-black shadow-2xl scale-[1.02]'
: 'text-zinc-500 hover:text-white hover:bg-zinc-900/50'
}`}
>
<div className="flex items-center space-x-4">
<Icon size={18} className={`${active ? 'text-black' : 'text-zinc-600 group-hover:text-blue-500'} transition-colors duration-500`} />
<span className="font-black text-[10px] uppercase tracking-[0.2em]">{label}</span>
</div>
{active && <ChevronRight size={14} />}
</Link>
);
const PrivateTerminal = ({ user, onLogout }: { user: UserSession, onLogout: () => void }) => {
const location = useLocation();
const navigate = useNavigate();
const handleTerminate = async () => {
await onLogout();
navigate('/');
};
return (
<div className="flex min-h-screen bg-[#020202] text-zinc-400 antialiased font-sans">
<aside className="w-80 fixed h-full bg-[#050505] border-r border-zinc-900 p-8 flex flex-col z-50">
<div className="mb-14 px-4 flex items-center space-x-4">
<div className="w-12 h-12 bg-white rounded-2xl flex items-center justify-center shadow-2xl">
<Cpu size={24} className="text-black" />
</div>
<div>
<h1 className="text-lg font-black italic tracking-tighter text-white uppercase leading-none">
AIBanking <span className="text-blue-500 not-italic">Core</span>
</h1>
<p className="text-[9px] uppercase tracking-[0.4em] font-bold text-zinc-600 mt-1">Institutional Mesh</p>
</div>
</div>
<nav className="flex-1 space-y-2 overflow-y-auto custom-scrollbar pr-2 pb-10">
<div className="space-y-10">
{['core', 'registry', 'finance', 'intelligence', 'system', 'admin'].map(cat => {
const catRoutes = routes.filter(r => r.showInSidebar && r.category === cat);
if (catRoutes.length === 0) return null;
return (
<div key={cat} className="space-y-3">
<p className="px-6 text-[8px] font-black uppercase text-zinc-700 tracking-[0.5em] mb-4">{cat.toUpperCase()}_SUITE</p>
{catRoutes.map((route) => (
<SidebarItem
key={route.path}
icon={route.icon}
label={route.label}
path={route.path}
active={location.pathname === route.path}
/>
))}
</div>
);
})}
</div>
</nav>
<div className="mt-auto pt-10 border-t border-zinc-900 space-y-4">
<button
onClick={handleTerminate}
className="w-full flex items-center gap-4 px-6 py-4 rounded-2xl text-rose-500 hover:bg-rose-500/10 transition-all font-black text-[10px] uppercase tracking-widest border border-transparent hover:border-rose-500/20"
>
<ShieldAlert size={16} />
<span>Terminate Link</span>
</button>
<div className="mt-8 p-6 bg-zinc-950 border border-zinc-900 rounded-[2rem] flex items-center justify-between shadow-2xl">
<div className="flex items-center gap-3">
<Activity size={16} className="text-emerald-500" />
<span className="text-[9px] font-black uppercase tracking-widest text-zinc-500">Node Sync: 100%</span>
</div>
<div className="w-2 h-2 bg-emerald-500 rounded-full animate-pulse shadow-[0_0_8px_#10b981]"></div>
</div>
</div>
</aside>
<main className="flex-1 ml-80 min-h-screen flex flex-col relative z-10">
<header className="h-24 flex items-center justify-between px-10 bg-transparent relative z-50">
<div className="flex items-center space-x-6">
<div className="flex flex-col">
<h1 className="text-xl font-black tracking-tighter text-white italic leading-none uppercase">SYSTEM <span className="text-blue-500 not-italic">CONSOLE</span></h1>
<p className="text-[10px] text-zinc-600 font-black uppercase tracking-[0.3em] mt-1 flex items-center gap-2">
<Terminal size={10} /> ROOT: {user.name.toUpperCase()}
</p>
</div>
</div>
<div className="flex items-center space-x-6">
<div className="text-right">
<p className="text-xs font-black text-white uppercase italic tracking-tighter">{user.name}</p>
<p className="text-[9px] text-zinc-600 uppercase tracking-[0.2em] font-bold">{user.role}</p>
</div>
<button onClick={handleTerminate} className="w-12 h-12 rounded-2xl bg-zinc-950 border border-zinc-900 flex items-center justify-center hover:border-rose-500/50 transition-all shadow-2xl">
<LogOut size={18} className="text-zinc-600" />
</button>
</div>
</header>
<div className="px-10 pb-20">
<Routes>
{routes.map((route) => (
<Route key={route.path} path={route.path} element={<route.component />} />
))}
<Route path="*" element={<Navigate to="/overview" replace />} />
</Routes>
</div>
</main>
</div>
);
};
const App: React.FC = () => {
const [currentUser, setCurrentUser] = useState<UserSession | null>(null);
const [isAuthChecked, setIsAuthChecked] = useState<boolean>(false);
const checkStatus = useCallback(async () => {
try {
const { user } = await apiClient.auth.me();
setCurrentUser(user);
} catch (e) {
console.error("Session sync failed.");
} finally {
setIsAuthChecked(true);
}
}, []);
useEffect(() => {
checkStatus();
window.addEventListener('auth-update', checkStatus);
return () => window.removeEventListener('auth-update', checkStatus);
}, [checkStatus]);
if (!isAuthChecked) {
return (
<div className="min-h-screen bg-black flex flex-col items-center justify-center space-y-12">
<div className="relative">
<div className="w-24 h-24 border-4 border-zinc-900 border-t-blue-500 rounded-full animate-spin"></div>
<Cpu className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-white" size={32} />
</div>
<p className="text-[11px] font-black text-zinc-700 uppercase tracking-[0.8em] animate-pulse italic">Synchronizing Node Registry...</p>
</div>
);
}
return (
<HashRouter>
<Routes>
<Route path="/" element={<Landing />} />
<Route path="/login" element={currentUser ? <Navigate to="/overview" replace /> : <Login />} />
<Route path="/airdrop" element={<Airdrop />} />
<Route path="/manifesto" element={<PrivacyPolicy />} />
<Route path="/documentation" element={<Documentation />} />
<Route path="/*" element={currentUser ? (
<PrivateTerminal user={currentUser} onLogout={async () => { await apiClient.auth.logout(); setCurrentUser(null); }} />
) : (
<Navigate to="/" replace />
)} />
</Routes>
</HashRouter>
);
};
export default App; |