/** * Dashboard Page - REAL DATA ONLY * NO MOCK DATA - Uses actual backend APIs */ import { api } from '../../shared/js/core/api-client.js'; import { LayoutManager } from '../../shared/js/core/layout-manager.js'; import { Toast } from '../../shared/js/components/toast.js'; import { formatNumber, formatCurrency, formatPercentage } from '../../shared/js/utils/formatters.js'; class DashboardPage { constructor() { this.marketData = []; this.sentimentChart = null; this.categoriesChart = null; this.lastUpdate = null; } async init() { try { console.log('[Dashboard] Initializing with REAL data only...'); await LayoutManager.injectLayouts(); LayoutManager.setActiveNav('dashboard'); this.bindEvents(); // Load Chart.js await this.loadChartJS(); // Load real data await this.loadAllData(); // Setup auto-refresh (30s) setInterval(() => this.loadAllData(), 30000); Toast.success('Dashboard loaded - Real data'); } catch (error) { console.error('[Dashboard] Init error:', error); Toast.error('Failed to load dashboard'); } } async loadChartJS() { if (window.Chart) return; return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/chart.js@4/dist/chart.umd.min.js'; script.onload = () => { console.log('[Dashboard] Chart.js loaded'); resolve(); }; script.onerror = reject; document.head.appendChild(script); }); } bindEvents() { document.getElementById('refresh-btn')?.addEventListener('click', () => { Toast.info('Refreshing...'); this.loadAllData(); }); } async loadAllData() { try { const startTime = Date.now(); // Load data in parallel const [stats, market, sentiment, resources] = await Promise.all([ this.loadStats(), this.loadMarket(), this.loadSentiment(), this.loadResources() ]); const duration = Date.now() - startTime; console.log(`[Dashboard] Data loaded in ${duration}ms`); // Update UI this.renderStats(stats); this.renderMarket(market); this.renderSentiment(sentiment); this.renderCategories(resources); // Update last update time this.lastUpdate = new Date(); document.getElementById('last-update').textContent = `Updated: ${this.lastUpdate.toLocaleTimeString()}`; } catch (error) { console.error('[Dashboard] Load error:', error); Toast.error('Failed to load data'); } } async loadStats() { try { const [resources, models, providers] = await Promise.all([ api.get('/resources/count'), api.get('/models/summary'), api.get('/providers/summary') ]); return { totalResources: resources.resources?.total || 0, freeResources: resources.resources?.apis || 0, aiModels: models.summary?.loaded_models || 0, activeProviders: providers.summary?.online || 0 }; } catch (error) { console.error('[Dashboard] Stats error:', error); return { totalResources: 0, freeResources: 0, aiModels: 0, activeProviders: 0 }; } } async loadMarket() { try { // Try to get top coins from backend const response = await api.get('/coins/top?limit=10'); return response.coins || response.data || []; } catch (error) { console.error('[Dashboard] Market error:', error); // Try alternative endpoint try { const response = await api.get('/market'); return response.data?.coins || []; } catch (e) { console.error('[Dashboard] Market fallback error:', e); return []; } } } async loadSentiment() { try { const response = await api.get('/sentiment/global'); return response.sentiment || response; } catch (error) { console.error('[Dashboard] Sentiment error:', error); // Try alternative endpoint try { const response = await api.get('/sentiment'); return response; } catch (e) { return { value: 50, label: 'neutral', available: false }; } } } async loadResources() { try { const response = await api.get('/resources'); // Count by category const categories = {}; const resources = response.resources || response.data || []; resources.forEach(r => { const cat = r.category || 'other'; categories[cat] = (categories[cat] || 0) + 1; }); return categories; } catch (error) { console.error('[Dashboard] Resources error:', error); return {}; } } renderStats(stats) { const statsGrid = document.getElementById('stats-grid'); if (!statsGrid) return; statsGrid.innerHTML = `
No market data available
Backend API may not be accessible
| # | Name | Price | 24h Change | Market Cap | Volume |
|---|---|---|---|---|---|
| ${idx + 1} |
${coin.name || coin.symbol}
${coin.symbol || ''}
|
${formatCurrency(coin.price || coin.current_price || 0)} | ${formatPercentage(coin.change_24h || coin.price_change_percentage_24h || 0)} | ${formatCurrency(coin.market_cap || 0)} | ${formatCurrency(coin.volume_24h || coin.total_volume || 0)} |