${formatCurrency(p.price)}
No upsell opportunities found.
`; const crossSellContainer = document.getElementById('crossSellContainer'); crossSellContainer.innerHTML = data.crossSells.length ? data.crossSells.map(p => createCard(p, 'border-sky-500')).join('') : `No cross-sell recommendations found.
`; document.getElementById('results-container').classList.remove('hidden'); document.getElementById('dashboard-placeholder').classList.add('hidden'); }; const generatePdf = () => { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const data = lastAnalysis; if (!data.primaryProduct) return; doc.setFillColor(157, 23, 77); // pink-800 doc.rect(0, 0, 210, 28, 'F'); doc.setFont('helvetica', 'bold'); doc.setFontSize(16); doc.setTextColor(255); doc.text("Upsell & Cross-Sell Recommendation Report", 105, 18, { align: 'center' }); doc.autoTable({ startY: 40, theme: 'plain', styles: { fontSize: 11 }, body: [[{ content: 'Primary Product:', styles: { fontStyle: 'bold' } }, data.primaryProduct.name, { content: formatCurrency(data.primaryProduct.price), styles: { fontStyle: 'bold' } }]] }); if (data.upsells.length > 0) { doc.autoTable({ startY: doc.autoTable.previous.finalY + 10, head: [['Upsell Opportunities', 'Category', 'Price']], body: data.upsells.map(p => [p.name, p.category, formatCurrency(p.price)]), theme: 'grid', headStyles: { fillColor: [190, 24, 93] }, // pink-700 }); } if (data.crossSells.length > 0) { doc.autoTable({ startY: doc.autoTable.previous.finalY + 10, head: [['Cross-Sell Recommendations', 'Category', 'Price']], body: data.crossSells.map(p => [p.name, p.category, formatCurrency(p.price)]), theme: 'grid', headStyles: { fillColor: [2, 132, 199] }, // sky-600 }); } doc.save(`${data.primaryProduct.sku}_Recommendations.pdf`); }; const switchToTab = (tabName) => { tabButtons.forEach(btn => btn.classList.toggle('active', btn.dataset.tab === tabName)); tabContents.forEach(content => content.classList.toggle('hidden', content.id !== `${tabName}-content`)); }; // Init & Listeners tabButtons.forEach(btn => btn.addEventListener('click', () => switchToTab(btn.dataset.tab))); addRowBtn.addEventListener('click', () => { productCatalog.push({ sku: '', name: '', category: '', price: 0 }); renderInputTable(); }); loadSampleBtn.addEventListener('click', () => { productCatalog = JSON.parse(JSON.stringify(SAMPLE_DATA)); renderInputTable(); }); tableBody.addEventListener('change', handleTableInput); updateDashboardBtn.addEventListener('click', populateDashboard); primaryProductSelect.addEventListener('change', analyze); downloadPdfBtn.addEventListener('click', generatePdf); productCatalog = JSON.parse(JSON.stringify(SAMPLE_DATA)); renderInputTable(); populateDashboard(); });