Really-amin commited on
Commit
98241ef
·
verified ·
1 Parent(s): c9868c2

Upload admin.html

Browse files
Files changed (1) hide show
  1. admin.html +764 -170
admin.html CHANGED
@@ -5,187 +5,392 @@
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Admin Dashboard - Crypto Monitor</title>
7
  <style>
8
- * { margin: 0; padding: 0; box-sizing: border-box; }
 
 
 
 
 
 
9
 
10
  :root {
11
- --primary: #667eea;
12
- --primary-dark: #5568d3;
13
- --success: #48bb78;
14
- --warning: #ed8936;
15
- --danger: #f56565;
16
- --bg-dark: #1a202c;
17
- --bg-card: #2d3748;
18
- --text-light: #e2e8f0;
19
- --text-muted: #a0aec0;
20
- --border: #4a5568;
 
 
 
 
 
 
 
 
 
21
  }
22
 
23
  body {
24
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
25
- background: var(--bg-dark);
26
  color: var(--text-light);
27
  line-height: 1.6;
 
28
  }
29
 
30
  .container {
31
- max-width: 1400px;
32
  margin: 0 auto;
33
- padding: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  }
35
 
 
 
 
 
 
 
36
  header {
37
- background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
38
- padding: 20px;
39
- border-radius: 10px;
40
- margin-bottom: 30px;
41
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  }
43
 
44
  header h1 {
45
- font-size: 28px;
46
- font-weight: 700;
47
- margin-bottom: 5px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  }
49
 
50
  header .subtitle {
51
- color: rgba(255, 255, 255, 0.9);
52
- font-size: 14px;
 
 
53
  }
54
 
 
55
  .tabs {
56
  display: flex;
57
- gap: 10px;
58
- margin-bottom: 30px;
59
  flex-wrap: wrap;
 
 
 
 
60
  }
61
 
62
  .tab-btn {
63
  padding: 12px 24px;
64
- background: var(--bg-card);
65
- border: 2px solid var(--border);
66
- border-radius: 8px;
67
  cursor: pointer;
68
  font-weight: 600;
69
- color: var(--text-light);
70
- transition: all 0.3s;
 
 
 
 
71
  }
72
 
73
  .tab-btn:hover {
74
- background: var(--primary);
75
- border-color: var(--primary);
 
76
  }
77
 
78
  .tab-btn.active {
79
- background: var(--primary);
80
- border-color: var(--primary);
 
81
  }
82
 
 
83
  .tab-content {
84
  display: none;
85
- animation: fadeIn 0.3s;
86
  }
87
 
88
  .tab-content.active {
89
  display: block;
90
  }
91
 
92
- @keyframes fadeIn {
93
- from { opacity: 0; transform: translateY(10px); }
94
- to { opacity: 1; transform: translateY(0); }
 
 
 
 
 
 
95
  }
96
 
 
97
  .card {
98
  background: var(--bg-card);
99
- border-radius: 10px;
100
- padding: 20px;
101
- margin-bottom: 20px;
102
  border: 1px solid var(--border);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  }
104
 
105
  .card h3 {
106
- color: var(--primary);
107
- margin-bottom: 15px;
108
- font-size: 18px;
 
 
 
 
 
109
  }
110
 
 
111
  .stats-grid {
112
  display: grid;
113
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
114
- gap: 15px;
115
- margin-bottom: 20px;
116
  }
117
 
118
  .stat-card {
119
- background: var(--bg-card);
120
- padding: 20px;
121
- border-radius: 8px;
122
  border: 1px solid var(--border);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  }
124
 
125
  .stat-card .label {
126
  color: var(--text-muted);
127
- font-size: 12px;
128
  text-transform: uppercase;
129
- letter-spacing: 0.5px;
 
 
130
  }
131
 
132
  .stat-card .value {
133
- font-size: 32px;
134
- font-weight: 700;
135
- color: var(--primary);
136
- margin: 5px 0;
 
 
 
 
 
137
  }
138
 
139
  .stat-card .badge {
140
- display: inline-block;
141
- padding: 4px 8px;
142
- border-radius: 4px;
143
- font-size: 11px;
 
 
144
  font-weight: 600;
 
145
  }
146
 
147
  .badge-success {
148
- background: var(--success);
149
- color: white;
 
150
  }
151
 
152
  .badge-warning {
153
- background: var(--warning);
154
- color: white;
 
155
  }
156
 
157
  .badge-danger {
158
- background: var(--danger);
159
- color: white;
 
160
  }
161
 
 
162
  .btn {
163
- padding: 10px 20px;
164
  border: none;
165
- border-radius: 6px;
166
  cursor: pointer;
167
  font-weight: 600;
168
- transition: all 0.2s;
169
- margin-right: 10px;
170
- margin-bottom: 10px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  }
172
 
173
  .btn-primary {
174
- background: var(--primary);
175
  color: white;
 
176
  }
177
 
178
  .btn-primary:hover {
179
- background: var(--primary-dark);
 
180
  }
181
 
182
  .btn-success {
183
- background: var(--success);
184
  color: white;
 
185
  }
186
 
187
  .btn-success:hover {
188
- background: #38a169;
 
189
  }
190
 
191
  .btn-secondary {
@@ -195,105 +400,175 @@
195
  }
196
 
197
  .btn-secondary:hover {
198
- background: var(--border);
 
 
 
 
 
 
 
 
199
  }
200
 
 
201
  table {
202
  width: 100%;
203
- border-collapse: collapse;
204
- margin-top: 15px;
 
205
  }
206
 
207
  table thead {
208
- background: var(--bg-dark);
209
  }
210
 
211
  table th {
212
- padding: 12px;
213
  text-align: left;
214
- font-weight: 600;
215
- font-size: 12px;
216
  text-transform: uppercase;
217
  color: var(--text-muted);
 
 
218
  }
219
 
220
  table td {
221
- padding: 12px;
222
- border-top: 1px solid var(--border);
 
 
 
 
223
  }
224
 
225
  table tbody tr:hover {
226
- background: var(--bg-dark);
 
 
 
 
 
 
 
 
 
227
  }
228
 
 
229
  .status-online {
230
  color: var(--success);
 
231
  }
232
 
233
  .status-offline {
234
  color: var(--danger);
 
235
  }
236
 
237
  .status-degraded {
238
  color: var(--warning);
 
239
  }
240
 
 
241
  .loading {
242
  text-align: center;
243
- padding: 40px;
244
  color: var(--text-muted);
245
  }
246
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  .error-message {
248
- background: var(--danger);
249
- color: white;
250
- padding: 15px;
251
- border-radius: 8px;
252
  margin-bottom: 20px;
 
 
 
 
253
  }
254
 
255
  .success-message {
256
- background: var(--success);
257
- color: white;
258
- padding: 15px;
259
- border-radius: 8px;
260
  margin-bottom: 20px;
 
 
 
 
261
  }
262
 
263
  .empty-state {
264
  text-align: center;
265
- padding: 60px 20px;
266
  color: var(--text-muted);
267
  }
268
 
269
  .empty-state svg {
270
- width: 64px;
271
- height: 64px;
272
- margin-bottom: 20px;
273
  opacity: 0.3;
274
  }
275
 
 
276
  .filter-bar {
277
  display: flex;
278
- gap: 10px;
279
  margin-bottom: 20px;
280
  flex-wrap: wrap;
281
  }
