"Untitled"
Bootstrap 4.1.1 Snippet by pradeep330

<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css"> <script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <!------ Include the above in your HEAD tag ---------->
.programs4-stat-card { border: 1px solid #e8e8e8; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); } [data-bs-theme="dark"] .programs4-stat-card { border-color: var(--bs-border-color); box-shadow: none; } .programs4-stat-icon { width: 3.25rem; height: 3.25rem; background-color: #e6f4f1; border-radius: 0.65rem; } [data-bs-theme="dark"] .programs4-stat-icon { background-color: rgba(230, 244, 241, 0.18); } .programs4-cycle-wrap { position: relative; width: 100%; max-width: 220px; height: 220px; margin-left: auto; margin-right: auto; } .comparison-chart-wrap { position: relative; height: 280px; }
<script> const themeToggle = document.getElementById('themeToggle'); const themeIcon = document.getElementById('themeIcon'); const htmlElement = document.documentElement; const savedTheme = localStorage.getItem('theme') || 'light'; if (savedTheme === 'dark') { htmlElement.setAttribute('data-bs-theme', 'dark'); themeIcon.classList.remove('bi-moon-fill'); themeIcon.classList.add('bi-sun-fill'); } else { themeIcon.classList.remove('bi-sun-fill'); themeIcon.classList.add('bi-moon-fill'); } themeToggle.addEventListener('click', () => { const currentTheme = htmlElement.getAttribute('data-bs-theme'); if (currentTheme === 'dark') { htmlElement.removeAttribute('data-bs-theme'); themeIcon.classList.remove('bi-sun-fill'); themeIcon.classList.add('bi-moon-fill'); localStorage.setItem('theme', 'light'); } else { htmlElement.setAttribute('data-bs-theme', 'dark'); themeIcon.classList.remove('bi-moon-fill'); themeIcon.classList.add('bi-sun-fill'); localStorage.setItem('theme', 'dark'); } }); const body = document.body; const sidebarToggle = document.getElementById('sidebarToggle'); const sidebarBackdrop = document.getElementById('sidebarBackdrop'); const savedSidebar = localStorage.getItem('sidebar') || 'expanded'; if (savedSidebar === 'collapsed') body.classList.add('sidebar-collapsed'); sidebarToggle.addEventListener('click', () => { const isMobile = window.matchMedia('(max-width: 992px)').matches; if (isMobile) { body.classList.toggle('sidebar-open'); if (body.classList.contains('sidebar-open')) body.classList.remove('sidebar-collapsed'); else if (savedSidebar === 'collapsed') body.classList.add('sidebar-collapsed'); } else { body.classList.toggle('sidebar-collapsed'); localStorage.setItem('sidebar', body.classList.contains('sidebar-collapsed') ? 'collapsed' : 'expanded'); } }); sidebarBackdrop.addEventListener('click', () => { body.classList.remove('sidebar-open'); if (savedSidebar === 'collapsed') body.classList.add('sidebar-collapsed'); }); document.getElementById('userMenuLogout').addEventListener('click', () => { window.location.href = 'index.html'; }); const chartCss = getComputedStyle(document.documentElement); Chart.defaults.color = chartCss.getPropertyValue('--text-color-muted').trim() || '#6c757d'; Chart.defaults.font.family = "'Lato', -apple-system, BlinkMacSystemFont, sans-serif"; const cycleNotStarted = 14; const cycleInProgress = 32; const cycleCompleted = 54; const annualReportsCompleted = 7; const annualReportsPending = 12; const annualReturnsTotal = 24; const cycleColors = { notStarted: '#94a3b8', inProgress: '#f59e0b', completed: '#22c55e' }; document.getElementById('cycleNotStartedCount').textContent = cycleNotStarted; document.getElementById('cycleInProgressCount').textContent = cycleInProgress; document.getElementById('cycleCompletedCount').textContent = cycleCompleted; document.getElementById('annualReportsCompletedCount').textContent = annualReportsCompleted; document.getElementById('annualReportsPendingCount').textContent = annualReportsPending; document.getElementById('annualReturnsTotalCount').textContent = annualReturnsTotal; const cycleCanvas = document.getElementById('cycleStatusDonut'); if (cycleCanvas) { new Chart(cycleCanvas.getContext('2d'), { type: 'doughnut', data: { labels: ['Not started', 'In progress', 'Completed'], datasets: [{ data: [cycleNotStarted, cycleInProgress, cycleCompleted], backgroundColor: [cycleColors.notStarted, cycleColors.inProgress, cycleColors.completed], borderWidth: 2, borderColor: document.documentElement.getAttribute('data-bs-theme') === 'dark' ? '#212529' : '#fff' }] }, options: { responsive: true, maintainAspectRatio: false, cutout: '62%', plugins: { legend: { display: false }, tooltip: { callbacks: { label(ctx) { const total = ctx.dataset.data.reduce((a, b) => a + b, 0); const v = ctx.raw; const pct = total ? ((v / total) * 100).toFixed(1) : 0; return ' ' + ctx.label + ': ' + v + ' (' + pct + '%)'; } } } } } }); } const comparisonReportConfigs = [{ id: 'compQ1', title: 'Completion rate by reporting year (%)', datasetLabel: 'Rate', labels: ['2023', '2024', '2025', '2026'], data: [56, 50, 45, 40], color: '#667eea' }, { id: 'compQ2', title: 'Average days to submit by reporting year', datasetLabel: 'Days', labels: ['2023', '2024', '2025', '2026'], data: [62, 58, 51, 47], color: '#f59e0b' }, { id: 'compQ3', title: 'Standards met (count) by reporting year', datasetLabel: 'Count', labels: ['2023', '2024', '2025', '2026'], data: [88, 92, 95, 97], color: '#22c55e' } ]; let comparisonBarCharts = []; function destroyComparisonBarCharts() { comparisonBarCharts.forEach(function (ch) { ch.destroy(); }); comparisonBarCharts = []; } function colClassForChartCount(n) { if (n <= 1) return 'col-12'; if (n === 2) return 'col-12 col-md-6'; return 'col-12 col-md-4'; } function renderComparisonReportCharts() { const root = document.getElementById('comparisonChartsRoot'); const emptyEl = document.getElementById('comparisonChartsEmpty'); const selected = comparisonReportConfigs.filter(function (cfg) { const el = document.getElementById(cfg.id); return el && el.checked; }); destroyComparisonBarCharts(); root.innerHTML = ''; if (selected.length === 0) { emptyEl.classList.remove('d-none'); root.classList.add('d-none'); return; } emptyEl.classList.add('d-none'); root.classList.remove('d-none'); const colCls = colClassForChartCount(selected.length); selected.forEach(function (cfg, i) { const col = document.createElement('div'); col.className = colCls; const wrap = document.createElement('div'); wrap.className = 'comparison-chart-wrap border rounded-3 p-3 bg-body-secondary bg-opacity-10'; const title = document.createElement('h6'); title.className = 'small text-muted mb-2 fw-semibold'; title.textContent = cfg.title; const canvas = document.createElement('canvas'); canvas.setAttribute('role', 'img'); canvas.setAttribute('aria-label', cfg.title); wrap.appendChild(title); wrap.appendChild(canvas); col.appendChild(wrap); root.appendChild(col); const ctx = canvas.getContext('2d'); const gridColor = document.documentElement.getAttribute('data-bs-theme') === 'dark' ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.06)'; const ch = new Chart(ctx, { type: 'bar', plugins: [{ id: 'comparisonBarValueLabels', afterDatasetsDraw: function (chart) { const meta = chart.getDatasetMeta(0); if (!meta || !meta.data || !meta.data.length) return; const values = chart.data.datasets[0].data; const c = chart.ctx; const isDark = document.documentElement.getAttribute('data-bs-theme') === 'dark'; c.save(); c.font = '600 13px ' + (Chart.defaults.font.family || 'sans-serif'); c.fillStyle = isDark ? '#f1f5f9' : '#1e293b'; c.textAlign = 'center'; c.textBaseline = 'bottom'; meta.data.forEach(function (bar, index) { const val = values[index]; if (val === undefined || val === null) return; const x = bar.x; const y = bar.y; const top = Math.min(y, bar.base); c.fillText(String(val), x, top - 6); }); c.restore(); } }], data: { labels: cfg.labels, datasets: [{ label: cfg.datasetLabel, data: cfg.data, backgroundColor: cfg.color, borderRadius: 6, maxBarThickness: 48 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { callbacks: { title: function (items) { return items.length ? 'Year ' + items[0].label : ''; } } } }, scales: { y: { beginAtZero: true, grid: { color: gridColor }, ticks: { precision: 0 } }, x: { grid: { display: false } } } } }); comparisonBarCharts.push(ch); }); } document.getElementById('comparisonReportGenerateChartsBtn').addEventListener('click', renderComparisonReportCharts); </script>

Questions / Comments: