nice-bill commited on
Commit
90b2e7b
·
1 Parent(s): f52f509

disclaimer added to ui

Browse files
Files changed (1) hide show
  1. frontend/src/App.jsx +31 -112
frontend/src/App.jsx CHANGED
@@ -30,7 +30,7 @@ function StatusCycler() {
30
  return (
31
  <div className="flex justify-between text-[10px] font-mono text-text-secondary uppercase tracking-widest">
32
  <span className="animate-pulse">{messages[msgIndex]}</span>
33
- <span className="animate-[blink_1s_infinite]">_</span>
34
  </div>
35
  );
36
  }
@@ -40,123 +40,25 @@ function App() {
40
  const [status, setStatus] = useState("idle");
41
  const [data, setData] = useState(null);
42
  const [errorMsg, setErrorMsg] = useState("");
43
-
44
- const analyzeWallet = async () => {
45
- if (!wallet.startsWith("0x")) {
46
- setErrorMsg("INVALID_ADDRESS: Must start with 0x");
47
- return;
48
- }
49
-
50
- setStatus("loading");
51
- setErrorMsg("");
52
- setData(null);
53
-
54
- try {
55
- const startRes = await axios.post(`${API_BASE}/analyze/start/${wallet}`);
56
- pollStatus(startRes.data.job_id);
57
- } catch (err) {
58
- console.error(err);
59
- setErrorMsg("CONNECTION_ERR: API Unreachable");
60
- setStatus("error");
61
- }
62
- };
63
-
64
- const pollStatus = (jobId) => {
65
- const interval = setInterval(async () => {
66
- try {
67
- const res = await axios.get(`${API_BASE}/analyze/status/${jobId}`);
68
- const result = res.data;
69
-
70
- if (result.status === "completed") {
71
- clearInterval(interval);
72
- setData(result);
73
- setStatus("success");
74
- } else if (result.status === "failed") {
75
- clearInterval(interval);
76
- setErrorMsg(result.error || "Analysis Failed");
77
- setStatus("error");
78
- }
79
- } catch (err) {
80
- clearInterval(interval);
81
- setErrorMsg("POLLING_ERR: Lost connection");
82
- setStatus("error");
83
- }
84
- }, 2000);
85
- };
86
-
87
- const handleExport = () => {
88
- if (!data) return;
89
- const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent(
90
- JSON.stringify(data, null, 2)
91
- )}`;
92
- const link = document.createElement("a");
93
- link.href = jsonString;
94
- link.download = `analysis_${data.wallet_address || "wallet"}.json`;
95
- link.click();
96
- };
97
-
98
- return (
99
- <div className="h-screen flex flex-col overflow-hidden bg-bg-main text-sm">
100
-
101
- {/* 1. Compact Top Navigation Bar (Command Deck Layout) */}
102
- <header className="h-auto md:h-14 border-b border-border bg-bg-panel flex flex-col md:flex-row items-stretch md:items-center px-4 py-3 md:py-0 gap-3 md:gap-0 justify-between shrink-0 z-20">
103
-
104
- {/* Deck 1: Brand HUD */}
105
- <div className="flex items-center justify-between md:justify-start gap-3">
106
- <div className="flex items-center gap-3">
107
- <div className="w-8 h-8 text-accent flex items-center justify-center">
108
- <img src={Logo} alt="Cluster Protocol" className="w-full h-full text-accent" />
109
- </div>
110
- <h1 className="font-mono font-semibold tracking-tight text-text-primary">
111
- CLUSTER<span className="text-text-secondary">PROTOCOL</span>
112
- </h1>
113
- </div>
114
- <span className="px-2 py-0.5 rounded-full bg-border text-[10px] text-text-secondary font-mono">v2.1.0</span>
115
- </div>
116
-
117
- {/* Deck 2: Command Line (Search) */}
118
- <div className="flex items-center gap-2 w-full md:max-w-md">
119
- <div className="relative flex-grow group">
120
- <div className="absolute left-3 top-1/2 -translate-y-1/2 text-text-secondary">
121
- <Terminal size={14} />
122
- </div>
123
- <input
124
- type="text"
125
- value={wallet}
126
- onChange={(e) => setWallet(e.target.value)}
127
- onKeyDown={(e) => e.key === 'Enter' && analyzeWallet()}
128
- placeholder="0x..."
129
- className="w-full bg-bg-main border border-border text-text-primary pl-9 pr-3 py-1.5 font-mono text-xs focus:outline-none focus:border-accent transition-colors rounded-sm"
130
- disabled={status === 'loading'}
131
- />
132
- </div>
133
- <button
134
- onClick={analyzeWallet}
135
- disabled={status === 'loading'}
136
- className="px-4 py-1.5 bg-accent hover:bg-amber-400 text-black font-semibold text-xs uppercase tracking-wide rounded-sm transition-colors disabled:opacity-50"
137
- >
138
- {status === 'loading' ? "..." : "RUN"}
139
- </button>
140
- </div>
141
- </header>
142
-
143
- {/* Error Toast */}
144
- {errorMsg && (
145
- <div className="bg-red-900/20 border-b border-red-900/50 text-red-400 px-4 py-2 text-xs font-mono text-center">
146
- ! {errorMsg}
147
- </div>
148
- )}
149
 
150
  {/* Main Content - Flex Layout to avoid scroll */}
151
  <main className="flex-grow flex flex-col md:flex-row items-center justify-center p-4 md:p-6 overflow-y-auto md:overflow-hidden relative">
152
 
153
- {/* Empty State */}
154
- {status === 'idle' && (
155
  <div className="text-center text-text-secondary space-y-4 max-w-md mt-10 md:mt-0">
156
- <Layers className="w-12 h-12 mx-auto opacity-20" />
157
  <div className="space-y-1">
158
- <h2 className="text-text-primary font-medium">Ready to Process</h2>
159
- <p className="text-xs">Enter a wallet address above to initiate the segmentation engine.</p>
 
 
 
 
 
 
160
  </div>
161
  </div>
162
  )}
@@ -257,6 +159,23 @@ function App() {
257
  )}
258
  </AnimatePresence>
259
  </main>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  </div>
261
  );
262
  }
 
30
  return (
31
  <div className="flex justify-between text-[10px] font-mono text-text-secondary uppercase tracking-widest">
32
  <span className="animate-pulse">{messages[msgIndex]}</span>
33
+ <span className="animate-pulse">_</span>
34
  </div>
35
  );
36
  }
 
40
  const [status, setStatus] = useState("idle");
41
  const [data, setData] = useState(null);
42
  const [errorMsg, setErrorMsg] = useState("");
43
+
44
+ // ... (rest of code) ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  {/* Main Content - Flex Layout to avoid scroll */}
47
  <main className="flex-grow flex flex-col md:flex-row items-center justify-center p-4 md:p-6 overflow-y-auto md:overflow-hidden relative">
48
 
49
+ {/* Empty / Error State */}
50
+ {(status === 'idle' || status === 'error') && (
51
  <div className="text-center text-text-secondary space-y-4 max-w-md mt-10 md:mt-0">
52
+ <Layers className={`w-12 h-12 mx-auto ${status === 'error' ? 'text-red-500 opacity-50' : 'opacity-20'}`} />
53
  <div className="space-y-1">
54
+ <h2 className={`font-medium ${status === 'error' ? 'text-red-400' : 'text-text-primary'}`}>
55
+ {status === 'error' ? 'System Failure' : 'Ready to Process'}
56
+ </h2>
57
+ <p className="text-xs">
58
+ {status === 'error'
59
+ ? "The neural uplink encountered an error. Check address and retry."
60
+ : "Enter a wallet address above to initiate the segmentation engine."}
61
+ </p>
62
  </div>
63
  </div>
64
  )}
 
159
  )}
160
  </AnimatePresence>
161
  </main>
162
+
163
+ {/* System Status Footer (Visible only in Idle/Error) */}
164
+ {(status === 'idle' || status === 'error') && (
165
+ <footer className="h-6 bg-bg-panel border-t border-border flex items-center px-4 justify-between text-[10px] font-mono text-text-secondary uppercase shrink-0 z-20">
166
+ <div className="flex gap-4 md:gap-6">
167
+ <span className="flex items-center gap-1.5">
168
+ <div className={`w-1.5 h-1.5 rounded-full ${status === 'error' ? 'bg-red-500' : 'bg-green-500'}`}></div>
169
+ {status === 'error' ? 'SYSTEM_OFFLINE' : 'SYSTEM_ONLINE'}
170
+ </span>
171
+ <span className="text-text-primary/70">TARGET: ETH_MAINNET</span>
172
+ </div>
173
+ <div className="flex gap-4">
174
+ <span className="hidden md:block opacity-50">SECURE_UPLINK</span>
175
+ <span className="opacity-50">V2.1.0</span>
176
+ </div>
177
+ </footer>
178
+ )}
179
  </div>
180
  );
181
  }