Non-Compliant
${nonCompliantCount}
`;
urgentContainer.innerHTML = urgentItemsHTML || '
No urgent action items found. Great job!
';
}
function renderSubTable() {
let tableHTML = '';
if (subcontractors.length === 0) {
tableHTML = '
| No subcontractors added yet. |
';
} else {
subcontractors.forEach(sub => {
const overallStatus = getOverallStatus(sub);
const statusInfo = statusConfig[overallStatus];
tableHTML += `
| ${sub.name} |
${statusInfo.text} |
${sub.trade} |
|
`;
});
}
subTableBody.innerHTML = tableHTML;
}
function renderReport() {
const reportContainer = document.getElementById('report-output');
let tableHTML = `
| Subcontractor | `;
REQUIRED_DOCS.forEach(doc => tableHTML += `${doc.name} | `);
tableHTML += '
';
subcontractors.forEach(sub => {
tableHTML += `| ${sub.name} | `;
REQUIRED_DOCS.forEach(doc => {
const docData = sub.documents[doc.id];
const statusInfo = statusConfig[docData.status];
tableHTML += `${statusInfo.text} | `;
});
tableHTML += '
';
});
tableHTML += '
';
reportContainer.innerHTML = tableHTML;
}
function openComplianceModal(subId) {
const sub = subcontractors.find(s => s.id === subId);
if (!sub) return;
modalSubId.value = subId;
modalTitle.textContent = `Manage Compliance: ${sub.name}`;
let docHTML = '';
REQUIRED_DOCS.forEach(doc => {
const docData = sub.documents[doc.id];
docHTML += `
`;
});
modalDocList.innerHTML = docHTML;
modal.style.display = 'flex';
}
function closeModal() {
modal.style.display = 'none';
}
function addSub(e) {
e.preventDefault();
const name = document.getElementById('subName').value;
const contact = document.getElementById('subContact').value;
const trade = document.getElementById('subTrade').value;
const newId = subcontractors.length > 0 ? Math.max(...subcontractors.map(s => s.id)) + 1 : 1;
const newSub = { id: newId, name, contact, trade, documents: {} };
REQUIRED_DOCS.forEach(doc => {
newSub.documents[doc.id] = { status: 'missing', expiry: null };
});
subcontractors.push(newSub);
addSubForm.reset();
renderAll();
}
function handleComplianceSave(e) {
e.preventDefault();
const subId = parseInt(modalSubId.value);
const sub = subcontractors.find(s => s.id === subId);
if (!sub) return;
const formData = new FormData(complianceForm);
REQUIRED_DOCS.forEach(doc => {
sub.documents[doc.id].status = formData.get(`${doc.id}_status`);
sub.documents[doc.id].expiry = formData.get(`${doc.id}_expiry`) || null;
});
closeModal();
renderAll();
}
function deleteSub(subId) {
if (confirm('Are you sure you want to delete this subcontractor?')) {
subcontractors = subcontractors.filter(s => s.id !== subId);
renderAll();
}
}
function downloadPdf() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF({ orientation: 'landscape' });
doc.setFontSize(18);
doc.text("Subcontractor Compliance Report", 14, 22);
doc.setFontSize(11);
doc.setTextColor(100);
doc.text(`Report Generated: ${new Date().toLocaleDateString('en-US')}`, 14, 30);
doc.autoTable({
html: '#report-table',
startY: 40,
theme: 'grid',
headStyles: { fillColor: [241, 245, 249], textColor: [51, 65, 85] },
styles: { cellPadding: 2, fontSize: 8 },
didParseCell: function(data) {
// Remove span tags to get clean text for PDF
const cell = data.cell.raw;
if(cell.querySelector('.badge')) {
data.cell.text = [cell.querySelector('.badge').textContent];
// Custom styling for PDF cells based on status
if (cell.innerHTML.includes('badge-compliant')) data.cell.styles.textColor = [22, 101, 52];
if (cell.innerHTML.includes('badge-expiring_soon')) data.cell.styles.textColor = [133, 77, 14];
if (cell.innerHTML.includes('badge-expired') || cell.innerHTML.includes('badge-missing')) data.cell.styles.textColor = [153, 27, 27];
}
}
});
doc.save('Subcontractor_Compliance_Report.pdf');
}
// --- EVENT LISTENERS ---
tabs.forEach((tab) => tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('active'));
tabContents.forEach(c => c.classList.remove('active'));
tab.classList.add('active');
document.getElementById(tab.dataset.tab).classList.add('active');
}));
addSubForm.addEventListener('submit', addSub);
complianceForm.addEventListener('submit', handleComplianceSave);
document.getElementById('close-modal-btn').addEventListener('click', closeModal);
document.getElementById('cancel-modal-btn').addEventListener('click', closeModal);
document.getElementById('downloadPdfBtn').addEventListener('click', downloadPdf);
// --- GLOBAL ACCESS & INITIALIZATION ---
// Expose functions to be called from inline HTML onclick
window.app = { openComplianceModal, deleteSub };
renderAll();
});