Subcontractor Compliance Management System

Subcontractor Compliance Management System

Track and manage compliance documents for all your subcontractors in one place.

Compliance Overview

Urgent Action Items (Expired or Missing)

Add New Subcontractor

All Subcontractors

Company Name Overall Status Trade Actions

Full Compliance Report

${expiringCount}

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 = ``; REQUIRED_DOCS.forEach(doc => tableHTML += ``); tableHTML += ''; subcontractors.forEach(sub => { tableHTML += ``; REQUIRED_DOCS.forEach(doc => { const docData = sub.documents[doc.id]; const statusInfo = statusConfig[docData.status]; tableHTML += ``; }); tableHTML += ''; }); tableHTML += '
Subcontractor${doc.name}
${sub.name}${statusInfo.text}
'; 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(); });
Scroll to Top