282
 
283
  select, input {
284
- padding: 10px;
285
- border-radius: 6px;
286
  border: 1px solid var(--border);
287
- background: var(--bg-dark);
288
  color: var(--text-light);
 
 
 
 
 
 
 
 
289
  }
290
 
 
291
  .log-entry {
292
- padding: 10px;
293
  border-left: 3px solid var(--primary);
294
- margin-bottom: 10px;
295
- background: var(--bg-dark);
296
- border-radius: 4px;
 
 
 
 
 
 
297
  }
298
 
299
  .log-entry.error {
@@ -303,23 +578,33 @@
303
  .log-timestamp {
304
  color: var(--text-muted);
305
  font-size: 12px;
 
306
  }
307
 
 
308
  pre {
309
- background: var(--bg-dark);
310
- padding: 15px;
311
- border-radius: 6px;
312
  overflow-x: auto;
313
  font-size: 13px;
314
- line-height: 1.4;
 
315
  }
316
 
 
317
  .model-card {
318
- background: var(--bg-dark);
319
- padding: 15px;
320
- border-radius: 8px;
321
- margin-bottom: 15px;
322
  border-left: 4px solid var(--primary);
 
 
 
 
 
 
323
  }
324
 
325
  .model-card.valid {
@@ -334,9 +619,61 @@
334
  border-left-color: var(--danger);
335
  }
336
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  @media (max-width: 768px) {
 
 
 
 
 
 
 
 
 
 
 
 
338
  .stats-grid {
339
- grid-template-columns: 1fr;
340
  }
341
 
342
  .tabs {
@@ -348,7 +685,25 @@
348
  }
349
 
350
  table th, table td {
351
- padding: 8px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  }
353
  }
354
  </style>
@@ -356,18 +711,73 @@
356
  <body>
357
  <div class="container">
358
  <header>
359
- <h1>🚀 Crypto Monitor Admin Dashboard</h1>
360
- <p class="subtitle">Real-time provider management & system monitoring | NO MOCK DATA</p>
 
 
 
 
 
 
 
 
 
 
 
361
  </header>
362
 
363
  <div class="tabs">
364
- <button class="tab-btn active" onclick="switchTab('status')">📊 Status</button>
365
- <button class="tab-btn" onclick="switchTab('providers')">🔌 Providers</button>
366
- <button class="tab-btn" onclick="switchTab('market')">💰 Market Data</button>
367
- <button class="tab-btn" onclick="switchTab('apl')">🤖 APL Scanner</button>
368
- <button class="tab-btn" onclick="switchTab('hf-models')">🧠 HF Models</button>
369
- <button class="tab-btn" onclick="switchTab('diagnostics')">🔧 Diagnostics</button>
370
- <button class="tab-btn" onclick="switchTab('logs')">📝 Logs</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
  </div>
372
 
373
  <!-- Status Tab -->
@@ -376,7 +786,12 @@
376
  <div class="stat-card">
377
  <div class="label">System Health</div>
378
  <div class="value" id="system-health">-</div>
379
- <span class="badge badge-success" id="health-badge">Healthy</span>
 
 
 
 
 
380
  </div>
381
  <div class="stat-card">
382
  <div class="label">Total Providers</div>
@@ -389,19 +804,55 @@
389
  <div class="stat-card">
390
  <div class="label">Database</div>
391
  <div class="value">✓</div>
392
- <span class="badge badge-success">Connected</span>
 
 
 
 
 
 
393
  </div>
394
  </div>
395
 
396
  <div class="card">
397
- <h3>Quick Actions</h3>
398
- <button class="btn btn-primary" onclick="refreshAllData()">🔄 Refresh All</button>
399
- <button class="btn btn-success" onclick="runAPL()">🤖 Run APL Scan</button>
400
- <button class="btn btn-secondary" onclick="runDiagnostics()">🔧 Run Diagnostics</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  </div>
402
 
403
  <div class="card">
404
- <h3>Recent Market Data</h3>
 
 
 
 
 
 
405
  <div id="quick-market-view"></div>
406
  </div>
407
  </div>
@@ -409,7 +860,13 @@
409
  <!-- Providers Tab -->
410
  <div id="tab-providers" class="tab-content">
411
  <div class="card">
412
- <h3>Providers Management</h3>
 
 
 
 
 
 
413
  <div class="filter-bar">
414
  <select id="category-filter" onchange="filterProviders()">
415
  <option value="">All Categories</option>
@@ -421,7 +878,13 @@
421
  <option value="rpc">RPC</option>
422
  <option value="news">News</option>
423
  </select>
424
- <button class="btn btn-secondary" onclick="loadProviders()">🔄 Refresh</button>
 
 
 
 
 
 
425
  </div>
426
  <div id="providers-table"></div>
427
  </div>
@@ -430,18 +893,43 @@
430
  <!-- Market Data Tab -->
431
  <div id="tab-market" class="tab-content">
432
  <div class="card">
433
- <h3>Live Market Data</h3>
434
- <button class="btn btn-primary" onclick="loadMarketData()">🔄 Refresh Prices</button>
 
 
 
 
 
 
 
 
 
 
 
 
435
  <div id="market-data-container"></div>
436
  </div>
437
 
438
  <div class="card">
439
- <h3>Sentiment Analysis</h3>
 
 
 
 
 
 
 
 
440
  <div id="sentiment-data"></div>
441
  </div>
442
 
443
  <div class="card">
444
- <h3>Trending Coins</h3>
 
 
 
 
 
445
  <div id="trending-coins"></div>
446
  </div>
447
  </div>
@@ -449,27 +937,56 @@
449
  <!-- APL Tab -->
450
  <div id="tab-apl" class="tab-content">
451
  <div class="card">
452
- <h3>Auto Provider Loader (APL)</h3>
 
 
 
 
 
 
453
  <p style="color: var(--text-muted); margin-bottom: 20px;">
454
  APL automatically discovers, validates, and integrates cryptocurrency data providers.
455
  All validations use REAL API calls - NO MOCK DATA.
456
  </p>
457
 
458
  <button class="btn btn-success" onclick="runAPL()" id="apl-run-btn">
459
- 🤖 Run APL Scan
 
 
 
 
 
 
 
 
 
 
460
  </button>
461
- <button class="btn btn-secondary" onclick="loadAPLReport()">📊 View Last Report</button>
462
 
463
  <div id="apl-status" style="margin-top: 20px;"></div>
464
  </div>
465
 
466
  <div class="card">
467
- <h3>APL Summary Statistics</h3>
 
 
 
 
 
 
 
 
468
  <div id="apl-summary"></div>
469
  </div>
470
 
471
  <div class="card">
472
- <h3>APL Output</h3>
 
 
 
 
 
 
473
  <pre id="apl-output" style="max-height: 400px; overflow-y: auto;">No output yet. Click "Run APL Scan" to start.</pre>
474
  </div>
475
  </div>
@@ -477,16 +994,35 @@
477
  <!-- HF Models Tab -->
478
  <div id="tab-hf-models" class="tab-content">
479
  <div class="card">
480
- <h3>Hugging Face Models</h3>
 
 
 
 
 
 
 
 
481
  <p style="color: var(--text-muted); margin-bottom: 20px;">
482
  HuggingFace models validated by APL for crypto sentiment analysis and NLP tasks.
483
  </p>
484
- <button class="btn btn-primary" onclick="loadHFModels()">🔄 Refresh Models</button>
 
 
 
 
 
 
485
  <div id="hf-models-container"></div>
486
  </div>
487
 
488
  <div class="card">
489
- <h3>HF Services Health</h3>
 
 
 
 
 
490
  <div id="hf-health"></div>
491
  </div>
492
  </div>
@@ -494,10 +1030,32 @@
494
  <!-- Diagnostics Tab -->
495
  <div id="tab-diagnostics" class="tab-content">
496
  <div class="card">
497
- <h3>System Diagnostics</h3>
498
- <button class="btn btn-primary" onclick="runDiagnostics(true)">🔧 Run with Auto-Fix</button>
499
- <button class="btn btn-secondary" onclick="runDiagnostics(false)">🔍 Run Scan Only</button>
500
- <button class="btn btn-secondary" onclick="loadLastDiagnostics()">📋 View Last Results</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
501
 
502
  <div id="diagnostics-results" style="margin-top: 20px;"></div>
503
  </div>
@@ -506,9 +1064,28 @@
506
  <!-- Logs Tab -->
507
  <div id="tab-logs" class="tab-content">
508
  <div class="card">
509
- <h3>System Logs</h3>
510
- <button class="btn btn-primary" onclick="loadRecentLogs()">🔄 Refresh</button>
511
- <button class="btn btn-danger" onclick="loadErrorLogs()">❌ Errors Only</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
512
 
513
  <div id="logs-container" style="margin-top: 20px;"></div>
514
  </div>
@@ -578,7 +1155,7 @@
578
  market.cryptocurrencies.forEach(coin => {
579
  const changeClass = coin.change_24h >= 0 ? 'status-online' : 'status-offline';
580
  marketHTML += `
581
- <div style="background: var(--bg-dark); padding: 15px; border-radius: 8px;">
582
  <div style="font-weight: 600;">${coin.name} (${coin.symbol})</div>
583
  <div style="font-size: 24px; margin: 10px 0;">$${coin.price.toLocaleString()}</div>
584
  <div class="${changeClass}">${coin.change_24h >= 0 ? '↑' : '↓'} ${Math.abs(coin.change_24h).toFixed(2)}%</div>
@@ -661,10 +1238,10 @@
661
  <tr>
662
  <td>${coin.rank}</td>
663
  <td><strong>${coin.name}</strong> (${coin.symbol})</td>
664
- <td>$${coin.price.toLocaleString()}</td>
665
  <td class="${changeClass}">${coin.change_24h >= 0 ? '+' : ''}${coin.change_24h.toFixed(2)}%</td>
666
- <td>$${(coin.market_cap / 1e9).toFixed(2)}B</td>
667
- <td>$${(coin.volume_24h / 1e9).toFixed(2)}B</td>
668
  </tr>
669
  `;
670
  });
@@ -713,7 +1290,7 @@
713
  let html = '<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px;">';
714
  data.trending.forEach(coin => {
715
  html += `
716
- <div style="background: var(--bg-dark); padding: 15px; border-radius: 8px;">
717
  <div style="font-weight: 600;">${coin.name}</div>
718
  <div style="color: var(--text-muted);">${coin.symbol}</div>
719
  ${coin.market_cap_rank ? `<div style="margin-top: 10px;">Rank: #${coin.market_cap_rank}</div>` : ''}
@@ -745,9 +1322,14 @@
745
  if (result.status === 'completed') {
746
  document.getElementById('apl-status').innerHTML = `
747
  <div class="success-message">
748
- APL scan completed successfully!<br>
749
- Providers count: ${result.providers_count}<br>
750
- Time: ${result.timestamp}
 
 
 
 
 
751
  </div>
752
  `;
753
  document.getElementById('apl-output').textContent = result.stdout || 'Scan completed.';
@@ -756,7 +1338,14 @@
756
  await loadAPLSummary();
757
 
758
  } else {
759
- document.getElementById('apl-status').innerHTML = `<div class="error-message">APL scan ${result.status}: ${result.message || 'Unknown error'}</div>`;
 
 
 
 
 
 
 
760
  document.getElementById('apl-output').textContent = result.stdout || 'No output';
761
  }
762
  } catch (error) {
@@ -764,7 +1353,7 @@
764
  document.getElementById('apl-status').innerHTML = '<div class="error-message">Failed to run APL: ' + error.message + '</div>';
765
  } finally {
766
  btn.disabled = false;
767
- btn.textContent = '🤖 Run APL Scan';
768
  }
769
  }
770
 
@@ -862,7 +1451,7 @@
862
 
863
  const statusClass = health.ok ? 'status-online' : 'status-offline';
864
  document.getElementById('hf-health').innerHTML = `
865
- <div style="padding: 20px; background: var(--bg-dark); border-radius: 8px;">
866
  <div class="${statusClass}" style="font-size: 24px; font-weight: 700;">${health.ok ? '✓ Healthy' : '✗ Unhealthy'}</div>
867
  ${health.ok ? `
868
  <div style="margin-top: 15px;">
@@ -888,9 +1477,14 @@
888
 
889
  let html = `
890
  <div class="success-message">
891
- Diagnostics completed<br>
892
- Issues found: ${result.issues_found}<br>
893
- Time: ${result.timestamp}
 
 
 
 
 
894
  </div>
895
  `;
896
 
@@ -1014,4 +1608,4 @@
1014
  });
