feat: full dashboard update when switching assets (header, agents, banner, sidebar status)
This commit is contained in:
+125
-10
@@ -33,57 +33,159 @@ function switchAsset(asset, btnEl) {
|
||||
loadConfig();
|
||||
loadPortfolio();
|
||||
loadMultiStratChart('live');
|
||||
// Update pipeline header
|
||||
updatePipelineHeader();
|
||||
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 ───────────────────────────────────────────────────────
|
||||
function loadAssetBrief() {
|
||||
if (currentAsset === 'btc') {
|
||||
// BTC uses the existing pipeline via pollState
|
||||
pollState();
|
||||
showBTCPanels();
|
||||
return;
|
||||
}
|
||||
|
||||
const apiMap = {
|
||||
usd: '/api/usd/brief',
|
||||
xau: '/api/xau/brief'
|
||||
};
|
||||
|
||||
const apiMap = { usd: '/api/usd/brief', xau: '/api/xau/brief' };
|
||||
const api = apiMap[currentAsset];
|
||||
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)
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
addLog('SYS', `Erro ao carregar ${ASSET_LABELS[currentAsset]}: ${data.error}`);
|
||||
addLog('SYS', `Erro: ${data.error}`);
|
||||
return;
|
||||
}
|
||||
const brief = data.brief;
|
||||
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
|
||||
const priceStr = brief.price
|
||||
? (brief.price > 1000 ? brief.price.toLocaleString('pt-BR', {minimumFractionDigits: 2}) : brief.price.toFixed(4))
|
||||
: '-';
|
||||
let signalColor = '#888';
|
||||
if (brief.signal === 'ALTA') signalColor = '#69f0ae';
|
||||
else if (brief.signal === 'BAIXA') signalColor = '#ff6b6b';
|
||||
|
||||
updateAgentUI('brief', {
|
||||
status: 'done',
|
||||
message: `${ASSET_PAIRS[currentAsset]}: ${priceStr}`
|
||||
});
|
||||
|
||||
// Update decio agent card
|
||||
let decisionColor = '#888';
|
||||
if (decio.decision === 'BUY') decisionColor = '#69f0ae';
|
||||
else if (decio.decision === 'SELL') decisionColor = '#ff6b6b';
|
||||
|
||||
updateAgentUI('decio', {
|
||||
status: 'done',
|
||||
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}%`);
|
||||
})
|
||||
.catch(err => {
|
||||
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 ─────────────────────────────────────────────────────────────────────
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
updateClock();
|
||||
@@ -105,6 +207,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
loadPortfolio();
|
||||
loadActivityLog();
|
||||
updateStatus('Sistema operacional', 'online');
|
||||
updatePipelineHeader();
|
||||
// Load asset-specific data
|
||||
if (currentAsset === 'btc') {
|
||||
pollState();
|
||||
@@ -121,11 +224,23 @@ function updateClock() {
|
||||
|
||||
// ── Polling ───────────────────────────────────────────────────────────────────
|
||||
function startPolling() {
|
||||
if (currentAsset === 'btc') {
|
||||
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() {
|
||||
if (currentAsset !== 'btc') return; // Don't poll BTC state when on other assets
|
||||
fetch('/api/state')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
|
||||
Reference in New Issue
Block a user