`;
});
}
};
const renderChecklist = () => {
const container = document.getElementById('checklist-container');
if (!container) return;
const groupedByCategory = auditItems.reduce((acc, item) => {
(acc[item.category] = acc[item.category] || []).push(item);
return acc;
}, {});
container.innerHTML = '';
for (const category in groupedByCategory) {
const itemsHtml = groupedByCategory[category].map(item => `
`).join('');
container.innerHTML += `
`;
}
};
const renderAuditSetup = () => {
document.getElementById('company-name').value = auditDetails.companyName;
document.getElementById('facility-location').value = auditDetails.facilityLocation;
document.getElementById('auditor-name').value = auditDetails.auditorName;
document.getElementById('audit-date').value = auditDetails.auditDate;
};
const renderAll = () => {
renderDashboard();
renderChecklist();
renderAuditSetup();
};
// --- EVENT HANDLERS & LOGIC ---
window.updateAuditDetails = (field, value) => {
auditDetails[field] = value;
};
window.updateAuditItem = (id, field, value) => {
const item = auditItems.find(i => i.id === id);
if (item) {
item[field] = value;
const detailsDiv = document.getElementById(`details-${id}`);
if (detailsDiv) {
detailsDiv.classList.toggle('hidden', value !== 'Non-Compliant');
}
renderDashboard(); // Update dashboard in real time
}
};
// --- TAB NAVIGATION ---
window.changeTab = (tabIndex) => {
renderAll(); // Re-render to ensure data is fresh when switching tabs
currentTab = tabIndex;
const tabs = document.querySelectorAll('.tab');
const tabContents = document.querySelectorAll('.tab-content');
tabs.forEach((tab, index) => {
tab.classList.toggle('tab-active', index === tabIndex);
tab.classList.toggle('tab-inactive', index !== tabIndex);
});
tabContents.forEach((content, index) => {
content.style.display = index === tabIndex ? 'block' : 'none';
});
};
window.navigateTab = (direction) => {
const numTabs = document.querySelectorAll('.tab').length;
let newTab = currentTab + direction;
if (newTab < 0) newTab = 0;
if (newTab >= numTabs) newTab = numTabs - 1;
changeTab(newTab);
};
// --- PDF DOWNLOAD FUNCTIONALITY ---
window.downloadPDF = () => {
const { jsPDF } = window.jspdf;
const doc = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' });
// Header
doc.setFontSize(20);
doc.setFont(undefined, 'bold');
doc.text('Environmental Compliance Audit Report', 105, 22, { align: 'center' });
doc.setFontSize(11);
doc.setFont(undefined, 'normal');
doc.setTextColor(100);
// Audit Details Table
const detailsBody = [
['Company:', auditDetails.companyName, 'Auditor:', auditDetails.auditorName],
['Facility:', auditDetails.facilityLocation, 'Audit Date:', new Date(auditDetails.auditDate).toLocaleDateString('en-US')]
];
doc.autoTable({
startY: 30,
body: detailsBody,
theme: 'plain',
styles: { fontSize: 10, cellPadding: 1.5 },
columnStyles: {
0: { fontStyle: 'bold' },
2: { fontStyle: 'bold' }
}
});
// Summary Section
const totalApplicable = auditItems.filter(item => item.status !== 'N/A').length;
const compliantCount = auditItems.filter(item => item.status === 'Compliant').length;
const nonCompliantCount = auditItems.filter(item => item.status === 'Non-Compliant').length;
const complianceScore = totalApplicable > 0 ? Math.round((compliantCount / totalApplicable) * 100) : 0;
doc.setFontSize(14);
doc.setFont(undefined, 'bold');
doc.text('Audit Summary', 14, doc.autoTable.previous.finalY + 15);
const summaryBody = [
['Overall Compliance Score', `${complianceScore}%`],
['Total Items Audited', totalApplicable],
['Compliant Items', compliantCount],
['Non-Compliant Items', nonCompliantCount]
];
doc.autoTable({
startY: doc.autoTable.previous.finalY + 18,
head: [['Metric', 'Result']],
body: summaryBody,
theme: 'striped',
headStyles: { fillColor: [21, 128, 61] }
});
// Non-Compliance Findings
const nonCompliantItems = auditItems.filter(item => item.status === 'Non-Compliant');
if (nonCompliantItems.length > 0) {
doc.setFontSize(14);
doc.setFont(undefined, 'bold');
doc.text('Non-Compliance Findings & Corrective Actions', 14, doc.autoTable.previous.finalY + 15);
const findingsBody = nonCompliantItems.map(item => [
item.category,
item.question,
item.notes || 'N/A',
item.correctiveAction || 'To be determined'
]);
doc.autoTable({
startY: doc.autoTable.previous.finalY + 18,
head: [['Category', 'Finding', 'Notes', 'Corrective Action']],
body: findingsBody,
theme: 'grid',
headStyles: { fillColor: [185, 28, 28] } // Red color for non-compliance
});
}
doc.save('Environmental_Audit_Report.pdf');
};
// --- INITIAL RENDER ---
renderAll();
});
${item.question}
${category}
${itemsHtml}