1015
  </script>
1016
  </body>
1017
- </html>
 
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Admin Dashboard - Crypto Monitor</title>
7
  <style>
8
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
9
+
10
+ * {
11
+ margin: 0;
12
+ padding: 0;
13
+ box-sizing: border-box;
14
+ }
15
 
16
  :root {
17
+ --primary: #6366f1;
18
+ --primary-dark: #4f46e5;
19
+ --primary-light: #818cf8;
20
+ --success: #10b981;
21
+ --warning: #f59e0b;
22
+ --danger: #ef4444;
23
+ --info: #3b82f6;
24
+ --bg-dark: #0f172a;
25
+ --bg-darker: #020617;
26
+ --bg-card: #1e293b;
27
+ --bg-card-hover: #334155;
28
+ --text-light: #f1f5f9;
29
+ --text-muted: #94a3b8;
30
+ --border: #334155;
31
+ --border-light: #475569;
32
+ --shadow: rgba(0, 0, 0, 0.5);
33
+ --gradient-primary: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
34
+ --gradient-success: linear-gradient(135deg, #10b981 0%, #14b8a6 100%);
35
+ --gradient-danger: linear-gradient(135deg, #ef4444 0%, #f43f5e 100%);
36
  }
37
 
38
  body {
39
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
40
+ background: var(--bg-darker);
41
  color: var(--text-light);
42
  line-height: 1.6;
43
+ overflow-x: hidden;
44
  }
45
 
46
  .container {
47
+ max-width: 2000px;
48
  margin: 0 auto;
49
+ padding: 24px;
50
+ }
51
+
52
+ /* Animated background */
53
+ body::before {
54
+ content: '';
55
+ position: fixed;
56
+ top: 0;
57
+ left: 0;
58
+ width: 100%;
59
+ height: 100%;
60
+ background:
61
+ radial-gradient(circle at 20% 50%, rgba(251, 191, 36, 0.12) 0%, transparent 50%),
62
+ radial-gradient(circle at 80% 80%, rgba(16, 185, 129, 0.12) 0%, transparent 50%),
63
+ radial-gradient(circle at 50% 20%, rgba(99, 102, 241, 0.08) 0%, transparent 50%);
64
+ z-index: -1;
65
+ animation: pulse 15s ease-in-out infinite;
66
  }
67
 
68
+ @keyframes pulse {
69
+ 0%, 100% { opacity: 0.5; }
70
+ 50% { opacity: 0.8; }
71
+ }
72
+
73
+ /* Header */
74
  header {
75
+ background: var(--gradient-primary);
76
+ padding: 32px;
77
+ border-radius: 20px;
78
+ margin-bottom: 32px;
79
+ box-shadow: 0 20px 60px var(--shadow);
80
+ position: relative;
81
+ overflow: hidden;
82
+ }
83
+
84
+ header::before {
85
+ content: '';
86
+ position: absolute;
87
+ top: -50%;
88
+ right: -50%;
89
+ width: 200%;
90
+ height: 200%;
91
+ background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
92
+ animation: rotate 20s linear infinite;
93
+ }
94
+
95
+ @keyframes rotate {
96
+ from { transform: rotate(0deg); }
97
+ to { transform: rotate(360deg); }
98
+ }
99
+
100
+ header .content {
101
+ position: relative;
102
+ z-index: 1;
103
  }
104
 
105
  header h1 {
106
+ font-size: 36px;
107
+ font-weight: 800;
108
+ margin-bottom: 8px;
109
+ display: flex;
110
+ align-items: center;
111
+ gap: 16px;
112
+ }
113
+
114
+ header .icon {
115
+ width: 48px;
116
+ height: 48px;
117
+ background: rgba(255, 255, 255, 0.2);
118
+ border-radius: 12px;
119
+ display: flex;
120
+ align-items: center;
121
+ justify-content: center;
122
+ backdrop-filter: blur(10px);
123
+ }
124
+
125
+ header .icon svg {
126
+ color: #fbbf24;
127
+ filter: drop-shadow(0 0 8px rgba(251, 191, 36, 0.6));
128
  }
129
 
130
  header .subtitle {
131
+ color: rgba(255, 255, 255, 0.95);
132
+ font-size: 15px;
133
+ font-weight: 500;
134
+ opacity: 0.9;
135
  }
136
 
137
+ /* Tabs */
138
  .tabs {
139
  display: flex;
140
+ gap: 12px;
141
+ margin-bottom: 32px;
142
  flex-wrap: wrap;
143
+ background: var(--bg-card);
144
+ padding: 8px;
145
+ border-radius: 16px;
146
+ border: 1px solid var(--border);
147
  }
148
 
149
  .tab-btn {
150
  padding: 12px 24px;
151
+ background: transparent;
152
+ border: none;
153
+ border-radius: 12px;
154
  cursor: pointer;
155
  font-weight: 600;
156
+ color: var(--text-muted);
157
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
158
+ font-size: 14px;
159
+ display: flex;
160
+ align-items: center;
161
+ gap: 8px;
162
  }
163
 
164
  .tab-btn:hover {
165
+ background: var(--bg-card-hover);
166
+ color: var(--text-light);
167
+ transform: translateY(-2px);
168
  }
169
 
170
  .tab-btn.active {
171
+ background: var(--gradient-primary);
172
+ color: white;
173
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
174
  }
175
 
176
+ /* Tab Content */
177
  .tab-content {
178
  display: none;
179
+ animation: fadeSlideIn 0.4s cubic-bezier(0.4, 0, 0.2, 1);
180
  }
181
 
182
  .tab-content.active {
183
  display: block;
184
  }
185
 
186
+ @keyframes fadeSlideIn {
187
+ from {
188
+ opacity: 0;
189
+ transform: translateY(20px);
190
+ }
191
+ to {
192
+ opacity: 1;
193
+ transform: translateY(0);
194
+ }
195
  }
196
 
197
+ /* Cards */
198
  .card {
199
  background: var(--bg-card);
200
+ border-radius: 16px;
201
+ padding: 28px;
202
+ margin-bottom: 24px;
203
  border: 1px solid var(--border);
204
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.2);
205
+ transition: all 0.3s ease;
206
+ position: relative;
207
+ overflow: hidden;
208
+ }
209
+
210
+ .card::before {
211
+ content: '';
212
+ position: absolute;
213
+ top: 0;
214
+ left: 0;
215
+ width: 100%;
216
+ height: 4px;
217
+ background: linear-gradient(90deg, #10b981 0%, #14b8a6 50%, #06b6d4 100%);
218
+ transform: scaleX(0);
219
+ transition: transform 0.3s ease;
220
+ }
221
+
222
+ .card:hover {
223
+ border-color: var(--border-light);
224
+ transform: translateY(-4px);
225
+ box-shadow: 0 12px 40px rgba(16, 185, 129, 0.15);
226
+ }
227
+
228
+ .card:hover::before {
229
+ transform: scaleX(1);
230
  }
231
 
232
  .card h3 {
233
+ color: #10b981;
234
+ margin-bottom: 20px;
235
+ font-size: 22px;
236
+ font-weight: 700;
237
+ display: flex;
238
+ align-items: center;
239
+ gap: 12px;
240
+ text-shadow: 0 0 20px rgba(16, 185, 129, 0.3);
241
  }
242
 
243
+ /* Stats Grid */
244
  .stats-grid {
245
  display: grid;
246
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
247
+ gap: 20px;
248
+ margin-bottom: 24px;
249
  }
250
 
251
  .stat-card {
252
+ background: linear-gradient(135deg, var(--bg-card) 0%, var(--bg-darker) 100%);
253
+ padding: 24px;
254
+ border-radius: 16px;
255
  border: 1px solid var(--border);
256
+ transition: all 0.3s ease;
257
+ position: relative;
258
+ overflow: hidden;
259
+ }
260
+
261
+ .stat-card::after {
262
+ content: '';
263
+ position: absolute;
264
+ top: -50%;
265
+ right: -50%;
266
+ width: 200%;
267
+ height: 200%;
268
+ background: radial-gradient(circle, rgba(251, 191, 36, 0.15) 0%, transparent 70%);
269
+ opacity: 0;
270
+ transition: opacity 0.3s ease;
271
+ }
272
+
273
+ .stat-card:hover {
274
+ transform: translateY(-4px) scale(1.02);
275
+ box-shadow: 0 12px 32px rgba(251, 191, 36, 0.25);
276
+ border-color: #fbbf24;
277
+ }
278
+
279
+ .stat-card:hover::after {
280
+ opacity: 1;
281
  }
282
 
283
  .stat-card .label {
284
  color: var(--text-muted);
285
+ font-size: 13px;
286
  text-transform: uppercase;
287
+ letter-spacing: 1px;
288
+ font-weight: 600;
289
+ margin-bottom: 8px;
290
  }
291
 
292
  .stat-card .value {
293
+ font-size: 40px;
294
+ font-weight: 800;
295
+ background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 50%, #ea580c 100%);
296
+ -webkit-background-clip: text;
297
+ -webkit-text-fill-color: transparent;
298
+ background-clip: text;
299
+ margin: 8px 0;
300
+ line-height: 1;
301
+ filter: drop-shadow(0 0 12px rgba(251, 191, 36, 0.3));
302
  }
303
 
304
  .stat-card .badge {
305
+ display: inline-flex;
306
+ align-items: center;
307
+ gap: 6px;
308
+ padding: 6px 12px;
309
+ border-radius: 8px;
310
+ font-size: 12px;
311
  font-weight: 600;
312
+ margin-top: 8px;
313
  }
314
 
315
  .badge-success {
316
+ background: rgba(16, 185, 129, 0.15);
317
+ color: var(--success);
318
+ border: 1px solid rgba(16, 185, 129, 0.3);
319
  }
320
 
321
  .badge-warning {
322
+ background: rgba(245, 158, 11, 0.15);
323
+ color: var(--warning);
324
+ border: 1px solid rgba(245, 158, 11, 0.3);
325
  }
326
 
327
  .badge-danger {
328
+ background: rgba(239, 68, 68, 0.15);
329
+ color: var(--danger);
330
+ border: 1px solid rgba(239, 68, 68, 0.3);
331
  }
332
 
333
+ /* Buttons */
334
  .btn {
335
+ padding: 12px 24px;
336
  border: none;
337
+ border-radius: 10px;
338
  cursor: pointer;
339
  font-weight: 600;
340
+ transition: all 0.3s ease;
341
+ margin-right: 12px;
342
+ margin-bottom: 12px;
343
+ font-size: 14px;
344
+ display: inline-flex;
345
+ align-items: center;
346
+ gap: 8px;
347
+ position: relative;
348
+ overflow: hidden;
349
+ }
350
+
351
+ .btn::before {
352
+ content: '';
353
+ position: absolute;
354
+ top: 50%;
355
+ left: 50%;
356
+ width: 0;
357
+ height: 0;
358
+ border-radius: 50%;
359
+ background: rgba(255, 255, 255, 0.2);
360
+ transform: translate(-50%, -50%);
361
+ transition: width 0.5s, height 0.5s;
362
+ }
363
+
364
+ .btn:hover::before {
365
+ width: 300px;
366
+ height: 300px;
367
+ }
368
+
369
+ .btn span {
370
+ position: relative;
371
+ z-index: 1;
372
  }
373
 
374
  .btn-primary {
375
+ background: var(--gradient-primary);
376
  color: white;
377
+ box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
378
  }
379
 
380
  .btn-primary:hover {
381
+ transform: translateY(-2px);
382
+ box-shadow: 0 6px 20px rgba(99, 102, 241, 0.4);
383
  }
384
 
385
  .btn-success {
386
+ background: var(--gradient-success);
387
  color: white;
388
+ box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
389
  }
390
 
391
  .btn-success:hover {
392
+ transform: translateY(-2px);
393
+ box-shadow: 0 6px 20px rgba(16, 185, 129, 0.4);
394
  }
395
 
396
  .btn-secondary {
 
400
  }
401
 
402
  .btn-secondary:hover {
403
+ background: var(--bg-card-hover);
404
+ border-color: var(--border-light);
405
+ transform: translateY(-2px);
406
+ }
407
+
408
+ .btn-danger {
409
+ background: var(--gradient-danger);
410
+ color: white;
411
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);
412
  }
413
 
414
+ /* Table */
415
  table {
416
  width: 100%;
417
+ border-collapse: separate;
418
+ border-spacing: 0;
419
+ margin-top: 20px;
420
  }
421
 
422
  table thead {
423
+ background: var(--bg-darker);
424
  }
425
 
426
  table th {
427
+ padding: 16px;
428
  text-align: left;
429
+ font-weight: 700;
430
+ font-size: 13px;
431
  text-transform: uppercase;
432
  color: var(--text-muted);
433
+ letter-spacing: 0.5px;
434
+ border-bottom: 2px solid var(--border);
435
  }
436
 
437
  table td {
438
+ padding: 16px;
439
+ border-bottom: 1px solid var(--border);
440
+ }
441
+
442
+ table tbody tr {
443
+ transition: all 0.2s ease;
444
  }
445
 
446
  table tbody tr:hover {
447
+ background: var(--bg-darker);
448
+ transform: scale(1.01);
449
+ }
450
+
451
+ table code {
452
+ background: var(--bg-darker);
453
+ padding: 4px 8px;
454
+ border-radius: 6px;
455
+ font-size: 12px;
456
+ color: var(--primary-light);
457
  }
458
 
459
+ /* Status colors */
460
  .status-online {
461
  color: var(--success);
462
+ font-weight: 600;
463
  }
464
 
465
  .status-offline {
466
  color: var(--danger);
467
+ font-weight: 600;
468
  }
469
 
470
  .status-degraded {
471
  color: var(--warning);
472
+ font-weight: 600;
473
  }
474
 
475
+ /* Messages */
476
  .loading {
477
  text-align: center;
478
+ padding: 60px 20px;
479
  color: var(--text-muted);
480
  }
481
 
482
+ .loading::after {
483
+ content: '';
484
+ display: block;
485
+ width: 48px;
486
+ height: 48px;
487
+ margin: 20px auto;
488
+ border: 4px solid var(--border);
489
+ border-top-color: var(--primary);
490
+ border-radius: 50%;
491
+ animation: spin 0.8s linear infinite;
492
+ }
493
+
494
+ @keyframes spin {
495
+ to { transform: rotate(360deg); }
496
+ }
497
+
498
  .error-message {
499
+ background: rgba(239, 68, 68, 0.15);
500
+ color: var(--danger);
501
+ padding: 16px 20px;
502
+ border-radius: 12px;
503
  margin-bottom: 20px;
504
+ border: 1px solid rgba(239, 68, 68, 0.3);
505
+ display: flex;
506
+ align-items: center;
507
+ gap: 12px;
508
  }
509
 
510
  .success-message {
511
+ background: rgba(16, 185, 129, 0.15);
512
+ color: var(--success);
513
+ padding: 16px 20px;
514
+ border-radius: 12px;
515
  margin-bottom: 20px;
516
+ border: 1px solid rgba(16, 185, 129, 0.3);
517
+ display: flex;
518
+ align-items: center;
519
+ gap: 12px;
520
  }
521
 
522
  .empty-state {
523
  text-align: center;
524
+ padding: 80px 20px;
525
  color: var(--text-muted);
526
  }
527
 
528
  .empty-state svg {
529
+ width: 80px;
530
+ height: 80px;
531
+ margin-bottom: 24px;
532
  opacity: 0.3;
533
  }
534
 
535
+ /* Filters */
536
  .filter-bar {
537
  display: flex;
538
+ gap: 12px;
539
  margin-bottom: 20px;
540
  flex-wrap: wrap;
541
  }
542
 
543
  select, input {
544
+ padding: 12px 16px;
545
+ border-radius: 10px;
546
  border: 1px solid var(--border);
547
+ background: var(--bg-darker);
548
  color: var(--text-light);
549
+ font-size: 14px;
550
+ transition: all 0.3s ease;
551
+ }
552
+
553
+ select:focus, input:focus {
554
+ outline: none;
555
+ border-color: var(--primary);
556
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
557
  }
558
 
559
+ /* Log entries */
560
  .log-entry {
561
+ padding: 16px;
562
  border-left: 3px solid var(--primary);
563
+ margin-bottom: 12px;
564
+ background: var(--bg-darker);
565
+ border-radius: 8px;
566
+ transition: all 0.2s ease;
567
+ }
568
+
569
+ .log-entry:hover {
570
+ background: var(--bg-card);
571
+ transform: translateX(4px);
572
  }
573
 
574
  .log-entry.error {
 
578
  .log-timestamp {
579
  color: var(--text-muted);
580
  font-size: 12px;
581
+ font-weight: 600;
582
  }
583
 
584
+ /* Code blocks */
585
  pre {
586
+ background: var(--bg-darker);
587
+ padding: 20px;
588
+ border-radius: 12px;
589
  overflow-x: auto;
590
  font-size: 13px;
591
+ line-height: 1.6;
592
+ border: 1px solid var(--border);
593
  }
594
 
595
+ /* Model cards */
596
  .model-card {
597
+ background: var(--bg-darker);
598
+ padding: 20px;
599
+ border-radius: 12px;
600
+ margin-bottom: 16px;
601
  border-left: 4px solid var(--primary);
602
+ transition: all 0.3s ease;
603
+ }
604
+
605
+ .model-card:hover {
606
+ transform: translateX(4px);
607
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
608
  }
609
 
610
  .model-card.valid {
 
619
  border-left-color: var(--danger);
620
  }
621
 
622
+ /* SVG Icons */
623
+ .icon-svg {
624
+ width: 20px;
625
+ height: 20px;
626
+ }
627
+
628
+ .tab-btn svg {
629
+ color: var(--primary-light);
630
+ transition: all 0.3s ease;
631
+ }
632
+
633
+ .tab-btn.active svg {
634
+ color: #fbbf24;
635
+ filter: drop-shadow(0 0 6px rgba(251, 191, 36, 0.5));
636
+ }
637
+
638
+ .tab-btn:hover svg {
639
+ color: #fbbf24;
640
+ transform: scale(1.1);
641
+ }
642
+
643
+ .card h3 svg {
644
+ color: #10b981;
645
+ filter: drop-shadow(0 0 6px rgba(16, 185, 129, 0.4));
646
+ }
647
+
648
+ .btn svg {
649
+ filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3));
650
+ }
651
+
652
+ .badge svg {
653
+ filter: drop-shadow(0 0 4px currentColor);
654
+ }
655
+
656
+ .success-message svg,
657
+ .error-message svg {
658
+ filter: drop-shadow(0 0 6px currentColor);
659
+ }
660
+
661
+ /* Responsive */
662
  @media (max-width: 768px) {
663
+ .container {
664
+ padding: 16px;
665
+ }
666
+
667
+ header {
668
+ padding: 24px;
669
+ }
670
+
671
+ header h1 {
672
+ font-size: 24px;
673
+ }
674
+
675
  .stats-grid {
676
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
677
  }
678
 
679
  .tabs {
 
685
  }
686
 
687
  table th, table td {
688
+ padding: 10px;
689
+ }
690
+
691
+ .stat-card .value {
692
+ font-size: 32px;
693
+ }
694
+ }
695
+
696
+ @media (min-width: 1920px) {
697
+ .stats-grid {
698
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
699
+ }
700
+
701
+ .card {
702
+ padding: 32px;
703
+ }
704
+
705
+ header h1 {
706
+ font-size: 42px;
707
  }
708
  }
