// Sample data processing - in a real app, this would come from an API document.addEventListener('DOMContentLoaded', function() { // Process data and create visualizations // Performance overview cards createPerformanceCards(); // Top performers table createTopPerformersTable(); // Charts createRevenueByTypeChart(); createEngagementRatesChart(); // Detailed analysis table createNewsletterTable(); // Event listeners for sorting/filtering document.getElementById('sortTopPerformers').addEventListener('change', updateTopPerformersTable); document.getElementById('sortTable').addEventListener('change', updateNewsletterTable); document.getElementById('dataFilter').addEventListener('change', updateNewsletterTable); }); function createPerformanceCards() { const container = document.getElementById('performanceCards'); // These would be calculated from real data const metrics = [ { title: "Total Revenue", value: "SEK 12,450,821", change: "+7.2%", icon: "dollar-sign" }, { title: "Total Emails Sent", value: "5,271,883", change: "+3.4%", icon: "mail" }, { title: "Avg Open Rate", value: "36.5%", change: "+1.1%", icon: "eye" }, { title: "Avg Click Rate", value: "2.8%", change: "+0.4%", icon: "mouse-pointer" } ]; metrics.forEach(metric => { const card = document.createElement('div'); card.className = 'card bg-white p-4 rounded-lg shadow'; card.innerHTML = `

${metric.title}

${metric.value}

${metric.change} from last period

