${createKPICard('Time Series Total', currentTotal.toLocaleString(), 'blue', '
')}
${createKPICard('Category Average', currentAvg, 'green', '
')}
${createKPICard('Data Points', (dashboardData.timeSeries.data.length + dashboardData.categoryData.data.length), 'yellow', '
')}
${createKPICard('Last Update', new Date().toLocaleTimeString(), 'indigo', '
')}
Live User Registrations
Sales by Category
`;
}
function createStaticReport() {
const timeSeriesRows = dashboardData.timeSeries.labels.map((label, i) => `
| ${label} | ${dashboardData.timeSeries.data[i].toLocaleString()} |
`).join('');
const categoryRows = dashboardData.categoryData.labels.map((label, i) => `
| ${label} | ${dashboardData.categoryData.data[i].toLocaleString()} |
`).join('');
return `
Time Series Data
| Period | Value |
${timeSeriesRows}
Category Data
| Category | Value |
${categoryRows}
`;
}
// --- HELPER & UTILITY ---
function createKPICard(title, value, color, svgPath) {
return `
`;
}
function addTableRow(tableId) {
const table = document.getElementById(tableId);
const newRow = table.tBodies[0].insertRow();
newRow.innerHTML = `
| | | `;
newRow.querySelector('.delete-row-btn').addEventListener('click', (e) => e.target.closest('tr').remove());
}
function renderAnimatedCharts() {
const commonOptions = {
responsive: true, maintainAspectRatio: false,
plugins: { legend: { display: false } },
scales: {
y: { ticks: { color: '#9ca3af' }, grid: { color: '#4b5563' } },
x: { ticks: { color: '#9ca3af' }, grid: { display: false } }
},
animation: { duration: 800, easing: 'easeInOutQuart' }
};
Object.values(charts).forEach(chart => { if (chart) chart.destroy(); });
const tsCtx = document.getElementById('liveTimeSeriesChart')?.getContext('2d');
if (tsCtx) {
charts.timeSeries = new Chart(tsCtx, { type: 'line', data: { labels: dashboardData.timeSeries.labels, datasets: [{ data: dashboardData.timeSeries.data, backgroundColor: 'rgba(59, 130, 246, 0.2)', borderColor: '#3b82f6', tension: 0.3, fill: true }] }, options: commonOptions });
}
const catCtx = document.getElementById('liveCategoryChart')?.getContext('2d');
if (catCtx) {
charts.category = new Chart(catCtx, { type: 'bar', data: { labels: dashboardData.categoryData.labels, datasets: [{ data: dashboardData.categoryData.data, backgroundColor: ['#3b82f6', '#16a34a', '#f97316', '#c026d3', '#db2777', '#78716c'] }] }, options: commonOptions });
}
}
function simulateLiveUpdate() {
if (!charts.timeSeries || !charts.category) {
console.error("Charts are not initialized. Cannot simulate update.");
return;
}
// Add new time series data
const monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
const lastLabel = charts.timeSeries.data.labels.at(-1);
const lastLabelIndex = monthNames.indexOf(lastLabel);
const nextLabel = monthNames[(lastLabelIndex + 1) % 12];
const newDataPoint = Math.floor(Math.random() * 150) + 100;
charts.timeSeries.data.labels.push(nextLabel);
charts.timeSeries.data.datasets[0].data.push(newDataPoint);
if(charts.timeSeries.data.labels.length > 12) {
charts.timeSeries.data.labels.shift();
charts.timeSeries.data.datasets[0].data.shift();
}
charts.timeSeries.update();
// Update category data randomly
charts.category.data.datasets[0].data.forEach((_, index, arr) => {
arr[index] = Math.floor(Math.random() * 1000) + 50;
});
charts.category.update();
// Update KPIs on the dashboard
const animatedDashboardContent = document.getElementById('animated-dashboard');
if (animatedDashboardContent && !animatedDashboardContent.classList.contains('hidden')) {
const kpiContainer = animatedDashboardContent.querySelector('.grid');
const currentTotal = charts.timeSeries.data.datasets[0].data.reduce((a,b) => a+b, 0);
const currentAvg = (charts.category.data.datasets[0].data.reduce((a,b) => a+b, 0) / charts.category.data.datasets[0].data.length).toFixed(2);
kpiContainer.children[0].querySelector('p').textContent = currentTotal.toLocaleString();
kpiContainer.children[1].querySelector('p').textContent = currentAvg;
kpiContainer.children[3].querySelector('p').textContent = new Date().toLocaleTimeString();
}
}
function navigateTabs(direction) {
const newIndex = currentTabIndex + direction;
if (newIndex >= 0 && newIndex < tabs.length) showTab(newIndex);
}
function updateNavButtons() {
prevTabBtn.disabled = currentTabIndex === 0;
nextTabBtn.disabled = currentTabIndex === tabs.length - 1;
}
function generatePDF() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const activeTab = tabs[currentTabIndex];
doc.setFontSize(18); doc.text('Animated Data Visualization Report', 14, 22);
doc.setFontSize(12); doc.text(activeTab.name, 14, 30);
if (activeTab.id === 'animated-dashboard') {
doc.text("Live User Registrations", 14, 45);
const tsCanvas = document.getElementById('liveTimeSeriesChart');
if (tsCanvas) doc.addImage(tsCanvas.toDataURL('image/png', 1.0), 'PNG', 15, 50, 180, 90);
doc.addPage();
doc.setFontSize(18); doc.text('Animated Data Visualization Report', 14, 22);
doc.setFontSize(12); doc.text(activeTab.name + " (cont.)", 14, 30);
doc.text("Sales by Category", 14, 45);
const catCanvas = document.getElementById('liveCategoryChart');
if (catCanvas) doc.addImage(catCanvas.toDataURL('image/png', 1.0), 'PNG', 15, 50, 180, 90);
} else if (activeTab.id === 'static-report') {
const table1 = document.querySelector('#static-report .data-table');
const table2 = document.querySelectorAll('#static-report .data-table')[1];
if(table1) doc.autoTable({ html: table1, startY: 40, headStyles: { fillColor: [55, 65, 81] } });
if(table2) doc.autoTable({ html: table2, startY: doc.autoTable.previous.finalY + 10, headStyles: { fillColor: [55, 65, 81] } });
}
doc.save(`Data_Viz_Report_${activeTab.name.replace(/\s/g, '_')}.pdf`);
}
init();
});