709
  </style>
 
711
  <body>
712
  <div class="container">
713
  <header>
714
+ <div class="content">
715
+ <h1>
716
+ <div class="icon">
717
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
718
+ <path d="M12 2L2 7l10 5 10-5-10-5z"/>
719
+ <path d="M2 17l10 5 10-5"/>
720
+ <path d="M2 12l10 5 10-5"/>
721
+ </svg>
722
+ </div>
723
+ Crypto Monitor Admin Dashboard
724
+ </h1>
725
+ <p class="subtitle">Real-time provider management & system monitoring | NO MOCK DATA</p>
726
+ </div>
727
  </header>
728
 
729
  <div class="tabs">
730
+ <button class="tab-btn active" onclick="switchTab('status')">
731
+ <svg class="icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
732
+ <path d="M3 3v18h18"/>
733
+ <path d="M18 17V9"/>
734
+ <path d="M13 17V5"/>
735
+ <path d="M8 17v-3"/>
736
+ </svg>
737
+ <span>Status</span>
738
+ </button>
739
+ <button class="tab-btn" onclick="switchTab('providers')">
740
+ <svg class="icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
741
+ <circle cx="12" cy="12" r="3"/>
742
+ <path d="M12 1v6m0 6v6m8.66-16.5l-5.2 3m-3.92 6.5l-5.2 3M23 12h-6m-6 0H5m16.5 8.66l-3-5.2m-6.5-3.92l-3-5.2"/>
743
+ </svg>
744
+ <span>Providers</span>
745
+ </button>
746
+ <button class="tab-btn" onclick="switchTab('market')">
747
+ <svg class="icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
748
+ <path d="M12 2v20M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/>
749
+ </svg>
750
+ <span>Market Data</span>
751
+ </button>
752
+ <button class="tab-btn" onclick="switchTab('apl')">
753
+ <svg class="icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
754
+ <rect x="4" y="4" width="16" height="16" rx="2"/>
755
+ <path d="M9 9h.01M15 9h.01M9 15h6"/>
756
+ </svg>
757
+ <span>APL Scanner</span>
758
+ </button>
759
+ <button class="tab-btn" onclick="switchTab('hf-models')">
760
+ <svg class="icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
761
+ <path d="M12 8V4m0 16v-4"/>
762
+ <path d="M8 12H4m16 0h-4"/>
763
+ <circle cx="12" cy="12" r="3"/>
764
+ <path d="m8.2 8.2-1.5-1.5m10.6 0-1.5 1.5m-1.5 8.6-1.5 1.5m-6.2 0 1.5-1.5"/>
765
+ </svg>
766
+ <span>HF Models</span>
767
+ </button>
768
+ <button class="tab-btn" onclick="switchTab('diagnostics')">
769
+ <svg class="icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
770
+ <path d="M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z"/>
771
+ </svg>
772
+ <span>Diagnostics</span>
773
+ </button>
774
+ <button class="tab-btn" onclick="switchTab('logs')">
775
+ <svg class="icon-svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
776
+ <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/>
777
+ <path d="M14 2v6h6M16 13H8m8 4H8m2-8H8"/>
778
+ </svg>
779
+ <span>Logs</span>
780
+ </button>
781
  </div>
