`).join('');
};
const renderSupplierConfig = () => {
supplierTableBody.innerHTML = state.suppliers.map(s => `
| ${s.name} |
${s.category} |
$${s.cost.toFixed(2)} |
${s.rating}/5 |
|
`).join('');
};
// --- INITIALIZATION & EVENT HANDLERS ---
function initialize() {
loadInitialData();
const populateSelect = (el, options) => { el.innerHTML = options.map(o => `
`).join(''); };
populateSelect(reqCategory, state.categories);
populateSelect(supplierCategory, state.categories);
matchingForm.addEventListener('submit', (e) => {
e.preventDefault();
state.requirements = {
category: reqCategory.value,
cost: parseFloat(reqCost.value) || 0,
keywords: reqKeywords.value
};
runMatching(); renderResults();
});
supplierForm.addEventListener('submit', handleSupplierSubmit);
cancelEditBtn.addEventListener('click', resetSupplierForm);
supplierTableBody.addEventListener('click', handleTableClick);
downloadPdfBtn.addEventListener('click', generatePdf);
render();
}
function handleSupplierSubmit(e) {
e.preventDefault();
const supplier = {
id: state.editingSupplierId || Date.now(),
name: supplierName.value, category: supplierCategory.value,
cost: parseFloat(supplierCost.value), rating: parseFloat(supplierRating.value),
keywords: supplierKeywords.value
};
if(state.editingSupplierId) { state.suppliers = state.suppliers.map(s => s.id === supplier.id ? supplier : s); }
else { state.suppliers.push(supplier); }
resetSupplierForm(); render();
}
function handleTableClick(e) {
const row = e.target.closest('tr');
if (!row) return;
const id = parseInt(row.dataset.id);
if (e.target.classList.contains('edit-btn')) {
const s = state.suppliers.find(s => s.id === id);
if(!s) return;
state.editingSupplierId = id;
supplierId.value = s.id; supplierName.value = s.name; supplierCategory.value = s.category;
supplierCost.value = s.cost; supplierRating.value = s.rating; supplierKeywords.value = s.keywords;
supplierFormTitle.textContent = "Edit Supplier"; submitSupplierBtn.textContent = "Update Supplier";
cancelEditBtn.classList.remove('hidden');
} else if (e.target.classList.contains('delete-btn')) {
state.suppliers = state.suppliers.filter(s => s.id !== id); render();
}
}
function resetSupplierForm() {
supplierForm.reset(); state.editingSupplierId = null;
supplierFormTitle.textContent = "Add New Supplier";
submitSupplierBtn.textContent = "Add Supplier";
cancelEditBtn.classList.add('hidden');
}
// --- TAB NAVIGATION ---
const switchTab = (tabName) => { state.currentTab = tabName; Object.values(tabButtons).forEach(b => b.classList.remove('active')); Object.values(tabContents).forEach(c => c.classList.add('hidden')); if(tabButtons[tabName]) tabButtons[tabName].classList.add('active'); if(tabContents[tabName]) tabContents[tabName].classList.remove('hidden'); updateNavButtons(); };
const updateNavButtons = () => { prevBtn.disabled = state.currentTab === 'dashboard'; prevBtn.classList.toggle('opacity-50', prevBtn.disabled); nextBtn.disabled = state.currentTab === 'config'; nextBtn.classList.toggle('opacity-50', nextBtn.disabled); };
Object.keys(tabButtons).forEach(k => tabButtons[k]?.addEventListener('click', () => switchTab(k)));
nextBtn.addEventListener('click', () => { if (state.currentTab === 'dashboard') switchTab('config'); });
prevBtn.addEventListener('click', () => { if (state.currentTab === 'config') switchTab('dashboard'); });
// --- PDF GENERATION ---
async function generatePdf() {
if (!state.requirements || state.results.length === 0) return;
const { jsPDF } = window.jspdf;
document.getElementById('report-date').textContent = `Generated: ${new Date().toLocaleDateString()}`;
document.getElementById('pdf-category').textContent = state.requirements.category;
document.getElementById('pdf-cost').textContent = `$${state.requirements.cost.toFixed(2)}`;
document.getElementById('pdf-keywords').textContent = state.requirements.keywords || 'N/A';
document.getElementById('pdf-results-list').innerHTML = state.results.map(s => `
${s.name} (Score: ${s.score})
Category: ${s.category} | Est. Cost: $${s.cost.toFixed(2)} | Rating: ${s.rating}/5
Keywords: ${s.keywords}
`).join('');
const pdfContainer = document.getElementById('pdf-container');
pdfContainer.classList.remove('invisible', '-left-[9999px]');
try {
const canvas = await html2canvas(document.getElementById('pdf-report'), { scale: 2 });
const imgData = canvas.toDataURL('image/jpeg', 0.9);
const pdf = new jsPDF({ orientation: 'p', unit: 'px', format: [canvas.width, canvas.height] });
pdf.addImage(imgData, 'JPEG', 0, 0, canvas.width, canvas.height);
pdf.save('Supplier_Match_Report.pdf');
} catch (error) { console.error("PDF generation failed:", error); }
finally { pdfContainer.classList.add('invisible', '-left-[9999px]'); }
}
initialize();
});