Abandoned Carts
${metrics.totalCarts}
Emails Sent
${metrics.emailsSent}
`;
renderCharts();
document.getElementById('download-pdf-btn').addEventListener('click', generatePdf);
lucide.createIcons();
};
const renderCharts = () => {
// Recovery by step chart
const recoveryCtx = document.getElementById('recoveryChart').getContext('2d');
const recoveryLabels = appData.strategy.map((s, i) => `Email ${i+1}`);
const recoveryData = recoveryLabels.map((_, index) =>
cartData.filter(c => c.status === 'Recovered' && c.recoveredByStep === index + 1).reduce((sum, c) => sum + c.value, 0)
);
if (charts.recovery) charts.recovery.destroy();
charts.recovery = new Chart(recoveryCtx, {
type: 'bar',
data: { labels: recoveryLabels, datasets: [{ label: 'Revenue Recovered', data: recoveryData, backgroundColor: '#3b82f6' }] },
options: { responsive: true, maintainAspectRatio: false, plugins: { title: { display: true, text: 'Recovery by Email Step' } } }
});
// Funnel chart
const funnelCtx = document.getElementById('funnelChart').getContext('2d');
const metrics = calculateMetrics();
if (charts.funnel) charts.funnel.destroy();
charts.funnel = new Chart(funnelCtx, {
type: 'doughnut',
data: {
labels: ['Still Abandoned', 'Recovered', 'Emailed (Not Recovered)'],
datasets: [{ data: [
cartData.filter(c => c.status === 'Abandoned').length,
metrics.recoveredCarts,
cartData.filter(c => c.status === 'Emailed').length
], backgroundColor: ['#ef4444', '#22c55e', '#f97316']}]
},
options: { responsive: true, maintainAspectRatio: false, plugins: { title: { display: true, text: 'Cart Status Funnel' } } }
});
};
const renderStrategyConfig = () => {
const configContent = document.getElementById('content-strategy');
if (!configContent) return;
const strategyHtml = appData.strategy.map((step, index) => `
`).join('');
configContent.innerHTML = `
${strategyHtml}
`;
attachStrategyListeners();
};
const attachStrategyListeners = () => {
document.querySelectorAll('.strategy-input').forEach(input => {
input.addEventListener('change', (e) => {
const { index, prop } = e.target.dataset;
const value = e.target.type === 'number' ? parseFloat(e.target.value) : e.target.value;
appData.strategy[index][prop] = value;
alert('Strategy updated. Note: Run simulation on the Data tab to see effects.');
});
});
};
const renderCartData = () => {
const dataContent = document.getElementById('content-data');
if (!dataContent) return;
const getStatusBadge = (status) => {
const colors = {
Abandoned: 'bg-yellow-100 text-yellow-800',
Emailed: 'bg-orange-100 text-orange-800',
Recovered: 'bg-green-100 text-green-800'
};
return `
${status}`;
};
const tableRows = cartData.map(cart => `
| ${cart.email} |
${formatCurrency(cart.value)} |
${cart.items} |
${getStatusBadge(cart.status)} |
`).join('');
dataContent.innerHTML = `
Abandoned Carts Data
| Customer Email |
Cart Value |
Items |
Status |
${tableRows}
Note: This is sample data. Running the simulation will attempt to recover carts with 'Abandoned' status.
`;
document.getElementById('run-simulation-btn').addEventListener('click', runRecoverySimulation);
lucide.createIcons();
};
const generatePdf = () => {
loadingOverlay.style.display = 'flex';
const { jsPDF } = window.jspdf;
const pdfContent = document.getElementById('pdf-content-area');
const pdfHeader = document.getElementById('pdf-header');
document.getElementById('pdf-generated-date').textContent = new Date().toLocaleDateString('en-US');
pdfHeader.classList.remove('hidden');
html2canvas(pdfContent, { scale: 2, useCORS: true, logging: false })
.then(canvas => {
pdfHeader.classList.add('hidden');
const imgData = canvas.toDataURL('image/jpeg', 0.95);
const pdf = new jsPDF({ orientation: 'landscape', unit: 'px', format: 'a4' });
const pdfWidth = pdf.internal.pageSize.getWidth();
const imgProps = pdf.getImageProperties(imgData);
const imgHeight = (imgProps.height * pdfWidth) / imgProps.width;
pdf.addImage(imgData, 'JPEG', 0, 0, pdfWidth, imgHeight);
pdf.save('Cart-Recovery-Report.pdf');
loadingOverlay.style.display = 'none';
}).catch(err => {
console.error("PDF generation failed:", err);
pdfHeader.classList.add('hidden');
loadingOverlay.style.display = 'none';
alert('An error occurred generating the PDF.');
});
};
// --- TAB NAVIGATION & INITIALIZATION ---
const initializeTabs = () => {
const tabsContainer = document.getElementById('tabs-container');
const prevTabBtn = document.getElementById('prev-tab-btn');
const nextTabBtn = document.getElementById('next-tab-btn');
let activeTabIndex = 0;
const tabs = [
{ name: 'Recovery Dashboard', id: 'dashboard' },
{ name: 'Bot Strategy', id: 'strategy' },
{ name: 'Abandoned Carts Data', id: 'data' }
];
tabsContainer.innerHTML = tabs.map(t => `
`).join('');
mainContent.innerHTML = tabs.map(t => `
`).join('');
const tabButtons = tabsContainer.querySelectorAll('.tab-btn');
const tabContents = mainContent.querySelectorAll('.tab-content');
const switchTab = (index) => {
activeTabIndex = index;
tabButtons.forEach((btn, i) => btn.classList.toggle('active', i === index));
tabContents.forEach((content, i) => content.classList.toggle('hidden', i !== index));
prevTabBtn.disabled = activeTabIndex === 0;
nextTabBtn.disabled = activeTabIndex === tabs.length - 1;
};
tabButtons.forEach((btn, index) => btn.addEventListener('click', () => switchTab(index)));
prevTabBtn.addEventListener('click', () => { if (activeTabIndex > 0) switchTab(activeTabIndex - 1); });
nextTabBtn.addEventListener('click', () => { if (activeTabIndex < tabs.length - 1) switchTab(activeTabIndex + 1); });
switchTab(0);
renderDashboard();
renderStrategyConfig();
renderCartData();
};
initializeTabs();
});