782
 
783
  <!-- Status Tab -->
 
786
  <div class="stat-card">
787
  <div class="label">System Health</div>
788
  <div class="value" id="system-health">-</div>
789
+ <span class="badge badge-success" id="health-badge">
790
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
791
+ <polyline points="20 6 9 17 4 12"/>
792
+ </svg>
793
+ Healthy
794
+ </span>
795
  </div>
796
  <div class="stat-card">
797
  <div class="label">Total Providers</div>
 
804
  <div class="stat-card">
805
  <div class="label">Database</div>
806
  <div class="value">✓</div>
807
+ <span class="badge badge-success">
808
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
809
+ <ellipse cx="12" cy="5" rx="9" ry="3"/>
810
+ <path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/>
811
+ </svg>
812
+ Connected
813
+ </span>
814
  </div>
815
  </div>
816
 
817
  <div class="card">
818
+ <h3>
819
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
820
+ <circle cx="12" cy="12" r="1"/>
821
+ <circle cx="12" cy="5" r="1"/>
822
+ <circle cx="12" cy="19" r="1"/>
823
+ </svg>
824
+ Quick Actions
825
+ </h3>
826
+ <button class="btn btn-primary" onclick="refreshAllData()">
827
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
828
+ <path d="M21 12a9 9 0 11-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/>
829
+ <path d="M21 3v5h-5"/>
830
+ </svg>
831
+ <span>Refresh All</span>
832
+ </button>
833
+ <button class="btn btn-success" onclick="runAPL()">
834
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
835
+ <rect x="4" y="4" width="16" height="16" rx="2"/>
836
+ <path d="M9 9h.01M15 9h.01M9 15h6"/>
837
+ </svg>
838
+ <span>Run APL Scan</span>
839
+ </button>
840
+ <button class="btn btn-secondary" onclick="runDiagnostics()">
841
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
842
+ <path d="M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z"/>
843
+ </svg>
844
+ <span>Run Diagnostics</span>
845
+ </button>
846
  </div>
