admin08077 commited on
Commit
bb0f10e
·
verified ·
1 Parent(s): 7350849

Upload 10 files

Browse files
Files changed (7) hide show
  1. App.tsx +156 -140
  2. Dockerfile.txt +25 -0
  3. README.md +17 -13
  4. index.html +3 -1
  5. metadata.json +2 -1
  6. package.json +4 -9
  7. vite.config.ts +28 -5
App.tsx CHANGED
@@ -1,20 +1,8 @@
1
-
2
- import React, { useState, useEffect } from 'react';
3
- import { HashRouter, Routes, Route, Link, useLocation, Navigate } from 'react-router-dom';
4
  import {
5
- Leaf,
6
- Bell,
7
- LogOut,
8
- Activity,
9
- ChevronRight,
10
- Cpu,
11
- Settings as SettingsIcon,
12
- Terminal,
13
- Loader2,
14
- Key as KeyIcon,
15
- ShieldCheck,
16
- ArrowRight,
17
- Zap
18
  } from 'lucide-react';
19
  import { routes } from './views/routes';
20
  import Login from './views/Login';
@@ -25,72 +13,12 @@ import Airdrop from './views/Airdrop';
25
  import { apiClient } from './services/api';
26
  import { UserSession } from './types/index';
27
 
28
- const KeyGateway = ({ onAuthorized }: { onAuthorized: () => void }) => {
29
- const [key, setKey] = useState('');
30
- const [verifying, setVerifying] = useState(false);
31
-
32
- const handleSubmit = (e: React.FormEvent) => {
33
- e.preventDefault();
34
- if (!key.trim()) return;
35
- setVerifying(true);
36
- localStorage.setItem('LQI_API_KEY', key.trim());
37
- setTimeout(() => {
38
- setVerifying(false);
39
- onAuthorized();
40
- }, 1000);
41
- };
42
-
43
- return (
44
- <div className="min-h-screen bg-[#020202] flex items-center justify-center p-6 font-sans">
45
- <div className="absolute inset-0 z-0 opacity-10">
46
- <div className="matrix-line"></div>
47
- </div>
48
- <div className="w-full max-w-md bg-zinc-950 border border-zinc-900 rounded-[3rem] p-12 shadow-2xl relative z-10">
49
- <div className="flex flex-col items-center text-center mb-10">
50
- <div className="w-16 h-16 bg-blue-600/10 text-blue-500 rounded-3xl flex items-center justify-center mb-6 border border-blue-500/20">
51
- <KeyIcon size={32} />
52
- </div>
53
- <h2 className="text-3xl font-black text-white italic tracking-tighter uppercase mb-2">Neural <span className="text-blue-500 not-italic">Handshake</span></h2>
54
- <p className="text-zinc-600 text-[10px] font-black uppercase tracking-[0.3em]">Initialize Gemini Core Access</p>
55
- </div>
56
-
57
- <form onSubmit={handleSubmit} className="space-y-6">
58
- <div className="space-y-2">
59
- <label className="text-[10px] font-black text-zinc-700 uppercase tracking-widest ml-1">LQI_PRIVATE_KEY</label>
60
- <input
61
- type="password"
62
- value={key}
63
- onChange={(e) => setKey(e.target.value)}
64
- placeholder="Enter Gemini API Key..."
65
- className="w-full bg-black border border-zinc-800 focus:border-blue-500 rounded-2xl py-5 px-6 text-white font-mono text-sm outline-none transition-all shadow-inner"
66
- required
67
- />
68
- </div>
69
-
70
- <button
71
- type="submit"
72
- disabled={verifying}
73
- className="w-full bg-blue-600 hover:bg-blue-500 text-white rounded-[2rem] py-5 font-black text-xs uppercase tracking-[0.3em] transition-all flex items-center justify-center gap-3 shadow-xl shadow-blue-900/40"
74
- >
75
- {verifying ? <Loader2 className="animate-spin" size={18} /> : (
76
- <>
77
- <span>Initialize Node</span>
78
- <ArrowRight size={18} />
79
- </>
80
- )}
81
- </button>
82
- </form>
83
- </div>
84
- </div>
85
- );
86
- };
87
-
88
  const SidebarItem: React.FC<{ icon: any, label: string, path: string, active: boolean }> = ({ icon: Icon, label, path, active }) => (
89
  <Link
90
  to={path}
91
  className={`flex items-center justify-between px-6 py-4 rounded-2xl transition-all duration-500 group ${
92
  active
93
- ? 'bg-white text-black shadow-2xl'
94
  : 'text-zinc-500 hover:text-white hover:bg-zinc-900/50'
95
  }`}
96
  >
@@ -103,7 +31,6 @@ const SidebarItem: React.FC<{ icon: any, label: string, path: string, active: bo
103
  );
104
 
105
  const Header = ({ user, onLogout }: { user: UserSession, onLogout: () => void }) => {
106
- const isEsgNeutral = localStorage.getItem('esg_neutral') === 'true';
107
  const location = useLocation();
108
  const currentRoute = routes.find(r => r.path === location.pathname);
109
  const [typedTitle, setTypedTitle] = useState('');
@@ -122,31 +49,23 @@ const Header = ({ user, onLogout }: { user: UserSession, onLogout: () => void })
122
  }, [location.pathname, currentRoute]);
