const API_BASE = '/api/v1'; let chart = null; let currentSeriesData = []; let currentPage = 1; const itemsPerPage = 20; const popularSeries = ['GNPCA', 'GDP', 'UNRATE', 'CPIAUCSL', 'FEDFUNDS', 'M2SL', 'SP500', 'EXUSEU']; function init() { updateTime(); setInterval(updateTime, 1000); loadPopularSeries(); loadCategories(); loadReleases(); initChart(); } function updateTime() { const now = new Date(); document.getElementById('current-time').textContent = now.toLocaleString(); } function initChart() { const ctx = document.getElementById('dataChart').getContext('2d'); chart = new Chart(ctx, { type: 'line', data: { labels: [], datasets: [{ label: 'Value', data: [], borderColor: '#1a73e8', backgroundColor: 'rgba(26, 115, 232, 0.1)', fill: true, tension: 0.3, pointRadius: 3, pointHoverRadius: 6 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: true, position: 'top' }, tooltip: { mode: 'index', intersect: false } }, scales: { x: { ticks: { maxRotation: 45, minRotation: 45 } }, y: { beginAtZero: false } }, interaction: { mode: 'nearest', axis: 'x', intersect: false } } }); } async function searchSeries() { const searchText = document.getElementById('search-input').value.trim(); if (!searchText) { alert('Please enter a search term'); return; } try { const response = await axios.get(`${API_BASE}/series/search`, { params: { search_text: searchText, limit: 20 } }); if (response.data && response.data.seriess && response.data.seriess.length > 0) { displaySearchResults(response.data.seriess); } else { alert('No results found'); } } catch (error) { console.error('Search error:', error); alert('Search failed: ' + (error.response?.data?.error_message || error.message)); } } function displaySearchResults(results) { const select = document.getElementById('series-select'); select.innerHTML = ''; results.forEach(series => { const option = document.createElement('option'); option.value = series.id; option.textContent = `${series.id} - ${series.title}`; select.appendChild(option); }); if (results.length > 0) { select.value = results[0].id; loadSeriesData(); } } async function loadPopularSeries() { const select = document.getElementById('series-select'); select.innerHTML = ''; popularSeries.forEach(seriesId => { const option = document.createElement('option'); option.value = seriesId; option.textContent = seriesId; select.appendChild(option); }); if (popularSeries.length > 0) { select.value = popularSeries[0]; loadSeriesData(); } } async function loadSeriesData() { const seriesId = document.getElementById('series-select').value; if (!seriesId) { document.getElementById('chart-placeholder').style.display = 'block'; document.getElementById('dataChart').style.display = 'none'; return; } try { const [seriesRes, obsRes] = await Promise.all([ axios.get(`${API_BASE}/series`, { params: { series_id: seriesId } }), axios.get(`${API_BASE}/series/observations`, { params: { series_id: seriesId, limit: 1000 } }) ]); const series = seriesRes.data.series; const observations = obsRes.data.observations || []; displaySeriesInfo(series); displayChart(observations, seriesId); currentSeriesData = observations; renderTable(1); updatePagination(); document.getElementById('chart-placeholder').style.display = 'none'; document.getElementById('dataChart').style.display = 'block'; } catch (error) { console.error('Load series error:', error); alert('Failed to load series: ' + (error.response?.data?.error_message || error.message)); } } function displaySeriesInfo(series) { const info = document.getElementById('series-info'); info.innerHTML = `
Series ID: ${series.id}
Title: ${series.title}
Frequency: ${series.frequency}
Units: ${series.units}
Seasonal Adjustment: ${series.seasonal_adjustment}
Last Updated: ${series.last_updated}
Notes: ${series.notes}
` : ''} `; document.getElementById('chart-title').textContent = series.title || series.id; } function displayChart(observations, seriesId) { const labels = observations.map(o => o.date).reverse(); const data = observations.map(o => parseFloat(o.value) || null).reverse(); chart.data.labels = labels; chart.data.datasets[0].data = data; chart.data.datasets[0].label = seriesId; chart.update(); } function renderTable(page) { currentPage = page; const start = (page - 1) * itemsPerPage; const end = start + itemsPerPage; const pageData = currentSeriesData.slice(start, end); const tbody = document.getElementById('data-table-body'); if (pageData.length === 0) { tbody.innerHTML = '