847
 
848
  <div class="card">
849
+ <h3>
850
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
851
+ <path d="M3 3v18h18"/>
852
+ <path d="M18 17l-3-3-4 4-4-4-4 4"/>
853
+ </svg>
854
+ Recent Market Data
855
+ </h3>
856
  <div id="quick-market-view"></div>
857
  </div>
858
  </div>
 
860
  <!-- Providers Tab -->
861
  <div id="tab-providers" class="tab-content">
862
  <div class="card">
863
+ <h3>
864
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
865
+ <circle cx="12" cy="12" r="3"/>
866
+ <path d="M12 1v6m0 6v6m8.66-16.5l-5.2 3m-3.92 6.5l-5.2 3M23 12h-6m-6 0H5m16.5 8.66l-3-5.2m-6.5-3.92l-3-5.2"/>
867
+ </svg>
868
+ Providers Management
869
+ </h3>
870
  <div class="filter-bar">
871
  <select id="category-filter" onchange="filterProviders()">
872
  <option value="">All Categories</option>
 
878
  <option value="rpc">RPC</option>
879
  <option value="news">News</option>
880
  </select>
881
+ <button class="btn btn-secondary" onclick="loadProviders()">
882
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
883
+ <path d="M21 12a9 9 0 11-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/>
884
+ <path d="M21 3v5h-5"/>
885
+ </svg>
886
+ <span>Refresh</span>
887
+ </button>
888
  </div>