123
 
124
  return (
125
- <header className="h-24 flex items-center justify-between px-10 bg-transparent print:hidden relative z-50">
126
  <div className="flex items-center space-x-6">
127
  <div className="hidden md:flex flex-col">
128
  <h1 className="text-xl font-black tracking-tighter text-white italic leading-none uppercase">
129
- {typedTitle} <span className="text-blue-500 not-italic block md:inline">NODE</span>
130
  </h1>
131
  <p className="text-[10px] text-zinc-600 font-black uppercase tracking-[0.3em] mt-1 flex items-center gap-2">
132
  <Terminal size={10} />
133
- ROOT_IDENTIFIER: {user.name.toUpperCase().replace(' ', '_')}
134
  </p>
135
  </div>
136
-
137
- {isEsgNeutral && (
138
- <div className="px-4 py-1.5 bg-emerald-500/10 border border-emerald-500/20 rounded-full flex items-center gap-2 shadow-2xl shadow-emerald-500/5">
139
- <Leaf size={12} className="text-emerald-500" />
140
- <span className="text-[10px] font-black text-emerald-500 uppercase tracking-widest">ESG Offset Verified</span>
141
- </div>
142
- )}
143
  </div>
144
 
145
  <div className="flex items-center space-x-8">
146
  <div className="flex items-center space-x-6">
147
- <button className="p-3 text-zinc-500 hover:text-white transition-all relative group bg-zinc-950 rounded-xl border border-zinc-900 shadow-xl">
148
  <Bell size={18} />
149
- <span className="absolute top-3 right-3 w-2 h-2 bg-blue-500 rounded-full shadow-[0_0_10px_rgba(59,130,246,0.8)]"></span>
150
  </button>
151
  <div className="h-8 w-px bg-zinc-900"></div>
152
  <div className="flex items-center space-x-4 group cursor-pointer" onClick={onLogout}>
@@ -165,28 +84,26 @@ const Header = ({ user, onLogout }: { user: UserSession, onLogout: () => void })
165
  };
166
 
