`;
elements.csConfigContainer.appendChild(transactionEl);
});
}
// --- EVENT HANDLERS --- //
function handleConfigChange(e) {
if (!e.target.classList.contains('transaction-input')) return;
const target = e.target;
const id = parseInt(target.dataset.id);
const field = target.dataset.field;
const value = target.type === 'number' ? parseFloat(target.value) || 0 : target.value;
const transaction = crossSellData.transactions.find(t => t.id === id);
if (transaction) {
transaction[field] = value;
updateDashboardUI();
}
}
function handleAddTransaction() {
const newId = crossSellData.transactions.length > 0 ? Math.max(...crossSellData.transactions.map(t => t.id)) + 1 : 1;
crossSellData.transactions.unshift({
id: newId, primaryProduct: 'New Product', primaryRevenue: 0, crossSellProduct: '', crossSellRevenue: 0
});
populateConfigForm();
updateDashboardUI();
}
function handleRemoveTransaction(e) {
if (!e.target.classList.contains('remove-transaction-btn')) return;
const id = parseInt(e.target.dataset.id);
crossSellData.transactions = crossSellData.transactions.filter(t => t.id !== id);
populateConfigForm();
updateDashboardUI();
}
async function handlePdfDownload() {
if (typeof html2canvas === 'undefined' || typeof window.jspdf === 'undefined') return;
const { jsPDF } = window.jspdf;
const pdfExportElement = elements.pdfExportArea;
if (!pdfExportElement) return;
const originalBg = pdfExportElement.style.backgroundColor;
pdfExportElement.style.backgroundColor = 'white';
try {
const canvas = await html2canvas(pdfExportElement, { scale: 2, useCORS: true, logging: false });
pdfExportElement.style.backgroundColor = originalBg;
const imgData = canvas.toDataURL('image/png');
const pdf = new jsPDF({
orientation: 'landscape',
unit: 'px',
format: [canvas.width, canvas.height]
});
pdf.addImage(imgData, 'PNG', 0, 0, canvas.width, canvas.height);
pdf.save('Cross-Sell-Performance-Dashboard.pdf');
} catch (error) {
console.error("Error generating PDF:", error);
pdfExportElement.style.backgroundColor = originalBg;
}
}
// --- INITIALIZATION --- //
if (elements.csConfigContainer) {
elements.csConfigContainer.addEventListener('input', handleConfigChange);
elements.csConfigContainer.addEventListener('click', handleRemoveTransaction);
}
if (elements.addTransactionBtn) {
elements.addTransactionBtn.addEventListener('click', handleAddTransaction);
}
if (elements.downloadPdfBtn) {
elements.downloadPdfBtn.addEventListener('click', handlePdfDownload);
}
updateDashboardUI();
populateConfigForm();
window.updateNavButtons();
});
// --- GLOBAL FUNCTIONS FOR TAB NAVIGATION --- //
function switchTab(tabName) {
const tabDashboard = document.getElementById('tab-panel-dashboard');
const tabConfig = document.getElementById('tab-panel-config');
const btnDashboard = document.getElementById('tab-btn-dashboard');
const btnConfig = document.getElementById('tab-btn-config');
if (!tabDashboard || !tabConfig || !btnDashboard || !btnConfig) return;
const isDashboard = tabName === 'dashboard';
tabDashboard.classList.toggle('hidden', !isDashboard);
tabConfig.classList.toggle('hidden', isDashboard);
btnDashboard.classList.toggle('active', isDashboard);
btnConfig.classList.toggle('active', !isDashboard);
updateNavButtons();
}
function updateNavButtons() {
const btnDashboard = document.getElementById('tab-btn-dashboard');
const prevBtn = document.getElementById('prev-btn');
const nextBtn = document.getElementById('next-btn');
if (!btnDashboard || !prevBtn || !nextBtn) return;
const isDashboardActive = btnDashboard.classList.contains('active');
prevBtn.disabled = isDashboardActive;
nextBtn.disabled = !isDashboardActive;
prevBtn.classList.toggle('opacity-50', isDashboardActive);
prevBtn.classList.toggle('cursor-not-allowed', isDashboardActive);
nextBtn.classList.toggle('opacity-50', !isDashboardActive);
nextBtn.classList.toggle('cursor-not-allowed', !isDashboardActive);
}
function navigateTabs(direction) {
const isDashboardActive = document.getElementById('tab-btn-dashboard').classList.contains('active');
if (direction === 'next' && isDashboardActive) {
switchTab('config');
} else if (direction === 'prev' && !isDashboardActive) {
switchTab('dashboard');
}
}