Spaces:
Running
Running
Update index.html
Browse files- index.html +44 -19
index.html
CHANGED
|
@@ -702,7 +702,12 @@ body{font-family:'Outfit',sans-serif;background:var(--bg);color:var(--text);marg
|
|
| 702 |
<button onclick="loadLiveNews()" style="padding:4px 12px;border-radius:6px;border:1px solid rgba(255,255,255,0.1);background:rgba(255,255,255,0.03);color:var(--text);font-size:12px;cursor:pointer" title="Refresh">π</button>
|
| 703 |
</div>
|
| 704 |
<!-- COUNTERS -->
|
| 705 |
-
<div class="ln-counters" id="lnCounters"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 706 |
<!-- MVP / VILLAIN -->
|
| 707 |
<div class="ln-mvp-row" id="lnMvpRow" style="display:none"></div>
|
| 708 |
<!-- MAIN STUDIO (featured story with anchor) -->
|
|
@@ -2543,21 +2548,41 @@ const LN_CAT_LABELS = {
|
|
| 2543 |
let lnData = null, lnFilter = 'all', lnStudioIdx = 0, lnStudioTimer = null, lnAutoRefresh = null;
|
| 2544 |
|
| 2545 |
async function loadLiveNews(){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2546 |
try{
|
| 2547 |
-
const
|
| 2548 |
-
|
| 2549 |
-
|
| 2550 |
-
|
| 2551 |
-
|
| 2552 |
-
|
| 2553 |
-
|
| 2554 |
-
|
| 2555 |
-
|
| 2556 |
-
|
|
|
|
|
|
|
| 2557 |
}catch(e){
|
| 2558 |
-
console.error('Live news error:',e);
|
| 2559 |
-
|
|
|
|
|
|
|
|
|
|
| 2560 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2561 |
}
|
| 2562 |
|
| 2563 |
function renderLiveBreaking(items){
|
|
@@ -2574,13 +2599,13 @@ function renderLiveBreaking(items){
|
|
| 2574 |
|
| 2575 |
function renderLiveCounters(c){
|
| 2576 |
const el = document.getElementById('lnCounters');
|
| 2577 |
-
if(!c
|
| 2578 |
-
|
| 2579 |
-
|
| 2580 |
-
|
| 2581 |
-
const longPct = c.long_pct||50;
|
| 2582 |
el.innerHTML = `
|
| 2583 |
-
<div class="ln-counter"><div class="ln-counter-val" style="color:var(--accent2)">${
|
| 2584 |
<div class="ln-counter"><div class="ln-counter-val" style="color:var(--gold)">β‘${(c.total_risk_gpu||0).toLocaleString()}</div><div class="ln-counter-lbl">GPU at Risk</div><div style="font-size:10px;color:var(--muted);margin-top:2px">${c.active_traders||0} active traders</div></div>
|
| 2585 |
<div class="ln-counter"><div class="ln-counter-val" style="color:var(--red)">π ${c.liquidations_24h||0}</div><div class="ln-counter-lbl">Liquidations 24h</div><div style="font-size:10px;color:var(--red);margin-top:2px">${(c.liquidated_gpu_24h||0).toLocaleString()} GPU lost</div></div>
|
| 2586 |
<div class="ln-counter"><div class="ln-counter-val" style="color:#ff8a80">π¨ ${c.sec_violations_24h||0}</div><div class="ln-counter-lbl">SEC Actions 24h</div><div style="font-size:10px;color:var(--muted);margin-top:2px">βοΈ${c.sec_active_suspensions||0} suspended</div></div>
|
|
|
|
| 702 |
<button onclick="loadLiveNews()" style="padding:4px 12px;border-radius:6px;border:1px solid rgba(255,255,255,0.1);background:rgba(255,255,255,0.03);color:var(--text);font-size:12px;cursor:pointer" title="Refresh">π</button>
|
| 703 |
</div>
|
| 704 |
<!-- COUNTERS -->
|
| 705 |
+
<div class="ln-counters" id="lnCounters">
|
| 706 |
+
<div class="ln-counter"><div class="ln-counter-val" style="color:var(--accent2)">β</div><div class="ln-counter-lbl">Open Positions</div></div>
|
| 707 |
+
<div class="ln-counter"><div class="ln-counter-val" style="color:var(--gold)">β‘β</div><div class="ln-counter-lbl">GPU at Risk</div></div>
|
| 708 |
+
<div class="ln-counter"><div class="ln-counter-val" style="color:var(--red)">π β</div><div class="ln-counter-lbl">Liquidations 24h</div></div>
|
| 709 |
+
<div class="ln-counter"><div class="ln-counter-val" style="color:#ff8a80">π¨ β</div><div class="ln-counter-lbl">SEC Actions 24h</div></div>
|
| 710 |
+
</div>
|
| 711 |
<!-- MVP / VILLAIN -->
|
| 712 |
<div class="ln-mvp-row" id="lnMvpRow" style="display:none"></div>
|
| 713 |
<!-- MAIN STUDIO (featured story with anchor) -->
|
|
|
|
| 2548 |
let lnData = null, lnFilter = 'all', lnStudioIdx = 0, lnStudioTimer = null, lnAutoRefresh = null;
|
| 2549 |
|
| 2550 |
async function loadLiveNews(){
|
| 2551 |
+
const feedEl = document.getElementById('lnFeed');
|
| 2552 |
+
const titleEl = document.getElementById('lnFeedTitle');
|
| 2553 |
+
// Immediate visual feedback
|
| 2554 |
+
if(titleEl) titleEl.textContent = 'π‘ LIVE FEED β Fetching...';
|
| 2555 |
+
let r;
|
| 2556 |
try{
|
| 2557 |
+
const resp = await fetch('/api/live-news?hours=24');
|
| 2558 |
+
if(!resp.ok){
|
| 2559 |
+
// API returned error status
|
| 2560 |
+
const errText = await resp.text().catch(()=>'');
|
| 2561 |
+
console.error('Live news API status:', resp.status, errText);
|
| 2562 |
+
if(titleEl) titleEl.textContent = 'π‘ LIVE FEED β API Error ('+resp.status+')';
|
| 2563 |
+
if(feedEl) feedEl.innerHTML = `<div class="ln-no-stories"><div class="big">β οΈ</div><div style="font-size:14px;font-weight:600;color:var(--red)">API Error ${resp.status}</div><div style="font-size:11px;margin-top:6px;color:var(--muted);max-width:400px;word-break:break-all">${esc(errText.substring(0,300))}</div><div style="margin-top:12px"><button class="btn btn-primary" onclick="loadLiveNews()" style="padding:8px 20px;font-size:12px">π Retry</button></div></div>`;
|
| 2564 |
+
renderLiveCounters({});
|
| 2565 |
+
return;
|
| 2566 |
+
}
|
| 2567 |
+
r = await resp.json();
|
| 2568 |
+
console.log('Live news loaded:', r.total_stories||0, 'stories', r.error||'');
|
| 2569 |
}catch(e){
|
| 2570 |
+
console.error('Live news fetch error:', e);
|
| 2571 |
+
if(titleEl) titleEl.textContent = 'π‘ LIVE FEED β Connection Error';
|
| 2572 |
+
if(feedEl) feedEl.innerHTML = `<div class="ln-no-stories"><div class="big">π‘</div><div style="font-size:14px;font-weight:600;color:var(--red)">Failed to connect to Live News API</div><div style="font-size:11px;margin-top:6px;color:var(--muted)">${esc(String(e))}</div><div style="margin-top:12px"><button class="btn btn-primary" onclick="loadLiveNews()" style="padding:8px 20px;font-size:12px">π Retry</button></div></div>`;
|
| 2573 |
+
renderLiveCounters({});
|
| 2574 |
+
return;
|
| 2575 |
}
|
| 2576 |
+
if(!r){renderLiveCounters({});return;}
|
| 2577 |
+
lnData = r;
|
| 2578 |
+
try{renderLiveBreaking(r.breaking||[]);}catch(e){console.warn('LN Breaking render:',e);}
|
| 2579 |
+
try{renderLiveCounters(r.counters||{});}catch(e){console.warn('LN Counters render:',e);}
|
| 2580 |
+
try{renderLiveMvp(r.mvp||null, r.villain||null);}catch(e){console.warn('LN MVP render:',e);}
|
| 2581 |
+
try{renderLiveStudio(r.stories||[]);}catch(e){console.warn('LN Studio render:',e);}
|
| 2582 |
+
try{renderLiveFeed(r.stories||[]);}catch(e){console.warn('LN Feed render:',e);}
|
| 2583 |
+
// Auto-refresh every 60s
|
| 2584 |
+
if(lnAutoRefresh) clearInterval(lnAutoRefresh);
|
| 2585 |
+
lnAutoRefresh = setInterval(()=>{if(cTab==='livenews')loadLiveNews();},60000);
|
| 2586 |
}
|
| 2587 |
|
| 2588 |
function renderLiveBreaking(items){
|
|
|
|
| 2599 |
|
| 2600 |
function renderLiveCounters(c){
|
| 2601 |
const el = document.getElementById('lnCounters');
|
| 2602 |
+
if(!c) c={};
|
| 2603 |
+
const pos = c.active_positions||0;
|
| 2604 |
+
const lc = c.long_count||0;
|
| 2605 |
+
const sc = c.short_count||0;
|
| 2606 |
+
const longPct = c.long_pct||( pos>0 ? Math.round(lc/pos*100) : 50);
|
| 2607 |
el.innerHTML = `
|
| 2608 |
+
<div class="ln-counter"><div class="ln-counter-val" style="color:var(--accent2)">${pos}</div><div class="ln-counter-lbl">Open Positions</div><div style="font-size:10px;color:var(--muted);margin-top:2px">π’${lc} / π΄${sc} (${longPct}%L)</div></div>
|
| 2609 |
<div class="ln-counter"><div class="ln-counter-val" style="color:var(--gold)">β‘${(c.total_risk_gpu||0).toLocaleString()}</div><div class="ln-counter-lbl">GPU at Risk</div><div style="font-size:10px;color:var(--muted);margin-top:2px">${c.active_traders||0} active traders</div></div>
|
| 2610 |
<div class="ln-counter"><div class="ln-counter-val" style="color:var(--red)">π ${c.liquidations_24h||0}</div><div class="ln-counter-lbl">Liquidations 24h</div><div style="font-size:10px;color:var(--red);margin-top:2px">${(c.liquidated_gpu_24h||0).toLocaleString()} GPU lost</div></div>
|
| 2611 |
<div class="ln-counter"><div class="ln-counter-val" style="color:#ff8a80">π¨ ${c.sec_violations_24h||0}</div><div class="ln-counter-lbl">SEC Actions 24h</div><div style="font-size:10px;color:var(--muted);margin-top:2px">βοΈ${c.sec_active_suspensions||0} suspended</div></div>
|