Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', function() { | |
| // DOM Elements | |
| const tickerInput = document.getElementById('tickerInput'); | |
| const searchBtn = document.getElementById('searchBtn'); | |
| const stockTitle = document.getElementById('stockTitle'); | |
| const currentPriceEl = document.getElementById('currentPrice'); | |
| const dailyChangeEl = document.getElementById('dailyChange'); | |
| const marketCapEl = document.getElementById('marketCap'); | |
| const loadingIndicator = document.getElementById('loadingIndicator'); | |
| const timeButtons = document.querySelectorAll('.time-btn'); | |
| // Chart setup | |
| const ctx = document.getElementById('stockChart').getContext('2d'); | |
| let stockChart = new Chart(ctx, { | |
| type: 'line', | |
| data: { | |
| labels: [], | |
| datasets: [{ | |
| label: 'Price', | |
| data: [], | |
| borderColor: '#6366F1', | |
| backgroundColor: 'rgba(99, 102, 241, 0.1)', | |
| borderWidth: 2, | |
| tension: 0.1, | |
| fill: true | |
| }] | |
| }, | |
| options: { | |
| responsive: true, | |
| maintainAspectRatio: false, | |
| plugins: { | |
| legend: { | |
| display: false | |
| } | |
| }, | |
| scales: { | |
| y: { | |
| beginAtZero: false, | |
| grid: { | |
| color: 'rgba(0, 0, 0, 0.05)' | |
| } | |
| }, | |
| x: { | |
| grid: { | |
| display: false | |
| } | |
| } | |
| } | |
| } | |
| }); | |
| // Event Listeners | |
| searchBtn.addEventListener('click', fetchStockData); | |
| tickerInput.addEventListener('keypress', function(e) { | |
| if (e.key === 'Enter') fetchStockData(); | |
| }); | |
| // Time frame buttons | |
| timeButtons.forEach(btn => { | |
| btn.addEventListener('click', function() { | |
| timeButtons.forEach(b => b.classList.remove('bg-primary', 'text-white')); | |
| this.classList.add('bg-primary', 'text-white'); | |
| fetchStockData(this.dataset.time); | |
| }); | |
| }); | |
| // Default to 1 month view | |
| timeButtons[2].click(); | |
| // Fetch stock data | |
| async function fetchStockData(timeFrame = '1m') { | |
| const ticker = tickerInput.value.trim().toUpperCase(); | |
| if (!ticker) { | |
| alert('Please enter a stock symbol'); | |
| return; | |
| } | |
| loadingIndicator.classList.remove('hidden'); | |
| try { | |
| const response = await fetch(`http://localhost:5000/api/stock?ticker=${ticker}&time_frame=${timeFrame}`); | |
| const data = await response.json(); | |
| if (data.error) { | |
| throw new Error(data.error); | |
| } | |
| // Process data | |
| const dates = data.history.dates; | |
| const prices = data.history.prices; | |
| // Update chart | |
| stockChart.data.labels = dates; | |
| stockChart.data.datasets[0].data = prices; | |
| stockChart.update(); | |
| // Update stock info | |
| const lastPrice = data.current_price; | |
| const change = data.change_percent; | |
| const marketCap = data.market_cap; | |
| const currency = data.currency; | |
| stockTitle.textContent = `${ticker} Stock`; | |
| currentPriceEl.textContent = `${currency}${lastPrice.toFixed(2)}`; | |
| dailyChangeEl.textContent = `${change.toFixed(2)}%`; | |
| if (change >= 0) { | |
| dailyChangeEl.classList.add('price-up'); | |
| dailyChangeEl.classList.remove('price-down'); | |
| } else { | |
| dailyChangeEl.classList.add('price-down'); | |
| dailyChangeEl.classList.remove('price-up'); | |
| } | |
| // Format market cap | |
| let marketCapStr; | |
| if (marketCap >= 1e12) { | |
| marketCapStr = `${(marketCap / 1e12).toFixed(2)}T`; | |
| } else if (marketCap >= 1e9) { | |
| marketCapStr = `${(marketCap / 1e9).toFixed(2)}B`; | |
| } else if (marketCap >= 1e6) { | |
| marketCapStr = `${(marketCap / 1e6).toFixed(2)}M`; | |
| } else { | |
| marketCapStr = `${marketCap.toFixed(2)}`; | |
| } | |
| marketCapEl.textContent = `${currency}${marketCapStr}`; | |
| } catch (error) { | |
| console.error('Error fetching stock data:', error); | |
| alert('Error fetching stock data. Please try again.'); | |
| } finally { | |
| loadingIndicator.classList.add('hidden'); | |
| } | |
| } | |
| }); |