document.addEventListener('DOMContentLoaded', function() { // Fetch dashboard data fetchDashboardData(); // Event listeners for filter changes document.getElementById('salesPeriod').addEventListener('change', function() { fetchSalesChartData(this.value); }); }); // Fetch all dashboard data async function fetchDashboardData() { // Fetch summary statistics const statsResponse = await apiRequest('reports/dashboard-stats'); if (statsResponse.status === 'success') { updateDashboardStats(statsResponse.data); } // Fetch sales chart data (default: week) fetchSalesChartData('week'); // Fetch recent sales const salesResponse = await apiRequest('reports/recent-sales'); if (salesResponse.status === 'success') { renderRecentSales(salesResponse.data); } // Fetch low stock items const stockResponse = await apiRequest('inventory/low-stock'); if (stockResponse.status === 'success') { renderLowStockItems(stockResponse.data); } } // Update dashboard statistics function updateDashboardStats(stats) { document.getElementById('todaySales').textContent = formatCurrency(stats.today_sales); document.getElementById('todayOrders').textContent = stats.today_orders; document.getElementById('lowStockItems').textContent = stats.low_stock_count; document.getElementById('totalCustomers').textContent = stats.total_customers; } // Fetch sales chart data based on period async function fetchSalesChartData(period) { const chartResponse = await apiRequest(`reports/sales-chart?period=${period}`); if (chartResponse.status === 'success') { renderSalesChart(chartResponse.data, period); } } // Render sales chart function renderSalesChart(data, period) { const chartContainer = document.getElementById('salesChart'); const canvas = chartContainer.querySelector('canvas'); // If canvas already exists, destroy previous chart if (canvas) { const chartInstance = Chart.getChart(canvas); if (chartInstance) { chartInstance.destroy(); } } // Create new canvas const newCanvas = document.createElement('canvas'); chartContainer.innerHTML = ''; chartContainer.appendChild(newCanvas); // Format labels based on period let labels = data.labels; if (period === 'week') { // Convert to day names labels = data.labels.map(date => { const day = new Date(date).toLocaleDateString('en-US', {weekday: 'short'}); return day; }); } else if (period === 'month') { // Use day of month labels = data.labels.map(date => { return new Date(date).getDate(); }); } else if (period === 'year') { // Use month names labels = data.labels.map(date => { return new Date(date).toLocaleDateString('en-US', {month: 'short'}); }); } // Create chart new Chart(newCanvas, { type: 'line', data: { labels: labels, datasets: [{ label: 'Sales', data: data.sales, backgroundColor: 'rgba(37, 117, 252, 0.1)', borderColor: '#2575fc', borderWidth: 2, tension: 0.3, fill: true }] }, options: { responsive: true, maintainAspectRatio: false, scales: { y: { beginAtZero: true, ticks: { callback: function(value) { return '฿' + value; } } } }, plugins: { tooltip: { callbacks: { label: function(context) { return 'Sales: ' + formatCurrency(context.raw); } } } } } }); } // Render recent sales table function renderRecentSales(sales) { const tableBody = document.querySelector('#recentSalesTable tbody'); tableBody.innerHTML = ''; if (sales.length === 0) { const row = document.createElement('tr'); row.innerHTML = 'No recent sales found'; tableBody.appendChild(row); return; } sales.forEach(sale => { const row = document.createElement('tr'); const date = new Date(sale.created_at).toLocaleDateString(); const time = new Date(sale.created_at).toLocaleTimeString(); row.innerHTML = ` ${sale.reference_no} ${date} ${time} ${sale.customer_name || 'Walk-in Customer'} ${sale.item_count} ${formatCurrency(sale.grand_total)} ${sale.payment_status} `; tableBody.appendChild(row); }); } // Render low stock items table function renderLowStockItems(items) { const tableBody = document.querySelector('#lowStockTable tbody'); tableBody.innerHTML = ''; if (items.length === 0) { const row = document.createElement('tr'); row.innerHTML = 'No low stock items'; tableBody.appendChild(row); return; } items.forEach(item => { const row = document.createElement('tr'); // Determine stock status class let stockClass = 'text-warning'; if (item.quantity <= 0) { stockClass = 'text-danger'; } row.innerHTML = ` ${item.sku} ${item.name} ${item.category_name} ${item.quantity} ${item.low_stock_threshold} `; tableBody.appendChild(row); }); }