C-Suite Performance Dashboard

C-Suite Performance Dashboard

Key Performance Indicators (KPIs) Overview

Loading dashboard data...

No KPI data available. Go to "Data Configuration" to add KPIs.

'; return; } // Start building the HTML for the dashboard table let tableHtml = ` `; // Iterate through each KPI to create a table row kpis.forEach(kpi => { let performanceRatio = 'N/A'; let status = 'N/A'; let statusClass = ''; if (!isNaN(kpi.actualValue) && !isNaN(kpi.targetValue) && kpi.targetValue !== 0) { performanceRatio = (kpi.actualValue / kpi.targetValue); if (kpi.name.includes('Cost') || kpi.name.includes('Expense')) { // For cost-related KPIs, lower is better if (performanceRatio <= 1) { status = 'On Track'; statusClass = 'status-on-track'; } else if (performanceRatio <= 1.1) { // 10% above target status = 'Below Target'; statusClass = 'status-below-target'; } else { status = 'Critical'; statusClass = 'status-critical'; } } else { // For other KPIs, higher is better if (performanceRatio >= 1) { status = 'On Track'; statusClass = 'status-on-track'; } else if (performanceRatio >= 0.9) { // Within 10% of target status = 'Below Target'; statusClass = 'status-below-target'; } else { status = 'Critical'; statusClass = 'status-critical'; } } performanceRatio = `${(performanceRatio * 100).toFixed(2)}%`; } tableHtml += ` `; }); tableHtml += `
KPI Name Category Actual Value Target Value Performance Status
${kpi.name} ${kpi.category} ${formatValue(kpi.actualValue, kpi.unit, kpi.isCurrency)} ${formatValue(kpi.targetValue, kpi.unit, kpi.isCurrency)} ${performanceRatio} ${status}
`; dashboardOutput.innerHTML = tableHtml; // Insert the generated table HTML into the dashboard output div } // --- Event Listeners --- // Tab button click listeners dashboardTabBtn.addEventListener('click', () => switchTab('dashboard')); dataConfigTabBtn.addEventListener('click', () => { switchTab('dataConfig'); loadKpiInputs(); // Load current KPI data into input fields when switching to config tab }); // Add KPI button listener addKpiBtn.addEventListener('click', () => addKpiInput()); // Save & Update Dashboard button listener updateDashboardBtn.addEventListener('click', () => { updateKpiData(); // Read inputs and update the kpis array renderDashboard(); // Re-render the dashboard with updated data switchTab('dashboard'); // Switch back to the dashboard tab to show results }); // Previous Tab button listener prevTabBtn.addEventListener('click', () => { if (activeTab === 'dataConfig') { switchTab('dashboard'); } }); // Next Tab button listener nextTabBtn.addEventListener('click', () => { if (activeTab === 'dashboard') { switchTab('dataConfig'); loadKpiInputs(); // Load inputs when moving to data config } }); // PDF Download Button Listener downloadPdfBtn.addEventListener('click', function() { // List of elements to hide before capturing the dashboard for PDF // These are UI elements not relevant to the dashboard content itself in the PDF const elementsToHide = [ cSuiteDashboardContainer.querySelector('h1'), // Main tool title cSuiteDashboardContainer.querySelector('.flex.justify-center.mb-6'), // Tab navigation buttons cSuiteDashboardContainer.querySelector('.flex.justify-center.mt-6').children[0], // The PDF download button itself cSuiteDashboardContainer.querySelector('.flex.justify-center.space-x-4.mt-6') // Previous/Next navigation buttons ]; // Temporarily hide these elements elementsToHide.forEach(el => el && el.classList.add('hidden')); // Temporarily make the dashboard content visible if it's currently hidden const wasHidden = dashboardTabContent.classList.contains('hidden'); if (wasHidden) { dashboardTabContent.classList.remove('hidden'); } // Use html2canvas to capture the dashboard output section as an image html2canvas(dashboardOutput, { scale: 2, // Increase scale for higher resolution in the PDF useCORS: true, // Important if any external images were used (not applicable here, but good practice) scrollX: -window.scrollX, // Adjust for horizontal scroll position scrollY: -window.scrollY, // Adjust for vertical scroll position windowWidth: document.documentElement.offsetWidth, // Capture full window width windowHeight: document.documentElement.offsetHeight // Capture full window height }).then(canvas => { const { jsPDF } = window.jspdf; // Get jsPDF object from window scope const imgData = canvas.toDataURL('image/png'); // Convert canvas to PNG image data URL const pdf = new jsPDF('l', 'mm', 'a4'); // Create new PDF document (landscape, mm units, A4 size) const imgWidth = 297; // A4 landscape width in mm const pageHeight = 210; // A4 landscape height in mm const imgHeight = canvas.height * imgWidth / canvas.width; // Calculate image height to maintain aspect ratio let heightLeft = imgHeight; // Remaining height to be added to PDF // Add the first page of the image to the PDF pdf.addImage(imgData, 'PNG', 0, 0, imgWidth, imgHeight); heightLeft -= pageHeight; // If content spans multiple pages, add new pages while (heightLeft >= 0) { pdf.addPage(); // Add a new page // Position the image correctly for multi-page content pdf.addImage(imgData, 'PNG', 0, heightLeft - imgHeight, imgWidth, imgHeight); heightLeft -= pageHeight; } pdf.save('c-suite-performance-dashboard.pdf'); // Save the PDF file }).catch(error => { console.error("Error generating PDF:", error); // Log any errors during PDF generation }).finally(() => { // Always restore hidden elements and tab visibility, even if PDF generation fails elementsToHide.forEach(el => el && el.classList.remove('hidden')); if (wasHidden) { dashboardTabContent.classList.add('hidden'); } }); }); // --- Initial Setup on Load --- // Update KPI data from inputs (if any, though initially from sample) updateKpiData(); // Render the dashboard with the initial data renderDashboard(); // Load the sample KPI data into the configuration inputs loadKpiInputs(); // Set the initial active tab to 'Dashboard' switchTab('dashboard'); });
Scroll to Top