167
  const PrivateTerminal = ({ user, onLogout }: { user: UserSession, onLogout: () => void }) => {
168
- const [isKeyAuthorized, setIsKeyAuthorized] = useState(!!localStorage.getItem('LQI_API_KEY'));
 
169
 
170
- if (!isKeyAuthorized) {
171
- return <KeyGateway onAuthorized={() => setIsKeyAuthorized(true)} />;
172
- }
 
173
 
174
  return (
175
- <div className="flex min-h-screen bg-[#020202] text-zinc-400 antialiased selection:bg-blue-500/30 selection:text-blue-200 font-sans">
176
- <div className="fixed inset-0 pointer-events-none opacity-[0.03] z-0 overflow-hidden">
177
- <div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:40px_40px]"></div>
178
- </div>
179
-
180
- <aside className="w-80 fixed h-full bg-[#050505] border-r border-zinc-900 p-8 flex flex-col print:hidden z-50">
181
  <div className="mb-14 px-4 flex items-center space-x-4">
182
- <div className="w-12 h-12 bg-white rounded-2xl flex items-center justify-center shadow-2xl shadow-white/5">
183
  <Cpu size={24} className="text-black" />
184
  </div>
185
  <div>
186
  <h1 className="text-lg font-black italic tracking-tighter text-white uppercase leading-none">
187
- Lumina <span className="text-blue-500 not-italic">Quantum</span>
188
  </h1>
189
- <p className="text-[9px] uppercase tracking-[0.4em] font-bold text-zinc-600 mt-1">Institutional Ledger</p>
190
  </div>
191
  </div>
192
 
@@ -194,27 +111,32 @@ const PrivateTerminal = ({ user, onLogout }: { user: UserSession, onLogout: () =
194
  <NavigationLinks />
195
  </nav>
196
 
197
- <div className="mt-auto pt-10 border-t border-zinc-900">
198
- <SidebarItem icon={SettingsIcon} label="System Config" path="/settings" active={window.location.hash.includes('settings')} />
199
- <div className="mt-8 p-6 bg-zinc-950 border border-zinc-900 rounded-[2rem] flex items-center justify-between group cursor-help shadow-2xl">
 
 
 
 
 
 
200
  <div className="flex items-center gap-3">
201
  <Activity size={16} className="text-emerald-500" />
202
- <span className="text-[9px] font-black uppercase tracking-widest text-zinc-500">Node Reachable</span>
203
  </div>
204
- <div className="w-2 h-2 bg-emerald-500 rounded-full animate-pulse shadow-[0_0_8px_rgba(16,185,129,0.5)]"></div>
205
  </div>
206
  </div>
207
  </aside>
208
 
209
- <main className="flex-1 ml-80 min-h-screen flex flex-col relative z-10 print:ml-0 print:bg-white">
210
  <Header user={user} onLogout={onLogout} />
211
- <div className="px-10 pb-20 print:p-0">
212
  <Routes>
213
  {routes.map((route) => (
214
  <Route key={route.path} path={route.path} element={<route.component />} />
215
  ))}
216
- {/* Relative catch-all for terminal paths */}
217
- <Route path="*" element={<Navigate to="/" replace />} />
218
  </Routes>
219
  </div>
220
  </main>
@@ -225,7 +147,6 @@ const PrivateTerminal = ({ user, onLogout }: { user: UserSession, onLogout: () =
225
  const NavigationLinks = () => {
226
  const location = useLocation();
227
  const categories = ['core', 'registry', 'finance', 'intelligence', 'system', 'admin'];
228
-
229
  return (
230
  <div className="space-y-10">
231
  {categories.map(cat => {
@@ -233,7 +154,7 @@ const NavigationLinks = () => {
233
  if (catRoutes.length === 0) return null;
234
  return (
235
  <div key={cat} className="space-y-3">
236
- <p className="px-6 text-[8px] font-black uppercase text-zinc-700 tracking-[0.5em] mb-4">{cat.toUpperCase()}_V6_SEGMENT</p>
237
  {catRoutes.map((route) => (
238
  <SidebarItem
239
  key={route.path}
@@ -250,60 +171,155 @@ const NavigationLinks = () => {
250
  );
251
  };
252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  const App: React.FC = () => {
 
 
254
  const [currentUser, setCurrentUser] = useState<UserSession | null>(null);
255
  const [isAuthChecked, setIsAuthChecked] = useState<boolean>(false);
256
 
257
- const checkAuthStatus = async () => {
 
 
258
  const { user } = await apiClient.auth.me();
259
  setCurrentUser(user);
260
  setIsAuthChecked(true);
261
- };
262
 
263
  useEffect(() => {
264
- checkAuthStatus();
265
- window.addEventListener('auth-update', checkAuthStatus);
266
- return () => window.removeEventListener('auth-update', checkAuthStatus);
267
- }, []);
268
 
269
  const handleLogout = async () => {
270
  await apiClient.auth.logout();
271
  setCurrentUser(null);
272
- window.dispatchEvent(new Event('auth-update'));
273
  };
274
 
275
- if (!isAuthChecked) {
 
 
 
 
 
 
276
  return (
277
- <div className="min-h-screen bg-[#020202] flex flex-col items-center justify-center space-y-8">
278
- <Loader2 className="animate-spin text-blue-500" size={48} />
279
- <p className="text-[10px] font-black text-zinc-600 uppercase tracking-[0.4em] animate-pulse">Synchronizing Node Registry...</p>
 
 
 
280
  </div>
281
  );
282
  }
283
 
 
 
 
 
284
  return (
285
  <HashRouter>
286
  <Routes>
287
- <Route path="/" element={<Landing />} />
288
- <Route path="/login" element={<Login />} />
289
  <Route path="/airdrop" element={<Airdrop />} />
290
  <Route path="/manifesto" element={<PrivacyPolicy />} />
291
  <Route path="/documentation" element={<Documentation />} />
292
-
293
- {/* The terminal area handles its own key authorization logic inside */}
294
- <Route
295
- path="/*"
296
- element={
297
- currentUser ? (
298
- <PrivateTerminal user={currentUser} onLogout={handleLogout} />
299
- ) : (
300
- <Navigate to="/login" replace />
301
- )
302
- }
303
- />
304
  </Routes>
305
  </HashRouter>
306
  );
307
  };
308
 
309
- export default App;
 
1
+ import React, { useState, useEffect, useCallback } from 'react';
2
+ import { HashRouter, Routes, Route, Link, useLocation, Navigate, useNavigate } from 'react-router-dom';
 
3
  import {
4
+ Bell, LogOut, Activity, ChevronRight, Cpu, Settings as SettingsIcon, Terminal, Loader2, Key,
5
+ ShieldCheck, Zap, ArrowRight, ShieldAlert, Globe, Lock, Database, Shield, ZapOff, Fingerprint, Code
 
 
 
 
 
 
 
 
 
 
 
6
  } from 'lucide-react';
7
  import { routes } from './views/routes';
8
  import Login from './views/Login';
 
13
  import { apiClient } from './services/api';
14
  import { UserSession } from './types/index';
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  const SidebarItem: React.FC<{ icon: any, label: string, path: string, active: boolean }> = ({ icon: Icon, label, path, active }) => (
17
  <Link
18
  to={path}
19
  className={`flex items-center justify-between px-6 py-4 rounded-2xl transition-all duration-500 group ${
20
  active
21
+ ? 'bg-white text-black shadow-2xl scale-[1.02]'
22
  : 'text-zinc-500 hover:text-white hover:bg-zinc-900/50'
23
  }`}
24
  >
 
31
  );
32
 
33
  const Header = ({ user, onLogout }: { user: UserSession, onLogout: () => void }) => {
 
34
  const location = useLocation();
35
  const currentRoute = routes.find(r => r.path === location.pathname);
36
  const [typedTitle, setTypedTitle] = useState('');
 
49
  }, [location.pathname, currentRoute]);
50
 
51
  return (
52
+ <header className="h-24 flex items-center justify-between px-10 bg-transparent relative z-50">
53
  <div className="flex items-center space-x-6">
54
  <div className="hidden md:flex flex-col">
55
  <h1 className="text-xl font-black tracking-tighter text-white italic leading-none uppercase">
56
+ {typedTitle || 'CORE'} <span className="text-blue-500 not-italic">NODE</span>
57
  </h1>
58
  <p className="text-[10px] text-zinc-600 font-black uppercase tracking-[0.3em] mt-1 flex items-center gap-2">
59
  <Terminal size={10} />
60
+ ROOT_IDENTIFIER: {user.name.toUpperCase()}
61
  </p>
62
  </div>
 
 
 
 
 
 
 
63
  </div>
64
 
65
  <div className="flex items-center space-x-8">
66
  <div className="flex items-center space-x-6">
67
+ <button className="p-3 text-zinc-500 hover:text-white transition-all bg-zinc-950 rounded-xl border border-zinc-900 shadow-xl">
68
  <Bell size={18} />
 
69
  </button>
70
  <div className="h-8 w-px bg-zinc-900"></div>
71
  <div className="flex items-center space-x-4 group cursor-pointer" onClick={onLogout}>
 
84
  };
85
 
86
  const PrivateTerminal = ({ user, onLogout }: { user: UserSession, onLogout: () => void }) => {
87
+ const location = useLocation();
88
+ const navigate = useNavigate();
89
 
90
+ const handleTerminate = async () => {
91
+ await onLogout();
92
+ navigate('/');
93
+ };
94
 
95
  return (
96
+ <div className="flex min-h-screen bg-[#020202] text-zinc-400 antialiased font-sans">
97
+ <aside className="w-80 fixed h-full bg-[#050505] border-r border-zinc-900 p-8 flex flex-col z-50">
 
 
 
 
98
  <div className="mb-14 px-4 flex items-center space-x-4">
99
+ <div className="w-12 h-12 bg-white rounded-2xl flex items-center justify-center shadow-2xl">
100
  <Cpu size={24} className="text-black" />
101
  </div>
102
  <div>
103
  <h1 className="text-lg font-black italic tracking-tighter text-white uppercase leading-none">
104
+ AIBanking <span className="text-blue-500 not-italic">Core</span>
105
  </h1>
106
+ <p className="text-[9px] uppercase tracking-[0.4em] font-bold text-zinc-600 mt-1">Institutional Mesh</p>
107
  </div>
108
  </div>
109
 
 
111
  <NavigationLinks />
112
  </nav>
113
 
114
+ <div className="mt-auto pt-10 border-t border-zinc-900 space-y-4">
115
+ <button
116
+ onClick={handleTerminate}
117
+ 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"
118
+ >
119
+ <ShieldAlert size={16} />
120
+ <span>Terminate Link</span>
121
+ </button>
122
+ <div className="mt-8 p-6 bg-zinc-950 border border-zinc-900 rounded-[2rem] flex items-center justify-between shadow-2xl">
123
  <div className="flex items-center gap-3">
124
  <Activity size={16} className="text-emerald-500" />
125
+ <span className="text-[9px] font-black uppercase tracking-widest text-zinc-500">Node Sync: 100%</span>
126
  </div>
127
+ <div className="w-2 h-2 bg-emerald-500 rounded-full animate-pulse shadow-[0_0_8px_#10b981]"></div>
128
  </div>
129
  </div>
130
  </aside>
131
 
132
+ <main className="flex-1 ml-80 min-h-screen flex flex-col relative z-10">
133
  <Header user={user} onLogout={onLogout} />
134
+ <div className="px-10 pb-20">
135
  <Routes>
136
  {routes.map((route) => (
137
  <Route key={route.path} path={route.path} element={<route.component />} />
138
  ))}
139
+ <Route path="*" element={<Navigate to="/overview" replace />} />
 
140
  </Routes>
141
  </div>
142
  </main>
 
147
  const NavigationLinks = () => {
148
  const location = useLocation();
149
  const categories = ['core', 'registry', 'finance', 'intelligence', 'system', 'admin'];
 
150
  return (
151
  <div className="space-y-10">
152
  {categories.map(cat => {
 
154
  if (catRoutes.length === 0) return null;
155
  return (
156
  <div key={cat} className="space-y-3">
157
+ <p className="px-6 text-[8px] font-black uppercase text-zinc-700 tracking-[0.5em] mb-4">{cat.toUpperCase()}_SUITE</p>
158
  {catRoutes.map((route) => (
159
  <SidebarItem
160
  key={route.path}
 
171
  );
172
  };
173
 
174
+ const NeuralGate = ({ onAuthorized }: { onAuthorized: (tier: 'enterprise' | 'regular') => void }) => {
175
+ const [loading, setLoading] = useState(false);
176
+
177
+ const handleEnterpriseLink = async () => {
178
+ setLoading(true);
179
+ try {
180
+ await window.aistudio.openSelectKey();
181
+ onAuthorized('enterprise');
182
+ } catch (e) {
183
+ console.error("Enterprise gate refusal.");
184
+ } finally {
185
+ setLoading(false);
186
+ }
187
+ };
188
+
189
+ const handleRegularLink = () => {
190
+ onAuthorized('regular');
191
+ };
192
+
193
+ return (
194
+ <div className="min-h-screen bg-black flex flex-col items-center justify-center p-12 relative overflow-hidden">
195
+ <div className="absolute inset-0 z-0 opacity-20">
196
+ <div className="absolute top-0 left-0 w-full h-full bg-[radial-gradient(circle_at_50%_50%,_#1e1b4b_0%,_transparent_70%)]"></div>
197
+ <div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:80px_80px]"></div>
198
+ </div>
199
+
200
+ <div className="max-w-4xl w-full relative z-10 text-center space-y-16">
201
+ <div className="relative inline-block group">
202
+ <div className="absolute -inset-8 bg-blue-600/20 blur-3xl rounded-full opacity-50 group-hover:opacity-100 transition-opacity"></div>
203
+ <div className="w-32 h-32 bg-white rounded-[3.5rem] flex items-center justify-center mx-auto shadow-[0_40px_80px_rgba(255,255,255,0.1)] group-hover:rotate-12 transition-transform duration-1000 border-4 border-zinc-900">
204
+ <Lock size={64} className="text-black" />
205
+ </div>
206
+ </div>
207
+
208
+ <div className="space-y-8">
209
+ <h1 className="text-7xl lg:text-8xl font-black italic text-white uppercase tracking-tighter leading-none">
210
+ Neural <span className="text-blue-500 not-italic">Gateway</span>
211
+ </h1>
212
+ <p className="text-zinc-500 font-bold text-2xl leading-relaxed italic max-w-2xl mx-auto">
213
+ "To initialize the aibanking.dev ledger, establishing a secure neural link is mandatory. Select your protocol tier."
214
+ </p>
215
+ </div>
216
+
217
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-3xl mx-auto">
218
+ <button
219
+ onClick={handleEnterpriseLink}
220
+ disabled={loading}
221
+ className="flex flex-col items-center gap-6 py-10 px-8 bg-blue-600 hover:bg-blue-500 text-white rounded-[3.5rem] transition-all shadow-[0_30px_60px_rgba(37,99,235,0.4)] group active:scale-95 border-2 border-transparent hover:border-white/20"
222
+ >
223
+ <Zap size={40} className="group-hover:scale-125 transition-transform" />
224
+ <div className="text-center">
225
+ <span className="block font-black text-sm uppercase tracking-[0.4em] mb-2">Enterprise Tier</span>
226
+ <span className="block text-[10px] font-bold text-blue-100 uppercase tracking-widest opacity-60 italic">Requires Paid Google API Node</span>
227
+ </div>
228
+ <ArrowRight size={24} className="group-hover:translate-x-4 transition-transform" />
229
+ </button>
230
+
231
+ <button
232
+ onClick={handleRegularLink}
233
+ className="flex flex-col items-center gap-6 py-10 px-8 bg-zinc-900 hover:bg-zinc-800 text-white rounded-[3.5rem] transition-all shadow-2xl group active:scale-95 border-2 border-zinc-800 hover:border-zinc-700"
234
+ >
235
+ <Globe size={40} className="text-zinc-600 group-hover:text-blue-400 group-hover:scale-125 transition-all" />
236
+ <div className="text-center">
237
+ <span className="block font-black text-sm uppercase tracking-[0.4em] mb-2">Regular Tier</span>
238
+ <span className="block text-[10px] font-bold text-zinc-500 uppercase tracking-widest opacity-60 italic">Free Local Instance Access</span>
239
+ </div>
240
+ <ArrowRight size={24} className="text-zinc-700 group-hover:text-zinc-500 group-hover:translate-x-4 transition-all" />
241
+ </button>
242
+ </div>
243
+
244
+ <div className="pt-12 border-t border-zinc-900 space-y-6">
245
+ <div className="flex flex-col md:flex-row items-center justify-center gap-10">
246
+ <a href="https://ai.google.dev/gemini-api/docs/billing" target="_blank" rel="noreferrer" className="text-[10px] font-black text-zinc-600 hover:text-white uppercase tracking-widest transition-colors flex items-center gap-2">
247
+ <Key size={12} /> Registry Documentation
248
+ </a>
249
+ <p className="text-[10px] font-black text-zinc-700 uppercase tracking-[0.4em]">v6.5.0 Institutional Registry • Secured via RSA-OAEP</p>
250
+ </div>
251
+ <div className="flex justify-center gap-12 opacity-20">
252
+ <ShieldCheck size={32} /><Globe size={32} /><Database size={32} />
253
+ </div>
254
+ </div>
255
+ </div>
256
+ </div>
257
+ );
258
+ };
259
+
260
  const App: React.FC = () => {
261
+ const [hasKey, setHasKey] = useState<boolean | null>(null);
262
+ const [tier, setTier] = useState<'enterprise' | 'regular' | null>(null);
263
  const [currentUser, setCurrentUser] = useState<UserSession | null>(null);
264
  const [isAuthChecked, setIsAuthChecked] = useState<boolean>(false);
265
 
266
+ const checkStatus = useCallback(async () => {
267
+ const keySelected = await window.aistudio.hasSelectedApiKey();
268
+ setHasKey(keySelected);
269
  const { user } = await apiClient.auth.me();
270
  setCurrentUser(user);
271
  setIsAuthChecked(true);
272
+ }, []);
273
 
274
  useEffect(() => {
275
+ checkStatus();
276
+ window.addEventListener('auth-update', checkStatus);
277
+ return () => window.removeEventListener('auth-update', checkStatus);
278
+ }, [checkStatus]);
279
 
280
  const handleLogout = async () => {
281
  await apiClient.auth.logout();
282
  setCurrentUser(null);
 
283
  };
284
 
285
+ const onAuthorized = (selectedTier: 'enterprise' | 'regular') => {
286
+ setTier(selectedTier);
287
+ if (selectedTier === 'regular') setHasKey(true);
288
+ else checkStatus();
289
+ };
290
+
291
+ if (!isAuthChecked || (hasKey === null && !tier)) {
292
  return (
293
+ <div className="min-h-screen bg-black flex flex-col items-center justify-center space-y-12">
294
+ <div className="relative">
295
+ <div className="w-24 h-24 border-4 border-zinc-900 border-t-blue-500 rounded-full animate-spin"></div>
296
+ <Cpu className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 text-white" size={32} />
297
+ </div>
298
+ <p className="text-[11px] font-black text-zinc-700 uppercase tracking-[0.8em] animate-pulse italic">Synchronizing Node Registry...</p>
299
  </div>
300
  );
301
  }
302
 
303
+ if (!hasKey && tier !== 'regular') {
304
+ return <NeuralGate onAuthorized={onAuthorized} />;
305
+ }
306
+
307
  return (
308
  <HashRouter>
309
  <Routes>
310
+ <Route path="/" element={currentUser ? <Navigate to="/overview" replace /> : <Landing />} />
311
+ <Route path="/login" element={currentUser ? <Navigate to="/overview" replace /> : <Login />} />
312
  <Route path="/airdrop" element={<Airdrop />} />
313
  <Route path="/manifesto" element={<PrivacyPolicy />} />
314
  <Route path="/documentation" element={<Documentation />} />
315
+ <Route path="/*" element={currentUser ? (
316
+ <PrivateTerminal user={currentUser} onLogout={handleLogout} />
317
+ ) : (
318
+ <Navigate to="/" replace />
319
+ )} />
 
 
 
 
 
 
 
320
  </Routes>
321
  </HashRouter>
322
  );
323
  };
324
 
325
+ export default App;
Dockerfile.txt ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use a slim Node image for faster builds
2
+ FROM node:20-slim
3
+
4
+ # Set the working directory
5
+ WORKDIR /app
6
+
7
+ # Copy dependency manifest
8
+ COPY package.json ./
9
+
10
+ # Install dependencies
11
+ RUN npm install
12
+
13
+ # Copy the entire source code
14
+ COPY . .
15
+
16
+ # Build the static frontend
17
+ RUN npm run build
18
+
19
+ # Hugging Face Spaces use port 7860
20
+ ENV PORT=7860
21
+ EXPOSE 7860
22
+
23
+ # Start the application using Vite's preview mode
24
+ # "npm start" maps to: vite preview --port 7860 --host 0.0.0.0
25
+ CMD ["npm", "start"]
README.md CHANGED
@@ -1,16 +1,20 @@
1
- ---
2
- title: Quantum Ledger Intelligence
3
- emoji: 💎
4
- colorFrom: blue
5
- colorTo: gray
6
- sdk: docker
7
- pinned: false
8
- ---
9
 
10
- # Lumina Quantum Ledger
11
 
12
- This is a high-performance financial dashboard integrating AI-driven forecasting and corporate asset management.
13
 
14
- ## Setup
15
- 1. Ensure your Gemini API Key is added to the Space **Secrets** as `API_KEY`.
16
- 2. The Space will automatically build using the `Dockerfile` and serve on port 7860.
 
 
 
 
 
 
 
 
 
 
1
+ <div align="center">
2
+ <img width="1200" height="475" alt="GHBanner" src="https://github.com/user-attachments/assets/0aa67016-6eaf-458a-adb2-6e31a0763ed6" />
3
+ </div>
 
 
 
 
 
4
 
5
+ # Run and deploy your AI Studio app
6
 
7
+ This contains everything you need to run your app locally.
8
 
9
+ View your app in AI Studio: https://ai.studio/apps/drive/1lIFV2uT_kj0gG9PM3NWzaKh059u7b3nt
10
+
11
+ ## Run Locally
12
+
13
+ **Prerequisites:** Node.js
14
+
15
+
16
+ 1. Install dependencies:
17
+ `npm install`
18
+ 2. Set the `GEMINI_API_KEY` in [.env.local](.env.local) to your Gemini API key
19
+ 3. Run the app:
20
+ `npm run dev`
index.html CHANGED
@@ -29,10 +29,12 @@
29
  "@google/genai": "https://esm.sh/@google/genai@^1.41.0",
30
  "path": "https://esm.sh/path@^0.12.7",
31
  "vite": "https://esm.sh/vite@^7.3.1",
32
- "@vitejs/plugin-react": "https://esm.sh/@vitejs/plugin-react@^5.1.4"
 
33
  }
34
  }
35
  </script>
 
36
  </head>
37
  <body>
38
  <div id="root"></div>
 
29
  "@google/genai": "https://esm.sh/@google/genai@^1.41.0",
30
  "path": "https://esm.sh/path@^0.12.7",
31
  "vite": "https://esm.sh/vite@^7.3.1",
32
+ "@vitejs/plugin-react": "https://esm.sh/@vitejs/plugin-react@^5.1.4",
33
+ "url": "https://esm.sh/url@^0.11.4"
34
  }
35
  }
36
  </script>
37
+ <link rel="stylesheet" href="/index.css">
38
  </head>
39
  <body>
40
  <div id="root"></div>
metadata.json CHANGED
@@ -2,6 +2,7 @@
2
  "name": "Quantum Ledger Intelligence",
3
  "description": "A high-performance financial dashboard integrating AI-driven forecasting, sustainability metrics, and corporate asset management using the Gemini API.",
4
  "requestFramePermissions": [
5
- "microphone"
 
6
  ]
7
  }
 
2
  "name": "Quantum Ledger Intelligence",
3
  "description": "A high-performance financial dashboard integrating AI-driven forecasting, sustainability metrics, and corporate asset management using the Gemini API.",
4
  "requestFramePermissions": [
5
+ "microphone",
6
+ "camera"
7
  ]
8
  }
package.json CHANGED
@@ -7,24 +7,19 @@
7
  "dev": "vite",
8
  "build": "vite build",
9
  "preview": "vite preview",
10
- "start": "node server.js"
11
  },
12
  "dependencies": {
13
- "@google/genai": "^1.41.0",
14
- "bcryptjs": "^3.0.3",
15
- "cors": "^2.8.6",
16
- "express": "^5.2.1",
17
  "lucide-react": "^0.563.0",
18
- "path": "^0.12.7",
19
  "react": "^19.2.4",
20
  "react-dom": "^19.2.4",
21
  "react-router-dom": "^7.13.0",
22
  "recharts": "^3.7.0",
23
- "sqlite3": "^5.1.7"
24
  },
25
  "devDependencies": {
26
- "@types/react": "^19.2.14",
27
- "@types/react-dom": "^19.2.3",
28
  "@vitejs/plugin-react": "^5.1.4",
29
  "typescript": "^5.7.3",
30
  "vite": "^7.3.1"
 
7
  "dev": "vite",
8
  "build": "vite build",
9
  "preview": "vite preview",
10
+ "start": "vite preview --port 7860 --host 0.0.0.0"
11
  },
12
  "dependencies": {
 
 
 
 
13
  "lucide-react": "^0.563.0",
 
14
  "react": "^19.2.4",
15
  "react-dom": "^19.2.4",
16
  "react-router-dom": "^7.13.0",
17
  "recharts": "^3.7.0",
18
+ "@google/genai": "^1.41.0"
19
  },
20
  "devDependencies": {
21
+ "@types/react": "^19.2.4",
22
+ "@types/react-dom": "^19.2.4",
23
  "@vitejs/plugin-react": "^5.1.4",
24
  "typescript": "^5.7.3",
25
  "vite": "^7.3.1"
vite.config.ts CHANGED
@@ -1,6 +1,29 @@
1
- import { defineConfig } from 'vite'
2
- import react from '@vitejs/plugin-react'
 
 
3
 
4
- export default defineConfig({
5
- plugins: [react()],
6
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import path from 'path';
2
+ import { fileURLToPath } from 'url';
3
+ import { defineConfig, loadEnv } from 'vite';
4
+ import react from '@vitejs/plugin-react';
5
 
6
+ // Fix: __dirname is not available in ES modules environment.
7
+ // We define it using path.dirname and fileURLToPath(import.meta.url).
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
+
10
+ export default defineConfig(({ mode }) => {
11
+ const env = loadEnv(mode, '.', '');
12
+ return {
13
+ server: {
14
+ port: 3000,
15
+ host: '0.0.0.0',
16
+ },
17
+ plugins: [react()],
18
+ define: {
19
+ 'process.env.API_KEY': JSON.stringify(env.GEMINI_API_KEY),
20
+ 'process.env.GEMINI_API_KEY': JSON.stringify(env.GEMINI_API_KEY)
21
+ },
22
+ resolve: {
23
+ alias: {
24
+ // Fix: Use the polyfilled __dirname variable to resolve project root
25
+ '@': path.resolve(__dirname, '.'),
26
+ }
27
+ }
28
+ };
29
+ });