feat: add multi-asset sidebar (BTC, USD, XAU) with asset switching
- Added sidebar navigation with 3 tabs: Bitcoin, Dólar, Ouro - Added switchAsset() function to switch between assets - Updated CSS with sidebar layout (fixed 200px sidebar) - Updated script.js with asset state management - Sync sidebar clock and status with main header - BTC remains default active tab
This commit is contained in:
@@ -7,13 +7,44 @@
|
|||||||
let autoMode = false;
|
let autoMode = false;
|
||||||
let autoInterval = null;
|
let autoInterval = null;
|
||||||
let pollInterval = null;
|
let pollInterval = null;
|
||||||
|
let currentAsset = 'btc'; // 'btc', 'usd', 'xau'
|
||||||
const AGENT_EMOJIS = { brief: "📊", decio: "🎯", papert: "⚡", audit: "🔍" };
|
const AGENT_EMOJIS = { brief: "📊", decio: "🎯", papert: "⚡", audit: "🔍" };
|
||||||
const AGENT_COLORS = { brief: "#4fc3f7", decio: "#ffd54f", papert: "#69f0ae", audit: "#b388ff" };
|
const AGENT_COLORS = { brief: "#4fc3f7", decio: "#ffd54f", papert: "#69f0ae", audit: "#b388ff" };
|
||||||
|
|
||||||
|
// ── Asset Switching ───────────────────────────────────────────────────────────
|
||||||
|
const ASSET_SYMBOLS = { btc: '₿', usd: '💵', xau: '🪙' };
|
||||||
|
const ASSET_LABELS = { btc: 'Bitcoin', usd: 'Dólar', xau: 'Ouro' };
|
||||||
|
const ASSET_PAIRS = { btc: 'BTC/USD', usd: 'USD/BRL', xau: 'XAU/USD' };
|
||||||
|
|
||||||
|
function switchAsset(asset, btnEl) {
|
||||||
|
if (asset === currentAsset) return;
|
||||||
|
currentAsset = asset;
|
||||||
|
|
||||||
|
// Update sidebar buttons
|
||||||
|
document.querySelectorAll('.sidebar-btn').forEach(b => b.classList.remove('active'));
|
||||||
|
if (btnEl) btnEl.classList.add('active');
|
||||||
|
|
||||||
|
// Update header title dynamically
|
||||||
|
const titleEl = document.querySelector('.logo-text strong');
|
||||||
|
if (titleEl) titleEl.textContent = asset.toUpperCase();
|
||||||
|
|
||||||
|
// Reload data for new asset
|
||||||
|
loadConfig();
|
||||||
|
loadPortfolio();
|
||||||
|
loadMultiStratChart('live');
|
||||||
|
addLog('SYS', `Ativo alterado para ${ASSET_LABELS[asset]} (${ASSET_PAIRS[asset]})`);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Init ─────────────────────────────────────────────────────────────────────
|
// ── Init ─────────────────────────────────────────────────────────────────────
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
updateClock();
|
updateClock();
|
||||||
setInterval(updateClock, 1000);
|
setInterval(updateClock, 1000);
|
||||||
|
// Sidebar clock
|
||||||
|
setInterval(() => {
|
||||||
|
const now = new Date();
|
||||||
|
const el = document.getElementById('sidebarClock');
|
||||||
|
if (el) el.textContent = now.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' });
|
||||||
|
}, 1000);
|
||||||
startPolling();
|
startPolling();
|
||||||
loadAgentRegistry();
|
loadAgentRegistry();
|
||||||
loadMetrics();
|
loadMetrics();
|
||||||
@@ -75,6 +106,11 @@ function updateStatus(text, type) {
|
|||||||
const txt = document.getElementById('statusText');
|
const txt = document.getElementById('statusText');
|
||||||
if (dot) dot.className = `status-dot ${type}`;
|
if (dot) dot.className = `status-dot ${type}`;
|
||||||
if (txt) txt.textContent = text;
|
if (txt) txt.textContent = text;
|
||||||
|
// Sync sidebar status
|
||||||
|
const sidebarDot = document.getElementById('sidebarStatusDot');
|
||||||
|
const sidebarTxt = document.getElementById('sidebarStatusText');
|
||||||
|
if (sidebarDot) sidebarDot.className = `status-dot ${type}`;
|
||||||
|
if (sidebarTxt) sidebarTxt.textContent = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Pipeline ─────────────────────────────────────────────────────────────────
|
// ── Pipeline ─────────────────────────────────────────────────────────────────
|
||||||
|
|||||||
+83
-6
@@ -15,27 +15,104 @@
|
|||||||
--shadow: 0 8px 32px rgba(0,0,0,0.4);
|
--shadow: 0 8px 32px rgba(0,0,0,0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Reset & Base ───────────────────────────────────────── */
|
/* ── Reset & Base ───────────────────────────────────── */
|
||||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||||
|
|
||||||
|
/* ── Sidebar Layout ──────────────────────────────────── */
|
||||||
body {
|
body {
|
||||||
|
display: flex;
|
||||||
|
min-height: 100vh;
|
||||||
font-family: 'Exo 2', 'Noto Sans JP', sans-serif;
|
font-family: 'Exo 2', 'Noto Sans JP', sans-serif;
|
||||||
background: var(--bg-dark);
|
background: var(--bg-dark);
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
min-height: 100vh;
|
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Dashboard Layout ───────────────────────────────────── */
|
/* ── Sidebar ─────────────────────────────────────────── */
|
||||||
.dashboard {
|
.sidebar {
|
||||||
|
width: 200px;
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--bg-card);
|
||||||
|
border-right: 1px solid rgba(79,195,247,0.1);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px 0;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
.sidebar-logo {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 0 16px 20px;
|
||||||
|
border-bottom: 1px solid rgba(255,255,255,0.05);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.sidebar-logo-icon { font-size: 1.8rem; }
|
||||||
|
.sidebar-logo-text { font-size: 0.9rem; line-height: 1.2; color: var(--text-primary); }
|
||||||
|
.sidebar-logo-text strong { color: var(--accent-blue); }
|
||||||
|
|
||||||
|
.sidebar-nav {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 0 10px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.sidebar-btn {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
padding: 14px 8px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.sidebar-btn:hover {
|
||||||
|
background: var(--bg-card-hover);
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
.sidebar-btn.active {
|
||||||
|
background: rgba(79,195,247,0.1);
|
||||||
|
color: var(--accent-blue);
|
||||||
|
border: 1px solid rgba(79,195,247,0.2);
|
||||||
|
}
|
||||||
|
.sidebar-icon { font-size: 1.6rem; }
|
||||||
|
.sidebar-label { font-size: 0.8rem; font-weight: 600; }
|
||||||
|
.sidebar-pair { font-size: 0.65rem; opacity: 0.6; }
|
||||||
|
|
||||||
|
.sidebar-footer {
|
||||||
|
padding: 16px;
|
||||||
|
border-top: 1px solid rgba(255,255,255,0.05);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.sidebar-clock { font-size: 1.1rem; color: var(--accent-blue); margin-bottom: 8px; }
|
||||||
|
.sidebar-status { display: flex; align-items: center; justify-content: center; gap: 6px; font-size: 0.75rem; color: var(--text-secondary); }
|
||||||
|
|
||||||
|
/* ── Main Content ────────────────────────────────────── */
|
||||||
|
.main-content {
|
||||||
|
margin-left: 200px;
|
||||||
|
flex: 1;
|
||||||
|
padding: 20px;
|
||||||
|
max-width: calc(100vw - 200px);
|
||||||
|
}
|
||||||
|
.main-content .dashboard {
|
||||||
max-width: 1400px;
|
max-width: 1400px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Header ──────────────────────────────────────────────── */
|
/* ── Header ──────────────────────────────────────────── */
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
+34
-1
@@ -8,7 +8,40 @@
|
|||||||
<link href="https://fonts.googleapis.com/css2?family=Exo+2:wght@400;600;700&family=Noto+Sans+JP:wght@400;500;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Exo+2:wght@400;600;700&family=Noto+Sans+JP:wght@400;500;700&display=swap" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="dashboard">
|
<!-- Sidebar -->
|
||||||
|
<nav class="sidebar" id="sidebar">
|
||||||
|
<div class="sidebar-logo">
|
||||||
|
<span class="sidebar-logo-icon">🏢</span>
|
||||||
|
<div class="sidebar-logo-text">BrainSteel<br><strong>Fin</strong></div>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-nav">
|
||||||
|
<button class="sidebar-btn active" onclick="switchAsset('btc', this)" data-asset="btc">
|
||||||
|
<span class="sidebar-icon">₿</span>
|
||||||
|
<span class="sidebar-label">Bitcoin</span>
|
||||||
|
<span class="sidebar-pair">BTC/USD</span>
|
||||||
|
</button>
|
||||||
|
<button class="sidebar-btn" onclick="switchAsset('usd', this)" data-asset="usd">
|
||||||
|
<span class="sidebar-icon">💵</span>
|
||||||
|
<span class="sidebar-label">Dólar</span>
|
||||||
|
<span class="sidebar-pair">USD/BRL</span>
|
||||||
|
</button>
|
||||||
|
<button class="sidebar-btn" onclick="switchAsset('xau', this)" data-asset="xau">
|
||||||
|
<span class="sidebar-icon">🪙</span>
|
||||||
|
<span class="sidebar-label">Ouro</span>
|
||||||
|
<span class="sidebar-pair">XAU/USD</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="sidebar-footer">
|
||||||
|
<div class="sidebar-clock" id="sidebarClock"></div>
|
||||||
|
<div class="sidebar-status">
|
||||||
|
<span class="status-dot" id="sidebarStatusDot"></span>
|
||||||
|
<span id="sidebarStatusText">Online</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="main-content" id="mainContent">
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<header class="header">
|
<header class="header">
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
|
|||||||
Reference in New Issue
Block a user