Internal Controls Dashboard

Control Effectiveness

0%

Failed Controls

0

Open Audit Findings

0

Controls Tested (YTD)

0

Control Status

Effectiveness by Process

Open Audit Findings by Severity

Control Log

Control IDDescriptionProcessLast TestedStatus

Log or Update Control Test

Full Control Catalog

IDDescriptionStatusAction

Error: A required library is missing.

'; return; } // --- DATA MANAGEMENT --- let controls = JSON.parse(localStorage.getItem('icd_controls')) || []; let auditFindings = [ // Static for demo { severity: 'High', count: 3 }, { severity: 'Medium', count: 8 }, { severity: 'Low', count: 5 } ]; const getSampleData = () => { const today = new Date('2025-07-09'); const d = (daysAgo) => new Date(today.getTime() - daysAgo * 24*3600*1000).toISOString().split('T')[0]; return [ { id: 'AC-01', desc: 'User Access Review', process: 'IT General Controls', lastTested: d(15), status: 'Effective' }, { id: 'AC-02', desc: 'Privileged Access Management', process: 'IT General Controls', lastTested: d(20), status: 'Effective' }, { id: 'FR-01', desc: 'Journal Entry Approval', process: 'Financial Reporting', lastTested: d(10), status: 'Ineffective' }, { id: 'FR-02', desc: 'Bank Reconciliation Review', process: 'Financial Reporting', lastTested: d(5), status: 'Effective' }, { id: 'HR-01', desc: 'New Hire Onboarding Checklist', process: 'Human Resources', lastTested: d(30), status: 'Effective' }, { id: 'HR-02', desc: 'Termination Checklist', process: 'Human Resources', lastTested: d(30), status: 'Needs Improvement' }, { id: 'PC-01', desc: 'Procure-to-Pay Authorization', process: 'Procurement', lastTested: d(45), status: 'Effective' }, ]; }; if (controls.length === 0) controls = getSampleData(); const saveState = () => localStorage.setItem('icd_controls', JSON.stringify(controls)); // --- CHART INSTANCES & UTILITIES --- let statusChart, processChart, findingsChart; const tabButtons = document.querySelectorAll('.icd-tab-button'); const tabContents = document.querySelectorAll('.icd-tab-content'); const nextBtn = document.getElementById('icd-next-btn'); const prevBtn = document.getElementById('icd-prev-btn'); // --- RENDER FUNCTIONS --- const renderAll = () => { try { renderKPIs(); renderStatusChart(); renderProcessChart(); renderFindingsChart(); renderControlsTable(); renderManageTable(); updateNavButtons(); } catch(error) { console.error("Dashboard rendering failed:", error); } }; const renderKPIs = () => { const totalControls = controls.length; const effectiveControls = controls.filter(c => c.status === 'Effective').length; const failedControls = controls.filter(c => c.status === 'Ineffective').length; const effectiveness = totalControls > 0 ? (effectiveControls / totalControls) * 100 : 0; const effectivenessEl = document.getElementById('icd-effectiveness-kpi'); effectivenessEl.textContent = `${effectiveness.toFixed(1)}%`; effectivenessEl.className = effectiveness >= 95 ? 'success' : 'danger'; document.getElementById('icd-failed-controls-kpi').textContent = failedControls; document.getElementById('icd-audit-findings-kpi').textContent = auditFindings.reduce((sum, f) => sum + f.count, 0); document.getElementById('icd-controls-tested-kpi').textContent = totalControls; }; const renderStatusChart = () => { const byStatus = controls.reduce((acc, c) => { acc[c.status] = (acc[c.status] || 0) + 1; return acc; }, {}); const order = ['Effective', 'Needs Improvement', 'Ineffective']; const series = order.map(status => byStatus[status] || 0); const options = { chart: { type: 'donut', height: 350 }, series: series, labels: order, colors: ['var(--icd-success-color)', 'var(--icd-warning-color)', 'var(--icd-danger-color)'], legend: { position: 'bottom' } }; if(statusChart) statusChart.destroy(); document.querySelector("#icd-status-chart").innerHTML = ''; statusChart = new ApexCharts(document.querySelector("#icd-status-chart"), options); statusChart.render(); }; const renderProcessChart = () => { const processes = [...new Set(controls.map(c => c.process))]; const processData = processes.map(p => { const processControls = controls.filter(c => c.process === p); const effective = processControls.filter(c => c.status === 'Effective').length; return (effective / processControls.length * 100).toFixed(1); }); const options = { chart: { type: 'bar', height: 350 }, series: [{ name: 'Effectiveness', data: processData }], xaxis: { categories: processes }, yaxis: { max: 100, labels: { formatter: val => `${val}%` } }, plotOptions: { bar: { horizontal: true, distributed: true } }, legend: { show: false }, colors: processData.map(p => p >= 95 ? 'var(--icd-success-color)' : 'var(--icd-warning-color)') }; if(processChart) processChart.destroy(); document.querySelector("#icd-process-chart").innerHTML = ''; processChart = new ApexCharts(document.querySelector("#icd-process-chart"), options); processChart.render(); }; const renderFindingsChart = () => { const options = { chart: { type: 'bar', height: 300 }, series: [{ name: 'Findings', data: auditFindings.map(f=>f.count) }], xaxis: { categories: auditFindings.map(f=>f.severity) }, plotOptions: { bar: { distributed: true } }, colors: ['var(--icd-danger-color)', 'var(--icd-warning-color)', '#7f8c8d'], legend: { show: false } }; if(findingsChart) findingsChart.destroy(); document.querySelector("#icd-findings-chart").innerHTML = ''; findingsChart = new ApexCharts(document.querySelector("#icd-findings-chart"), options); findingsChart.render(); }; const renderControlsTable = () => { const tbody = document.getElementById('icd-controls-tbody'); tbody.innerHTML = ''; controls.forEach(c => { tbody.innerHTML += ` ${c.id} ${c.desc} ${c.process} ${c.lastTested} ${c.status} `; }); }; const renderManageTable = () => { const tbody = document.getElementById('icd-manage-tbody'); tbody.innerHTML = ''; controls.forEach(c => { tbody.innerHTML += `${c.id}${c.desc}${c.status}`; }); const controlIds = controls.map(c => ``); document.getElementById('icd-control-list').innerHTML = controlIds.join(''); const processes = [...new Set(controls.map(c => c.process))]; document.getElementById('icd-process-list').innerHTML = processes.map(p => ``).join(''); }; // --- EVENT HANDLING --- const switchTab = (tabId) => { tabContents.forEach(c => c.style.display = 'none'); tabButtons.forEach(b => b.classList.remove('active')); const activeContent = document.getElementById(tabId); const activeButton = document.querySelector(`.icd-tab-button[data-tab="${tabId}"]`); if (activeContent && activeButton) { activeContent.style.display = 'block'; activeButton.classList.add('active'); } updateNavButtons(); }; const updateNavButtons = () => { const i = [...tabButtons].findIndex(b => b.classList.contains('active')); prevBtn.disabled = i === 0; nextBtn.disabled = i === tabButtons.length - 1; }; tabButtons.forEach(b => b.addEventListener('click', () => switchTab(b.dataset.tab))); nextBtn.addEventListener('click', () => { const i = [...tabButtons].findIndex(b=>b.classList.contains('active')); if (i < tabButtons.length - 1) switchTab(tabButtons[i+1].dataset.tab); }); prevBtn.addEventListener('click', () => { const i = [...tabButtons].findIndex(b=>b.classList.contains('active')); if (i > 0) switchTab(tabButtons[i-1].dataset.tab); }); document.getElementById('icd-control-form').addEventListener('submit', e => { e.preventDefault(); const id = document.getElementById('icd-control-id').value; const newData = { id, desc: document.getElementById('icd-control-desc').value, process: document.getElementById('icd-control-process').value, lastTested: document.getElementById('icd-control-date').value, status: document.getElementById('icd-control-status').value }; const existingIndex = controls.findIndex(c => c.id === id); if (existingIndex > -1) { controls[existingIndex] = newData; } else { controls.push(newData); } saveState(); renderAll(); e.target.reset(); }); document.getElementById('icd-manage-tbody').addEventListener('click', e => { if(e.target.tagName === 'BUTTON') { const id = e.target.dataset.id; if(confirm('Are you sure you want to delete this control?')) { controls = controls.filter(c => c.id !== id); saveState(); renderAll(); } } }); // --- PDF EXPORT --- document.getElementById('icd-download-pdf-btn').addEventListener('click', function() { const btn = this; btn.textContent = 'Generating...'; btn.disabled = true; const content = document.getElementById('icd-pdf-capture-area'); html2canvas(content, { scale: 2 }).then(canvas => { const doc = new jsPDF({ orientation: 'l', unit: 'mm', format: 'a4' }); const imgData = canvas.toDataURL('image/png'); doc.setFontSize(18); doc.text('Internal Controls Status Report', 14, 22); doc.addImage(imgData, 'PNG', 10, 30, 277, 150); doc.addPage(); doc.text('Full Control Log', 14, 22); doc.autoTable({ html: '.icd-controls-table', startY: 30, theme: 'striped', headStyles: { fillColor: [44, 62, 80] } }); doc.save('Internal_Controls_Report.pdf'); }).finally(() => { btn.textContent = 'Download Report'; btn.disabled = false; }); }); // --- INITIALIZATION --- renderAll(); });
Scroll to Top