889
  <div id="providers-table"></div>
890
  </div>
 
893
  <!-- Market Data Tab -->
894
  <div id="tab-market" class="tab-content">
895
  <div class="card">
896
+ <h3>
897
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
898
+ <path d="M3 3v18h18"/>
899
+ <path d="M18 17l-3-3-4 4-4-4-4 4"/>
900
+ </svg>
901
+ Live Market Data
902
+ </h3>
903
+ <button class="btn btn-primary" onclick="loadMarketData()">
904
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
905
+ <path d="M21 12a9 9 0 11-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/>
906
+ <path d="M21 3v5h-5"/>
907
+ </svg>
908
+ <span>Refresh Prices</span>
909
+ </button>
910
  <div id="market-data-container"></div>
911
  </div>
912
 
913
  <div class="card">
914
+ <h3>
915
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
916
+ <circle cx="12" cy="12" r="10"/>
917
+ <path d="M8 14s1.5 2 4 2 4-2 4-2"/>
918
+ <line x1="9" y1="9" x2="9.01" y2="9"/>
919
+ <line x1="15" y1="9" x2="15.01" y2="9"/>
920
+ </svg>
921
+ Sentiment Analysis
922
+ </h3>
923
  <div id="sentiment-data"></div>
924
  </div>
925
 
926
  <div class="card">
927
+ <h3>
928
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
929
+ <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
930
+ </svg>
931
+ Trending Coins
932
+ </h3>
933
  <div id="trending-coins"></div>
934
  </div>
935
  </div>
 
937
  <!-- APL Tab -->
938
  <div id="tab-apl" class="tab-content">
939
  <div class="card">
940
+ <h3>
941
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
942
+ <rect x="4" y="4" width="16" height="16" rx="2"/>
943
+ <path d="M9 9h.01M15 9h.01M9 15h6"/>
944
+ </svg>
945
+ Auto Provider Loader (APL)
946
+ </h3>
947
  <p style="color: var(--text-muted); margin-bottom: 20px;">
948
  APL automatically discovers, validates, and integrates cryptocurrency data providers.
949
  All validations use REAL API calls - NO MOCK DATA.
950
  </p>
951
 
952
  <button class="btn btn-success" onclick="runAPL()" id="apl-run-btn">
953
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
954
+ <polygon points="5 3 19 12 5 21 5 3"/>
955
+ </svg>
956
+ <span>Run APL Scan</span>
957
+ </button>
958
+ <button class="btn btn-secondary" onclick="loadAPLReport()">
959
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
960
+ <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/>
961
+ <path d="M14 2v6h6M16 13H8m8 4H8m2-8H8"/>
962
+ </svg>
963
+ <span>View Last Report</span>
964
  </button>
 
965
 
966
  <div id="apl-status" style="margin-top: 20px;"></div>
967
  </div>
968
 
969
  <div class="card">
970
+ <h3>
971
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
972
+ <rect x="3" y="3" width="7" height="7"/>
973
+ <rect x="14" y="3" width="7" height="7"/>
974
+ <rect x="14" y="14" width="7" height="7"/>
975
+ <rect x="3" y="14" width="7" height="7"/>
976
+ </svg>
977
+ APL Summary Statistics
978
+ </h3>
979
  <div id="apl-summary"></div>
980
  </div>
981
 
982
  <div class="card">
983
+ <h3>
984
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
985
+ <polyline points="16 18 22 12 16 6"/>
986
+ <polyline points="8 6 2 12 8 18"/>
987
+ </svg>
988
+ APL Output
989
+ </h3>
990
  <pre id="apl-output" style="max-height: 400px; overflow-y: auto;">No output yet. Click "Run APL Scan" to start.</pre>
991
  </div>
992
  </div>
 
994
  <!-- HF Models Tab -->
995
  <div id="tab-hf-models" class="tab-content">
996
  <div class="card">
997
+ <h3>
998
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
999
+ <path d="M12 8V4m0 16v-4"/>
1000
+ <path d="M8 12H4m16 0h-4"/>
1001
+ <circle cx="12" cy="12" r="3"/>
1002
+ <path d="m8.2 8.2-1.5-1.5m10.6 0-1.5 1.5m-1.5 8.6-1.5 1.5m-6.2 0 1.5-1.5"/>
1003
+ </svg>
1004
+ Hugging Face Models
1005
+ </h3>
1006
  <p style="color: var(--text-muted); margin-bottom: 20px;">
1007
  HuggingFace models validated by APL for crypto sentiment analysis and NLP tasks.
1008
  </p>
1009
+ <button class="btn btn-primary" onclick="loadHFModels()">
1010
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1011
+ <path d="M21 12a9 9 0 11-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/>
1012
+ <path d="M21 3v5h-5"/>
1013
+ </svg>
1014
+ <span>Refresh Models</span>
1015
+ </button>
1016
  <div id="hf-models-container"></div>
1017
  </div>
1018
 
1019
  <div class="card">
