// 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);
});
}