diff --git a/static/script.js b/static/script.js index dd0ca48..a2739c7 100644 --- a/static/script.js +++ b/static/script.js @@ -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 = ` + + ${ASSET_LABELS[currentAsset]}: ${priceStr} + `; + } + // 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 = ` +
+ ${decio.decision} + ConfianΓ§a: ${decio.confidence}% + ${decio.stop_loss ? `Stop Loss: ${decio.stop_loss}` : ''} + ${decio.take_profit ? `Take Profit: ${decio.take_profit}` : ''} + Signal: ${brief.signal} + RSI: ${brief.rsi || '-'} + ${brief.change_24h !== undefined ? `24h: ${brief.change_24h >= 0 ? '+' : ''}${brief.change_24h}%` : ''} +
+ `; + } + + // 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 = ` + + Sistema online + `; + } + 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() { - pollState(); - pollInterval = setInterval(pollState, 3000); + if (currentAsset === 'btc') { + 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() { + if (currentAsset !== 'btc') return; // Don't poll BTC state when on other assets fetch('/api/state') .then(r => r.json()) .then(data => {