// Main javascript file document.addEventListener('DOMContentLoaded', function () { const filters = document.querySelectorAll('select[id^="filter_"]'); filters.forEach(filter => { filter.addEventListener('change', applyFilters); }); if (document.getElementById('dateRange')) { const dateRangePicker = $('#dateRange').daterangepicker({ opens: 'left', autoUpdateInput: false, locale: { cancelLabel: 'Clear' } }); dateRangePicker.on('apply.daterangepicker', function(ev, picker) { $(this).val(picker.startDate.format('YYYY-MM-DD') + ' - ' + picker.endDate.format('YYYY-MM-DD')); applyFilters(); }); dateRangePicker.on('cancel.daterangepicker', function(ev, picker) { $(this).val(''); applyFilters(); }); } // Keep track of chart instances const charts = {}; function applyFilters() { const activeFilters = {}; filters.forEach(f => { if (f.value) { activeFilters[f.id.replace('filter_', '')] = f.value; } }); let filteredData = sampleData.filter(row => { for (const col in activeFilters) { if (row[col] != activeFilters[col]) { return false; } } return true; }); const dateRange = $('#dateRange').val(); if (dateRange && charts.timeChart) { const dates = dateRange.split(' - '); const startDate = moment(dates[0], 'YYYY-MM-DD'); const endDate = moment(dates[1], 'YYYY-MM-DD'); const timeCol = Object.keys(charts.timeChart.data.datasets[0]._meta)[0]; filteredData = filteredData.filter(row => { const rowDate = moment(row[timeCol], 'YYYY-MM-DD'); return rowDate.isBetween(startDate, endDate, null, '[]'); }); } updateDashboard(filteredData); } function updateDashboard(data) { updateKpis(data); updateCharts(data); updateTable(data); } function updateKpis(data) { // This is a simplified example. It assumes the first KPI is always the one to be updated. const kpiElements = document.querySelectorAll('.card-text.fs-4'); if (kpiElements.length >= 3) { kpiElements[0].textContent = data.length; const kpiCol = document.querySelector('.card-subtitle.mb-2.text-muted').textContent.replace('Avg. ', '').replace('Total ', ''); const total = data.reduce((sum, row) => sum + parseFloat(row[kpiCol] || 0), 0); const avg = data.length > 0 ? total / data.length : 0; kpiElements[1].textContent = Math.round(avg * 100) / 100; kpiElements[2].textContent = total; } } function updateCharts(data) { if (charts.timeChart) { const timeCol = charts.timeChart.data.datasets[0].label.replace(' over Time', ''); charts.timeChart.data.labels = data.map(row => row[timeCol]); charts.timeChart.data.datasets[0].data = data.map(row => row[timeCol]); charts.timeChart.update(); } if (charts.categoryChart) { const catCol = charts.categoryChart.data.datasets[0].label.replace('Top 10 by ', ''); const metCol = charts.categoryChart.data.datasets[0].label.replace('Top 10 by ', ''); const grouped_data = {}; data.forEach(row => { const category = row[catCol]; if (!grouped_data[category]) { grouped_data[category] = 0; } grouped_data[category] += parseFloat(row[metCol]); }); const sorted_data = Object.entries(grouped_data).sort(([,a],[,b]) => b-a).slice(0, 10); charts.categoryChart.data.labels = sorted_data.map(item => item[0]); charts.categoryChart.data.datasets[0].data = sorted_data.map(item => item[1]); charts.categoryChart.update(); } if (charts.histogramChart) { const metCol = charts.histogramChart.data.datasets[0].label.replace('Histogram of ', ''); charts.histogramChart.data.labels = data.map(row => row[metCol]); charts.histogramChart.data.datasets[0].data = data.map(row => row[metCol]); charts.histogramChart.update(); } } function updateTable(data) { const tableBody = document.querySelector('.table-responsive tbody'); tableBody.innerHTML = ''; data.forEach(row => { const tr = document.createElement('tr'); for (const cell in row) { const td = document.createElement('td'); td.textContent = row[cell]; tr.appendChild(td); } tableBody.appendChild(tr); }); } document.getElementById('exportCsv').addEventListener('click', exportToCsv); function exportToCsv() { const activeFilters = {}; filters.forEach(f => { if (f.value) { activeFilters[f.id.replace('filter_', '')] = f.value; } }); let filteredData = sampleData.filter(row => { for (const col in activeFilters) { if (row[col] != activeFilters[col]) { return false; } } return true; }); const dateRange = $('#dateRange').val(); if (dateRange && charts.timeChart) { const dates = dateRange.split(' - '); const startDate = moment(dates[0], 'YYYY-MM-DD'); const endDate = moment(dates[1], 'YYYY-MM-DD'); const timeCol = Object.keys(charts.timeChart.data.datasets[0]._meta)[0]; filteredData = filteredData.filter(row => { const rowDate = moment(row[timeCol], 'YYYY-MM-DD'); return rowDate.isBetween(startDate, endDate, null, '[]'); }); } if (filteredData.length === 0) { alert("No data to export."); return; } const headers = Object.keys(filteredData[0]); const csvContent = [ headers.join(','), ...filteredData.map(row => headers.map(header => JSON.stringify(row[header])).join(',')) ].join('\n'); const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' }); const link = document.createElement('a'); const url = URL.createObjectURL(blob); link.setAttribute('href', url); link.setAttribute('download', 'filtered_data.csv'); link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } document.querySelectorAll('.export-png').forEach(button => { button.addEventListener('click', function() { const chartId = this.dataset.chart; const canvas = document.getElementById(chartId); html2canvas(canvas.parentElement).then(canvas => { const link = document.createElement('a'); link.download = chartId + '.png'; link.href = canvas.toDataURL(); link.click(); }); }); }); }