ISO Certification Dashboard

Total Certifications
0
Active & In Good Standing
0
Certifications At Risk
0
Open Non-Conformities
0

Certification Status

Open Non-Conformities by Standard

Upcoming Deadlines

ISO StandardEventDateDays Remaining

Enter Certification Data

ISO StandardScope / Business UnitExpiration DateNext Audit Date Major NCsMinor NCsAction

Error: Could not load required libraries.

'; return; } let iso_statusChart, iso_ncChart; const TABS = ['dashboardTab', 'dataInputTab']; let iso_currentTabIndex = 0; const STATUS_CONFIG = { Certified: { color: '#10b981' }, 'At Risk': { color: '#f97316' }, 'Pending Audit': { color: '#3b82f6' }, Expired: { color: '#ef4444' } }; const sampleData = [ { standard: "ISO 9001:2015", scope: "Corporate Quality Management", expDate: "2026-12-31", auditDate: "2025-11-15", major: 0, minor: 1 }, { standard: "ISO 27001:2022", scope: "Information Security (All Depts)", expDate: "2025-09-20", auditDate: "2025-08-01", major: 0, minor: 0 }, { standard: "ISO 14001:2015", scope: "Environmental Management", expDate: "2027-05-10", auditDate: "2026-04-01", major: 1, minor: 3 }, { standard: "ISO 45001:2018", scope: "Occupational Health & Safety", expDate: "2025-08-15", auditDate: "2025-07-20", major: 0, minor: 0 }, { standard: "ISO 22301:2019", scope: "Business Continuity", expDate: "2025-02-01", auditDate: "2024-12-15", major: 2, minor: 5 }, ]; function iso_initialize() { sampleData.forEach(d => iso_add_row(d)); iso_updateDashboard(); iso_updateNavButtons(); } window.iso_add_row = function(data = {}) { const tableBody = document.getElementById('iso-input-table-body'); const row = tableBody.insertRow(); row.innerHTML = ` `; // Apply styling to inputs to match table cells row.querySelectorAll('input').forEach(input => { input.style.width = '100%'; input.style.padding = '8px'; input.style.border = '1px solid #d1d5db'; input.style.borderRadius = '4px'; }); } function iso_collectAndProcessData() { const rows = document.getElementById('iso-input-table-body').rows; const today = new Date("2025-07-10T00:00:00Z"); // Using specified current date const risk_threshold = today.getTime() + 90 * 24 * 60 * 60 * 1000; // 90 days from now return Array.from(rows).map(row => { const expDateStr = row.querySelector('.expDate').value; const expDate = expDateStr ? new Date(expDateStr + "T00:00:00Z") : null; const auditDateStr = row.querySelector('.auditDate').value; const auditDate = auditDateStr ? new Date(auditDateStr + "T00:00:00Z") : null; let status = "Pending Audit"; let daysToExpire = null; if (expDate) { const isExpired = expDate.getTime() < today.getTime(); daysToExpire = Math.ceil((expDate - today) / (1000 * 60 * 60 * 24)); if (isExpired) { status = "Expired"; } else if (expDate.getTime() < risk_threshold) { status = "At Risk"; } else { status = "Certified"; } } return { standard: row.querySelector('.standard').value, scope: row.querySelector('.scope').value, expDate: expDateStr, auditDate: auditDateStr, majorNCs: parseInt(row.querySelector('.major').value) || 0, minorNCs: parseInt(row.querySelector('.minor').value) || 0, status: status, daysToExpire: daysToExpire, daysToAudit: auditDate ? Math.ceil((auditDate - today) / (1000 * 60 * 60 * 24)) : null, }; }); } window.iso_updateDashboard = function() { const data = iso_collectAndProcessData(); iso_updateKPIs(data); iso_updateCharts(data); iso_renderTables(data); iso_changeTab('dashboardTab'); } function iso_updateKPIs(data) { document.getElementById('kpi-total').textContent = data.length; document.getElementById('kpi-active').textContent = data.filter(d => d.status === 'Certified').length; document.getElementById('kpi-at-risk').textContent = data.filter(d => d.status === 'At Risk').length; const totalNCs = data.reduce((sum, d) => sum + d.majorNCs + d.minorNCs, 0); document.getElementById('kpi-open-ncs').textContent = totalNCs; } function iso_updateCharts(data) { // Status Chart if(iso_statusChart) iso_statusChart.destroy(); const statusCounts = data.reduce((acc, d) => { acc[d.status] = (acc[d.status] || 0) + 1; return acc; }, {}); iso_statusChart = new Chart(document.getElementById('iso-status-chart'), { type: 'doughnut', data: { labels: Object.keys(statusCounts), datasets: [{ data: Object.values(statusCounts), backgroundColor: Object.keys(statusCounts).map(k => STATUS_CONFIG[k]?.color || '#ccc') }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'top' } } } }); // NC Chart if(iso_ncChart) iso_ncChart.destroy(); iso_ncChart = new Chart(document.getElementById('iso-nc-chart'), { type: 'bar', data: { labels: data.map(d => d.standard), datasets: [ { label: 'Major NCs', data: data.map(d => d.majorNCs), backgroundColor: '#ef4444' }, { label: 'Minor NCs', data: data.map(d => d.minorNCs), backgroundColor: '#f59e0b' } ] }, options: { responsive: true, maintainAspectRatio: false, scales: { x: { stacked: true }, y: { stacked: true, beginAtZero: true } }, plugins: { legend: { position: 'top' } } } }); } function iso_renderTables(data) { const deadlinesBody = document.getElementById('iso-deadlines-table-body'); deadlinesBody.innerHTML = ''; const deadlines = []; data.forEach(d => { if (d.daysToExpire !== null && d.daysToExpire >= 0) deadlines.push({standard: d.standard, event: 'Expiration', date: d.expDate, days: d.daysToExpire}); if (d.daysToAudit !== null && d.daysToAudit >= 0) deadlines.push({standard: d.standard, event: 'Next Audit', date: d.auditDate, days: d.daysToAudit}); }); deadlines.sort((a, b) => a.days - b.days).slice(0, 5).forEach(d => { const daysClass = d.days < 30 ? 'days-left-due' : d.days < 90 ? 'days-left-soon' : 'days-left-ok'; deadlinesBody.innerHTML += `${d.standard}${d.event}${d.date}${d.days}`; }); } window.iso_downloadPDF = function() { const { jsPDF } = window.jspdf; const doc = new jsPDF('landscape'); const data = iso_collectAndProcessData(); doc.setFontSize(20).text("ISO Certification Status Report", 148, 20, { align: 'center' }); const chartCanvas1 = document.getElementById('iso-status-chart').toDataURL('image/png', 1.0); const chartCanvas2 = document.getElementById('iso-nc-chart').toDataURL('image/png', 1.0); doc.addImage(chartCanvas1, 'PNG', 15, 35, 100, 80); doc.addImage(chartCanvas2, 'PNG', 125, 35, 155, 80); const tableHead = [['ISO Standard', 'Scope/Unit', 'Status', 'Expires On', 'Days Left', 'Major NCs', 'Minor NCs', 'Next Audit']]; const tableBody = data.map(d => [d.standard, d.scope, d.status, d.expDate, d.daysToExpire, d.majorNCs, d.minorNCs, d.auditDate]); doc.autoTable({ head: tableHead, body: tableBody, startY: 120, theme: 'grid', headStyles: { fillColor: '#047857' } }); doc.save('ISO_Certification_Report.pdf'); } // --- TABBING & NAVIGATION --- window.iso_changeTab = function(tabId) { document.querySelectorAll('.iso-tab-content').forEach(c => c.classList.remove('active')); document.querySelectorAll('.iso-tab-button').forEach(b => b.classList.remove('active')); document.getElementById(tabId).classList.add('active'); const activeButton = Array.from(document.querySelectorAll('.iso-tab-button')).find(btn => btn.getAttribute('onclick').includes(tabId)); if (activeButton) activeButton.classList.add('active'); iso_currentTabIndex = TABS.indexOf(tabId); iso_updateNavButtons(); } window.iso_navigateTabs = function(direction) { let newIndex = iso_currentTabIndex; if (direction === 'next') newIndex = Math.min(newIndex + 1, TABS.length - 1); else if (direction === 'prev') newIndex = Math.max(newIndex - 1, 0); iso_changeTab(TABS[newIndex]); } function iso_updateNavButtons() { const prevBtn = document.getElementById('iso-prev-btn'); const nextBtn = document.getElementById('iso-next-btn'); if(prevBtn) prevBtn.disabled = iso_currentTabIndex === 0; if(nextBtn) nextBtn.disabled = iso_currentTabIndex === TABS.length - 1; } iso_initialize(); });
Scroll to Top