1020
+ <h3>
1021
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1022
+ <path d="M22 12h-4l-3 9L9 3l-3 9H2"/>
1023
+ </svg>
1024
+ HF Services Health
1025
+ </h3>
1026
  <div id="hf-health"></div>
1027
  </div>
1028
  </div>
 
1030
  <!-- Diagnostics Tab -->
1031
  <div id="tab-diagnostics" class="tab-content">
1032
  <div class="card">
1033
+ <h3>
1034
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1035
+ <path d="M14.7 6.3a1 1 0 000 1.4l1.6 1.6a1 1 0 001.4 0l3.77-3.77a6 6 0 01-7.94 7.94l-6.91 6.91a2.12 2.12 0 01-3-3l6.91-6.91a6 6 0 017.94-7.94l-3.76 3.76z"/>
1036
+ </svg>
1037
+ System Diagnostics
1038
+ </h3>
1039
+ <button class="btn btn-primary" onclick="runDiagnostics(true)">
1040
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1041
+ <path d="M20 6L9 17l-5-5"/>
1042
+ </svg>
1043
+ <span>Run with Auto-Fix</span>
1044
+ </button>
1045
+ <button class="btn btn-secondary" onclick="runDiagnostics(false)">
1046
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1047
+ <circle cx="11" cy="11" r="8"/>
1048
+ <path d="m21 21-4.35-4.35"/>
1049
+ </svg>
1050
+ <span>Run Scan Only</span>
1051
+ </button>
1052
+ <button class="btn btn-secondary" onclick="loadLastDiagnostics()">
1053
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1054
+ <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/>
1055
+ <path d="M14 2v6h6"/>
1056
+ </svg>
1057
+ <span>View Last Results</span>
1058
+ </button>
1059
 
1060
  <div id="diagnostics-results" style="margin-top: 20px;"></div>
1061
  </div>
 
1064
  <!-- Logs Tab -->
1065
  <div id="tab-logs" class="tab-content">
1066
  <div class="card">
1067
+ <h3>
1068
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1069
+ <path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/>
1070
+ <path d="M14 2v6h6M16 13H8m8 4H8m2-8H8"/>
1071
+ </svg>
1072
+ System Logs
1073
+ </h3>
1074
+ <button class="btn btn-primary" onclick="loadRecentLogs()">
1075
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1076
+ <path d="M21 12a9 9 0 11-9-9c2.52 0 4.93 1 6.74 2.74L21 8"/>
1077
+ <path d="M21 3v5h-5"/>
1078
+ </svg>
1079
+ <span>Refresh</span>
1080
+ </button>
1081
+ <button class="btn btn-danger" onclick="loadErrorLogs()">
1082
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1083
+ <circle cx="12" cy="12" r="10"/>
1084
+ <line x1="15" y1="9" x2="9" y2="15"/>
1085
+ <line x1="9" y1="9" x2="15" y2="15"/>
1086
+ </svg>
1087
+ <span>Errors Only</span>
1088
+ </button>
1089
 
1090
  <div id="logs-container" style="margin-top: 20px;"></div>
1091
  </div>
 
1155
  market.cryptocurrencies.forEach(coin => {
1156
  const changeClass = coin.change_24h >= 0 ? 'status-online' : 'status-offline';
1157
  marketHTML += `
1158
+ <div style="background: var(--bg-darker); padding: 15px; border-radius: 8px;">
1159
  <div style="font-weight: 600;">${coin.name} (${coin.symbol})</div>
1160
  <div style="font-size: 24px; margin: 10px 0;">$${coin.price.toLocaleString()}</div>
1161
  <div class="${changeClass}">${coin.change_24h >= 0 ? '↑' : '↓'} ${Math.abs(coin.change_24h).toFixed(2)}%</div>
 
1238
  <tr>
1239
  <td>${coin.rank}</td>
1240
  <td><strong>${coin.name}</strong> (${coin.symbol})</td>
1241
+ <td>${coin.price.toLocaleString()}</td>
1242
  <td class="${changeClass}">${coin.change_24h >= 0 ? '+' : ''}${coin.change_24h.toFixed(2)}%</td>
1243
+ <td>${(coin.market_cap / 1e9).toFixed(2)}B</td>
1244
+ <td>${(coin.volume_24h / 1e9).toFixed(2)}B</td>
1245
  </tr>
1246
  `;
1247
  });
 
1290
  let html = '<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 15px;">';
1291
  data.trending.forEach(coin => {
1292
  html += `
1293
+ <div style="background: var(--bg-darker); padding: 15px; border-radius: 8px;">
1294
  <div style="font-weight: 600;">${coin.name}</div>
1295
  <div style="color: var(--text-muted);">${coin.symbol}</div>
1296
  ${coin.market_cap_rank ? `<div style="margin-top: 10px;">Rank: #${coin.market_cap_rank}</div>` : ''}
 
1322
  if (result.status === 'completed') {
1323
  document.getElementById('apl-status').innerHTML = `
1324
  <div class="success-message">
1325
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1326
+ <path d="M20 6L9 17l-5-5"/>
1327
+ </svg>
1328
+ <div>
1329
+ APL scan completed successfully!<br>
1330
+ Providers count: ${result.providers_count}<br>
1331
+ Time: ${result.timestamp}
1332
+ </div>
1333
  </div>
1334
  `;
1335
  document.getElementById('apl-output').textContent = result.stdout || 'Scan completed.';
 
1338
  await loadAPLSummary();
1339
 
1340
  } else {
1341
+ document.getElementById('apl-status').innerHTML = `<div class="error-message">
1342
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1343
+ <circle cx="12" cy="12" r="10"/>
1344
+ <line x1="15" y1="9" x2="9" y2="15"/>
1345
+ <line x1="9" y1="9" x2="15" y2="15"/>
1346
+ </svg>
1347
+ APL scan ${result.status}: ${result.message || 'Unknown error'}
1348
+ </div>`;
1349
  document.getElementById('apl-output').textContent = result.stdout || 'No output';
1350
  }
1351
  } catch (error) {
 
1353
  document.getElementById('apl-status').innerHTML = '<div class="error-message">Failed to run APL: ' + error.message + '</div>';
1354
  } finally {
1355
  btn.disabled = false;
1356
+ btn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="5 3 19 12 5 21 5 3"/></svg><span>Run APL Scan</span>';
1357
  }
1358
  }
1359
 
 
1451
 
1452
  const statusClass = health.ok ? 'status-online' : 'status-offline';
1453
  document.getElementById('hf-health').innerHTML = `
1454
+ <div style="padding: 20px; background: var(--bg-darker); border-radius: 8px;">
1455
  <div class="${statusClass}" style="font-size: 24px; font-weight: 700;">${health.ok ? '✓ Healthy' : '✗ Unhealthy'}</div>
1456
  ${health.ok ? `
1457
  <div style="margin-top: 15px;">
 
1477
 
1478
  let html = `
1479
  <div class="success-message">
1480
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
1481
+ <path d="M20 6L9 17l-5-5"/>
1482
+ </svg>
1483
+ <div>
1484
+ Diagnostics completed<br>
1485
+ Issues found: ${result.issues_found}<br>
1486
+ Time: ${result.timestamp}
1487
+ </div>
1488
  </div>
1489
  `;
1490
 
 
1608
  });
1609
  </script>
1610
  </body>
1611
+ </html>