Business Performance Dashboard
MRR (Current)
$0
Operating Margin
0%
LTV : CAC Ratio
0:1
Revenue / Employee
$0
Monthly Recurring Revenue (MRR) Growth
OpEx Breakdown (YTD)
LTV vs. CAC
Manage Monthly Data
Monthly Data Records
| Month | Revenue | Profit | CAC | Action |
|---|
Error: A required library is missing.
'; return; } // --- DATA MANAGEMENT --- let monthlyData = JSON.parse(localStorage.getItem('bpd_monthlyData')) || []; const getSampleData = () => { const data = []; const year = new Date('2025-07-08').getFullYear(); for (let i = 0; i < 6; i++) { // First 6 months of 2025 const month = `${year}-${String(i + 1).padStart(2, '0')}`; const revenue = 45000 + (i * 5000) + Math.random() * 5000; const newCustomers = 20 + i * 3 + Math.random() * 5; data.push({ month, revenue: revenue, cogs: revenue * 0.2, // 20% COGS marketingSpend: 6000 + i * 500, opex: 15000, newCustomers: newCustomers, employees: 10 + i }); } monthlyData = data; }; if (monthlyData.length === 0) getSampleData(); const saveState = () => localStorage.setItem('bpd_monthlyData', JSON.stringify(monthlyData)); // --- CHART INSTANCES & UTILITIES --- let mrrChart, opexChart, ltvCacChart; const tabButtons = document.querySelectorAll('.bpd-tab-button'); const tabContents = document.querySelectorAll('.bpd-tab-content'); const nextBtn = document.getElementById('bpd-next-btn'); const prevBtn = document.getElementById('bpd-prev-btn'); const formatCurrency = (val) => val.toLocaleString('en-US', { style: 'currency', currency: 'USD' }); // --- RENDER FUNCTIONS --- const renderAll = () => { try { const processedData = processData(); renderKPIs(processedData); renderMrrChart(processedData); renderOpexChart(processedData); renderLtvCacChart(processedData); renderManageTable(); updateNavButtons(); } catch(error) { console.error("Dashboard rendering failed:", error); } }; const processData = () => { const sortedData = [...monthlyData].sort((a,b) => new Date(a.month) - new Date(b.month)); const calculatedData = sortedData.map(d => { const profit = d.revenue - d.cogs - d.opex - d.marketingSpend; const cac = d.newCustomers > 0 ? d.marketingSpend / d.newCustomers : 0; const grossMargin = 1 - (d.cogs / d.revenue); const ltv = d.revenue / d.newCustomers * grossMargin * 3; // Simplified LTV (3 year lifetime) return {...d, profit, cac, ltv }; }); return calculatedData; }; const renderKPIs = (data) => { const latestMonth = data[data.length - 1] || {}; const ytdRevenue = data.reduce((sum, d) => sum + d.revenue, 0); const ytdProfit = data.reduce((sum, d) => sum + d.profit, 0); const ytdOpMargin = ytdRevenue > 0 ? (ytdProfit / ytdRevenue) * 100 : 0; const ltvToCacRatio = latestMonth.cac > 0 ? latestMonth.ltv / latestMonth.cac : 0; document.getElementById('bpd-mrr-kpi').textContent = formatCurrency(latestMonth.revenue || 0); const opMarginEl = document.getElementById('bpd-op-margin-kpi'); opMarginEl.textContent = `${ytdOpMargin.toFixed(1)}%`; opMarginEl.className = ytdOpMargin >= 0 ? 'positive' : 'negative'; const ltvCacEl = document.getElementById('bpd-ltv-cac-kpi'); ltvCacEl.textContent = `${ltvToCacRatio.toFixed(1)} : 1`; ltvCacEl.className = ltvToCacRatio >= 3 ? 'positive' : 'negative'; document.getElementById('bpd-rev-per-emp-kpi').textContent = formatCurrency((latestMonth.revenue || 0) / (latestMonth.employees || 1)); }; const renderMrrChart = (data) => { const options = { chart: { type: 'area', height: 350, toolbar: { show: false } }, series: [{ name: 'MRR', data: data.map(d => d.revenue.toFixed(0)) }], xaxis: { categories: data.map(d => new Date(d.month + '-02').toLocaleString('default', { month: 'short', year: '2-digit' })) }, yaxis: { labels: { formatter: (val) => formatCurrency(val / 1000) + 'k' } }, stroke: { curve: 'smooth' }, colors: ['var(--bpd-secondary-color)'], dataLabels: { enabled: false } }; if(mrrChart) mrrChart.destroy(); document.querySelector("#bpd-mrr-chart").innerHTML = ''; mrrChart = new ApexCharts(document.querySelector("#bpd-mrr-chart"), options); mrrChart.render(); }; const renderOpexChart = (data) => { const ytdData = data.reduce((acc, d) => { acc.cogs += d.cogs; acc.marketingSpend += d.marketingSpend; acc.opex += d.opex; return acc; }, { cogs: 0, marketingSpend: 0, opex: 0 }); const options = { chart: { type: 'donut', height: 350 }, series: [ytdData.cogs, ytdData.marketingSpend, ytdData.opex], labels: ['COGS', 'Marketing', 'Operations'], legend: { position: 'bottom' } }; if(opexChart) opexChart.destroy(); document.querySelector("#bpd-opex-chart").innerHTML = ''; opexChart = new ApexCharts(document.querySelector("#bpd-opex-chart"), options); opexChart.render(); }; const renderLtvCacChart = (data) => { const latestMonth = data[data.length - 1] || {}; const options = { chart: { type: 'bar', height: 350, toolbar: { show: false } }, series: [{ name: 'Value', data: [latestMonth.ltv || 0, latestMonth.cac || 0] }], xaxis: { categories: ['Customer Lifetime Value (LTV)', 'Customer Acquisition Cost (CAC)'] }, plotOptions: { bar: { distributed: true } }, colors: ['var(--bpd-success-color)', 'var(--bpd-danger-color)'], legend: { show: false }, tooltip: { y: { formatter: (val) => formatCurrency(val) } } }; if(ltvCacChart) ltvCacChart.destroy(); document.querySelector("#bpd-ltv-cac-bar-chart").innerHTML = ''; ltvCacChart = new ApexCharts(document.querySelector("#bpd-ltv-cac-bar-chart"), options); ltvCacChart.render(); }; const renderManageTable = () => { const tbody = document.getElementById('bpd-data-tbody'); tbody.innerHTML = ''; const data = processData(); data.sort((a,b) => new Date(b.month) - new Date(a.month)).forEach(d => { tbody.innerHTML += `