`;
tableHtml = `
| Top Tweets | Retweets | Likes | Replies |
${data.tweets.map(t => `| ${t.content} | ${t.retweets} | ${t.likes} | ${t.replies} |
`).join('')}
`;
} else if (platform === 'instagram') {
kpis += `
Reach
${(data.reach/1000).toFixed(1)}k
Story Views
${(data.storyViews/1000).toFixed(1)}k
`;
tableHtml = `
| Top Posts | Likes | Comments | Saves |
${data.posts.map(p => `| ${p.content} | ${p.likes} | ${p.comments} | ${p.saves} |
`).join('')}
`;
} else if (platform === 'linkedin') {
kpis += `
Impressions
${(data.impressions/1000).toFixed(1)}k
Engagement
${(data.engagement/1000).toFixed(1)}k
`;
tableHtml = `
Visitor Demographics (Industry)
`;
}
return kpis + tableHtml;
}
function createCampaignPerformance() {
const campaignsHtml = dashboardData.campaigns.map(c => `
| ${c.name} | ${c.platform} |
$${c.spend.toLocaleString()} | ${c.conversions.toLocaleString()} |
${c.roi}% | $${(c.spend * c.roi / 100).toLocaleString()} |
`).join('');
return `
| Campaign Name | Platform | Spend | Conversions | ROI | Return |
${campaignsHtml}
`;
}
// --- HELPER & UTILITY ---
function createKPICard(title, value, color, svgPath) {
return `
`;
}
function addTableRow(tableId) {
const tableBody = document.querySelector(`#${tableId} tbody`);
const newRow = tableBody.insertRow();
const emptyItem = { content: '', likes: 0, comments: 0, shares: 0, retweets: 0, replies: 0, saves: 0, name: '', platform: 'Facebook', spend: 0, conversions: 0, roi: 0 };
let cellsHtml = '';
if (tableId.includes('facebook')) cellsHtml = `
| | | | `;
else if (tableId.includes('twitter')) cellsHtml = `
| | | | `;
else if (tableId.includes('instagram')) cellsHtml = `
| | | | `;
else if (tableId.includes('campaigns')) cellsHtml = `
| | | | | `;
newRow.innerHTML = `${cellsHtml}
| `;
newRow.querySelector('.delete-row-btn').addEventListener('click', (e) => e.target.closest('tr').remove());
}
function renderChartsForTab(tabId) {
const { analytics, linkedin } = dashboardData;
const chartOptions = (type = 'x') => ({
scales: type === 'x' ? {
y: { beginAtZero: true, ticks: { color: '#94a3b8' }, grid: { color: '#475569' } },
x: { ticks: { color: '#94a3b8' }, grid: { color: '#334155' } }
} : {},
plugins: { legend: { labels: { color: '#cbd5e1' } } }
});
if (tabId === 'overall-summary') {
if (window.followerGrowthChartInstance) window.followerGrowthChartInstance.destroy();
const followerCtx = document.getElementById('followerGrowthChart')?.getContext('2d');
if(followerCtx) window.followerGrowthChartInstance = new Chart(followerCtx, { type: 'line', data: { labels: analytics.followerGrowth.labels, datasets: [{ label: 'Total Followers (k)', data: analytics.followerGrowth.data, backgroundColor: 'rgba(59, 130, 246, 0.2)', borderColor: 'rgba(59, 130, 246, 1)', borderWidth: 2, tension: 0.3, fill: true }] }, options: chartOptions() });
if (window.engagementByPlatformChartInstance) window.engagementByPlatformChartInstance.destroy();
const engagementCtx = document.getElementById('engagementByPlatformChart')?.getContext('2d');
if(engagementCtx) window.engagementByPlatformChartInstance = new Chart(engagementCtx, { type: 'bar', data: { labels: analytics.engagementByPlatform.labels, datasets: [{ label: 'Engagement', data: analytics.engagementByPlatform.data, backgroundColor: ['#3b82f6', '#0ea5e9', '#d946ef', '#0a66c2'] }] }, options: chartOptions() });
}
if (tabId === 'linkedin-analytics') {
if (window.linkedinVisitorChartInstance) window.linkedinVisitorChartInstance.destroy();
const linkedinCtx = document.getElementById('linkedinVisitorChart')?.getContext('2d');
if(linkedinCtx) window.linkedinVisitorChartInstance = new Chart(linkedinCtx, { type: 'doughnut', data: { labels: linkedin.visitors.labels, datasets: [{ label: 'Visitor Industry', data: linkedin.visitors.data, backgroundColor: ['#3b82f6', '#14b8a6', '#f97316', '#8b5cf6'], borderColor: '#1e293b', borderWidth: 3 }] }, options: { ...chartOptions('none'), plugins: { legend: { position: 'bottom', labels: { color: '#cbd5e1' } } } } });
}
}
function navigateTabs(direction) {
const newIndex = currentTabIndex + direction;
if (newIndex >= 0 && newIndex < tabs.length) showTab(newIndex);
}
function updateNavButtons() {
prevTabBtn.disabled = currentTabIndex === 0;
nextTabBtn.disabled = currentTabIndex === tabs.length - 1;
}
function generatePDF() {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const activeTab = tabs[currentTabIndex];
doc.setFontSize(18); doc.text('Social Media Analytics Report', 14, 22);
doc.setFontSize(12); doc.text(activeTab.name, 14, 30);
// This is a simplified example; more complex logic can be added for each tab.
const table = tabContentArea.querySelector(`#${activeTab.id} table`);
if(table) {
doc.autoTable({ html: table, startY: 40, theme: 'grid', headStyles: { fillColor: [51, 65, 85] } });
} else if (activeTab.id === 'overall-summary') {
const { summary } = dashboardData;
doc.autoTable({
startY: 40, head: [['Metric', 'Value']],
body: [['Total Followers', summary.totalFollowers.toLocaleString()], ['Total Engagement', summary.totalEngagement.toLocaleString()], ['Total Reach', summary.totalReach.toLocaleString()], ['Profile Visits', summary.profileVisits.toLocaleString()]],
theme: 'grid', headStyles: { fillColor: [51, 65, 85] }
});
}
doc.save(`Social_Media_${activeTab.name.replace(/\s/g, '_')}.pdf`);
}
init();
});