`; container.appendChild(card); }); } function createTopPerformersTable() { // Sort and display top 5 performers by revenue updateTopPerformersTable(); } function updateTopPerformersTable() { const sortBy = document.getElementById('sortTopPerformers').value; const tableBody = document.querySelector('#topPerformersTable tbody'); // Clear existing rows tableBody.innerHTML = ''; // Sample data - in a real app this would come from processed document data const performers = [ { name: "Batteridrivna ljus + julbelysning", revenue: "SEK 536,665", openRate: "34.3%", clickRate: "3.9%", orders: 119 }, { name: "Vakuumpåsar och förvaring", revenue: "SEK 361,063", openRate: "35.4%", clickRate: "3.2%", orders: 92 }, { name: "Nya Förvara-sortimentet", revenue: "SEK 353,538", openRate: "41.0%", clickRate: "3.9%", orders: 83 }, { name: "Gör fint hemma", revenue: "SEK 351,538", openRate: "38.9%", clickRate: "4.0%", orders: 112 }, { name: "Bästsäljare", revenue: "SEK 350,165", openRate: "39.3%", clickRate: "3.8%", orders: 156 } ]; // Sort based on selected option performers.sort((a, b) => { if (sortBy === 'revenue') { return parseFloat(b.revenue.replace(/[^0-9.]/g, '')) - parseFloat(a.revenue.replace(/[^0-9.]/g, '')); } else if (sortBy === 'openRate') { return parseFloat(b.openRate) - parseFloat(a.openRate); } else if (sortBy === 'clickRate') { return parseFloat(b.clickRate) - parseFloat(a.clickRate); } else if (sortBy === 'orders') { return b.orders - a.orders; } return 0; }); // Add rows performers.forEach(item => { const row = document.createElement('tr'); row.className = 'border-b hover:bg-gray-50'; row.innerHTML = ` ${item.name} ${item.revenue} ${item.openRate} ${item.clickRate} ${item.orders} `; tableBody.appendChild(row); }); } function createRevenueByTypeChart() { const ctx = document.getElementById('revenueByTypeChart').getContext('2d'); // Sample data based on document categories new Chart(ctx, { type: 'bar', data: { labels: ['Home & Living', 'Seasonal', 'Food & Cooking', 'Garden', 'Personal Care', 'Other'], datasets: [{ label: 'Revenue (SEK)', data: [4850000, 3200000, 2100000, 1800000, 950000, 450000], backgroundColor: [ 'rgba(59, 130, 246, 0.7)', 'rgba(16, 185, 129, 0.7)', 'rgba(245, 158, 11, 0.7)', 'rgba(139, 92, 246, 0.7)', 'rgba(236, 72, 153, 0.7)', 'rgba(75, 85, 99, 0.7)' ], borderColor: [ 'rgba(59, 130, 246, 1)', 'rgba(16, 185, 129, 1)', 'rgba(245, 158, 11, 1)', 'rgba(139, 92, 246, 1)', 'rgba(236, 72, 153, 1)', 'rgba(75, 85, 99, 1)' ], borderWidth: 1 }] }, options: { responsive: true, plugins: { legend: { display: false }, tooltip: { callbacks: { label: function(context) { return `SEK ${context.raw.toLocaleString()}`; } } } }, scales: { y: { beginAtZero: true, ticks: { callback: function(value) { return `SEK ${(value / 1000).toFixed(0)}k`; } } } } } }); } function createEngagementRatesChart() { const ctx = document.getElementById('engagementRatesChart').getContext('2d'); new Chart(ctx, { type: 'line', data: { labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], datasets: [ { label: 'Open Rate', data: [32.5, 34.1, 35.7, 36.2, 37.8, 38.2, 37.5, 38.1, 39.4, 39.8, 40.2, 42.3], borderColor: 'rgba(59, 130, 246, 1)', backgroundColor: 'rgba(59, 130, 246, 0.1)', tension: 0.4, fill: true }, { label: 'Click Rate', data: [2.1, 2.3, 2.5, 2.6, 2.8, 2.9, 3.0, 3.1, 3.2, 3.3, 3.6, 3.9], borderColor: 'rgba(16, 185, 129, 1)', backgroundColor: 'rgba(16, 185, 129, 0.1)', tension: 0.4, fill: true } ] }, options: { responsive: true, plugins: { tooltip: { callbacks: { label: function(context) { return `${context.dataset.label}: ${context.raw}%`; } } } }, scales: { y: { beginAtZero: false, min: 0, ticks: { callback: function(value) { return `${value}%`; } } } } } }); } function createNewsletterTable() { // Initial load with all data updateNewsletterTable(); } function updateNewsletterTable() { const filterValue = document.getElementById('dataFilter').value; const sortBy = document.getElementById('sortTable').value; const tableBody = document.querySelector('#newsletterTable tbody'); // Clear existing rows tableBody.innerHTML = ''; // Sample data - in a real app this would be processed from the documents const newsletters = [ { name: "Batteridrivna ljus + julbelysning [SV]", sent: "179,638", delivered: "179,426", opens: "24,753", clicks: "2,643", revenue: "SEK 53,666", orders: 119, openRate: "13.8%", clickRate: "1.5%", country: "SE" }, { name: "Vakuumpåsar och förvaring [SV]", sent: "171,597", delivered: "171,292", opens: "60,651", clicks: "2,853", revenue: "SEK 36,106", orders: 92, openRate: "35.4%", clickRate: "1.7%", country: "SE" }, { name: "Nya Förvara-sortimentet [SV]", sent: "172,602", delivered: "172,400", opens: "61,560", clicks: "6,103", revenue: "SEK 35,347", orders: 83, openRate: "35.7%", clickRate: "3.5%", country: "SE" }, { name: "Gör fint hemma [SV]", sent: "172,075", delivered: "171,737", opens: "61,503", clicks: "4,338", revenue: "SEK 31,975", orders: 112, openRate: "35.8%", clickRate: "2.5%", country: "SE" }, { name: "Bästsäljare [SV]", sent: "172,845", delivered: "172,650", opens: "61,455", clicks: "4,339", revenue: "SEK 31,175", orders: 156, openRate: "35.6%", clickRate: "2.5%", country: "SE" }, { name: "Utomhusljus - Gravljus [NO]", sent: "30,441", delivered: "30,402", opens: "7,656", clicks: "508", revenue: "SEK 6,493", orders: 11, openRate: "25.2%", clickRate: "1.7%", country: "NO" }, { name: "Batteridrivna ljus + julbelysning [NO]", sent: "30,423", delivered: "30,387", opens: "7,687", clicks: "459", revenue: "SEK 5,939", orders: 11, openRate: "25.3%", clickRate: "1.5%", country: "NO" }, { name: "Bakning [DK]", sent: "6,243", delivered: "6,205", opens: "1,973", clicks: "101", revenue: "SEK 1,923", orders: 5, openRate: "31.8%", clickRate: "1.6%", country: "DK" } ]; // Filter data let filteredData = newsletters; if (filterValue !== 'all') { filteredData = newsletters.filter(item => item.country === filterValue); } // Sort data filteredData.sort((a, b) => { if (sortBy === 'name') { return a.name.localeCompare(b.name); } else if (sortBy === 'revenue') { return parseFloat(b.revenue.replace(/[^0-9.]/g, '')) - parseFloat(a.revenue.replace(/[^0-9.]/g, '')); } else if (sortBy === 'openRate') { return parseFloat(b.openRate) - parseFloat(a.openRate); } else if (sortBy === 'clickRate') { return parseFloat(b.clickRate) - parseFloat(a.clickRate); } else if (sortBy === 'orders') { return b.orders - a.orders; } return 0; }); // Add rows filteredData.forEach(item => { const row = document.createElement('tr'); row.className = 'border-b hover:bg-gray-50'; row.innerHTML = ` ${item.name} ${item.sent} ${item.delivered} ${item.opens} ${item.clicks} ${item.revenue} ${item.orders} ${item.openRate} ${item.clickRate} `; tableBody.appendChild(row); }); }