feat: full dashboard update when switching assets (header, agents, banner, sidebar status)
This commit is contained in:
+126
-11
@@ -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() {
|
||||||
pollState();
|
if (currentAsset === 'btc') {
|
||||||
pollInterval = setInterval(pollState, 3000);
|
pollState();
|
||||||
|
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 => {
|
||||||
|
|||||||
Reference in New Issue
Block a user