feat: full dashboard update when switching assets (header, agents, banner, sidebar status)

This commit is contained in:
2026-06-15 23:29:51 +00:00
parent 27d15afe6f
commit 9cb12ea6e6
+125 -10
View File
@@ -33,57 +33,159 @@ function switchAsset(asset, btnEl) {
loadConfig(); loadConfig();
loadPortfolio(); loadPortfolio();
loadMultiStratChart('live'); loadMultiStratChart('live');
// Update pipeline header
updatePipelineHeader();
addLog('SYS', `Ativo alterado para ${ASSET_LABELS[asset]} (${ASSET_PAIRS[asset]})`); addLog('SYS', `Ativo alterado para ${ASSET_LABELS[asset]} (${ASSET_PAIRS[asset]})`);
} }
function updatePipelineHeader() {
const h2 = document.querySelector('.pipeline-section h2');
if (h2) {
const emoji = currentAsset === 'btc' ? '📊' : currentAsset === 'usd' ? '💵' : '🪙';
h2.innerHTML = `${emoji} Pipeline ${ASSET_LABELS[currentAsset]}`;
}
// Update run button text
const btnRun = document.getElementById('btnRun');
if (btnRun) {
if (currentAsset === 'btc') {
btnRun.innerHTML = '▶ Executar Pipeline';
btnRun.disabled = false;
} else {
btnRun.innerHTML = `▶ Executar ${ASSET_LABELS[currentAsset]}`;
btnRun.disabled = false;
}
}
}
// ── Asset Brief Loader ─────────────────────────────────────────────────────── // ── Asset Brief Loader ───────────────────────────────────────────────────────
function loadAssetBrief() { function loadAssetBrief() {
if (currentAsset === 'btc') { if (currentAsset === 'btc') {
// BTC uses the existing pipeline via pollState // BTC uses the existing pipeline via pollState
pollState(); pollState();
showBTCPanels();
return; return;
} }
const apiMap = { const apiMap = { usd: '/api/usd/brief', xau: '/api/xau/brief' };
usd: '/api/usd/brief',
xau: '/api/xau/brief'
};
const api = apiMap[currentAsset]; const api = apiMap[currentAsset];
if (!api) return; if (!api) return;
// Show loading state on agent cards
updateAgentUI('brief', { status: 'working', message: `Carregando ${ASSET_LABELS[currentAsset]}...` });
updateAgentUI('decio', { status: 'waiting', message: 'Aguardando...' });
updateAgentUI('papert', { status: 'idle', message: 'Aguardando...' });
updateAgentUI('audit', { status: 'idle', message: 'Aguardando...' });
fetch(api) fetch(api)
.then(r => r.json()) .then(r => r.json())
.then(data => { .then(data => {
if (data.error) { if (data.error) {
addLog('SYS', `Erro ao carregar ${ASSET_LABELS[currentAsset]}: ${data.error}`); addLog('SYS', `Erro: ${data.error}`);
return; return;
} }
const brief = data.brief; const brief = data.brief;
const decio = data.decio; const decio = data.decio;
// Format price based on asset type
let priceStr = '-';
if (brief.price && brief.price > 0) {
if (currentAsset === 'usd') {
priceStr = `R$ ${brief.price.toFixed(4)}`;
} else if (currentAsset === 'xau') {
priceStr = `US$ ${brief.price.toLocaleString('pt-BR', {minimumFractionDigits: 2})}`;
}
}
// Update header with price badge
const headerStatus = document.querySelector('.header-status');
if (headerStatus) {
headerStatus.innerHTML = `
<span class="status-dot" id="statusDot" style="background:#69f0ae"></span>
<span id="statusText">${ASSET_LABELS[currentAsset]}: ${priceStr}</span>
`;
}
// Update brief agent card // Update brief agent card
const priceStr = brief.price let signalColor = '#888';
? (brief.price > 1000 ? brief.price.toLocaleString('pt-BR', {minimumFractionDigits: 2}) : brief.price.toFixed(4)) if (brief.signal === 'ALTA') signalColor = '#69f0ae';
: '-'; else if (brief.signal === 'BAIXA') signalColor = '#ff6b6b';
updateAgentUI('brief', { updateAgentUI('brief', {
status: 'done', status: 'done',
message: `${ASSET_PAIRS[currentAsset]}: ${priceStr}` message: `${ASSET_PAIRS[currentAsset]}: ${priceStr}`
}); });
// Update decio agent card // Update decio agent card
let decisionColor = '#888';
if (decio.decision === 'BUY') decisionColor = '#69f0ae';
else if (decio.decision === 'SELL') decisionColor = '#ff6b6b';
updateAgentUI('decio', { updateAgentUI('decio', {
status: 'done', status: 'done',
message: `Decisão: ${decio.decision} (${decio.confidence}%)` message: `Decisão: ${decio.decision} (${decio.confidence}%)`
}); });
// Update papert
updateAgentUI('papert', {
status: 'done',
message: `SL: ${decio.stop_loss || 0} | TP: ${decio.take_profit || 0}`
});
// Update audit
updateAgentUI('audit', {
status: 'done',
message: `${brief.signal} | RSI: ${brief.rsi || '-'}`
});
// Show decision banner
const banner = document.getElementById('lastDecisionBanner');
if (banner) {
banner.style.display = 'block';
banner.className = `decision-banner ${decio.decision.toLowerCase()}`;
banner.innerHTML = `
<div style="display:flex;align-items:center;gap:20px;flex-wrap:wrap">
<span style="font-size:1.5rem;font-weight:700;color:${decisionColor}">${decio.decision}</span>
<span style="color:var(--text-secondary)">Confiança: <b style="color:${decisionColor}">${decio.confidence}%</b></span>
${decio.stop_loss ? `<span style="color:var(--text-secondary)">Stop Loss: <b>${decio.stop_loss}</b></span>` : ''}
${decio.take_profit ? `<span style="color:var(--text-secondary)">Take Profit: <b>${decio.take_profit}</b></span>` : ''}
<span style="color:var(--text-secondary)">Signal: <b style="color:${signalColor}">${brief.signal}</b></span>
<span style="color:var(--text-secondary)">RSI: <b>${brief.rsi || '-'}</b></span>
${brief.change_24h !== undefined ? `<span style="color:var(--text-secondary)">24h: <b style="color:${brief.change_24h >= 0 ? '#69f0ae' : '#ff6b6b'}">${brief.change_24h >= 0 ? '+' : ''}${brief.change_24h}%</b></span>` : ''}
</div>
`;
}
// Update sidebar status
const sidebarDot = document.getElementById('sidebarStatusDot');
const sidebarText = document.getElementById('sidebarStatusText');
if (sidebarDot) sidebarDot.style.background = decisionColor;
if (sidebarText) sidebarText.textContent = `${decio.decision} ${decio.confidence}%`;
addLog('SYS', `${ASSET_LABELS[currentAsset]} | ${decio.decision} | Conf: ${decio.confidence}%`); addLog('SYS', `${ASSET_LABELS[currentAsset]} | ${decio.decision} | Conf: ${decio.confidence}%`);
}) })
.catch(err => { .catch(err => {
addLog('SYS', `Erro API ${currentAsset}: ${err.message}`); addLog('SYS', `Erro API ${currentAsset}: ${err.message}`);
updateAgentUI('brief', { status: 'error', message: 'Erro ao carregar' });
}); });
} }
function showBTCPanels() {
// Restore BTC panels
const banner = document.getElementById('lastDecisionBanner');
if (banner) banner.style.display = 'none';
const headerStatus = document.querySelector('.header-status');
if (headerStatus) {
headerStatus.innerHTML = `
<span class="status-dot" id="statusDot"></span>
<span id="statusText">Sistema online</span>
`;
}
const sidebarDot = document.getElementById('sidebarStatusDot');
const sidebarText = document.getElementById('sidebarStatusText');
if (sidebarDot) sidebarDot.style.background = '#69f0ae';
if (sidebarText) sidebarText.textContent = 'Online';
}
// ── Init ───────────────────────────────────────────────────────────────────── // ── Init ─────────────────────────────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
updateClock(); updateClock();
@@ -105,6 +207,7 @@ document.addEventListener('DOMContentLoaded', () => {
loadPortfolio(); loadPortfolio();
loadActivityLog(); loadActivityLog();
updateStatus('Sistema operacional', 'online'); updateStatus('Sistema operacional', 'online');
updatePipelineHeader();
// Load asset-specific data // Load asset-specific data
if (currentAsset === 'btc') { if (currentAsset === 'btc') {
pollState(); pollState();
@@ -121,11 +224,23 @@ function updateClock() {
// ── Polling ─────────────────────────────────────────────────────────────────── // ── Polling ───────────────────────────────────────────────────────────────────
function startPolling() { function startPolling() {
if (currentAsset === 'btc') {
pollState(); pollState();
pollInterval = setInterval(pollState, 3000); pollInterval = setInterval(() => {
if (currentAsset === 'btc') pollState();
}, 3000);
} else {
// For USD/XAU, poll the asset brief
loadAssetBrief();
pollInterval = setInterval(() => {
if (currentAsset !== 'btc') loadAssetBrief();
else pollState();
}, 10000);
}
} }
function pollState() { function pollState() {
if (currentAsset !== 'btc') return; // Don't poll BTC state when on other assets
fetch('/api/state') fetch('/api/state')
.then(r => r.json()) .then(r => r.json())
.then(data => { .then(data => {