diff --git a/src/components/Dashboard.tsx b/src/components/Dashboard.tsx
index 22465ec..4f8ca76 100644
--- a/src/components/Dashboard.tsx
+++ b/src/components/Dashboard.tsx
@@ -106,14 +106,44 @@ function Dashboard({ data, showDataLabels, setShowDataLabels, includeVAT, setInc
return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
};
+ // Linear regression helper
+ const linearRegression = (values: number[]) => {
+ const n = values.length;
+ if (n < 2) return values;
+ let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
+ for (let i = 0; i < n; i++) {
+ sumX += i;
+ sumY += values[i];
+ sumXY += i * values[i];
+ sumX2 += i * i;
+ }
+ const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
+ const intercept = (sumY - slope * sumX) / n;
+ return values.map((_, i) => slope * i + intercept);
+ };
+
+ const trendlineDataset = (values: number[]) => ({
+ label: 'Trend',
+ data: linearRegression(values),
+ borderColor: chartColors.secondary,
+ borderWidth: 2,
+ borderDash: [6, 4],
+ tension: 0,
+ fill: false,
+ pointRadius: 0,
+ pointHoverRadius: 0,
+ datalabels: { display: false }
+ });
+
if (trendGranularity === 'week') {
const grouped = groupByWeek(filteredData, includeVAT);
const weeks = Object.keys(grouped).filter(w => w).sort();
+ const revenueValues = weeks.map(w => grouped[w].revenue);
return {
labels: weeks.map(formatLabel),
datasets: [{
label: includeVAT ? 'Revenue (incl. VAT)' : 'Revenue (excl. VAT)',
- data: weeks.map(w => grouped[w].revenue),
+ data: revenueValues,
borderColor: chartColors.primary,
backgroundColor: chartColors.primary + '10',
borderWidth: 2,
@@ -121,7 +151,7 @@ function Dashboard({ data, showDataLabels, setShowDataLabels, includeVAT, setInc
fill: true,
pointRadius: 0,
pointHoverRadius: 4
- }]
+ }, trendlineDataset(revenueValues)]
};
} else {
// Daily granularity
@@ -132,11 +162,12 @@ function Dashboard({ data, showDataLabels, setShowDataLabels, includeVAT, setInc
dailyData[date] += Number(row[revenueField] || row.revenue_incl_tax || 0);
});
const days = Object.keys(dailyData).sort();
+ const revenueValues = days.map(d => dailyData[d]);
return {
labels: days.map(formatLabel),
datasets: [{
label: includeVAT ? 'Revenue (incl. VAT)' : 'Revenue (excl. VAT)',
- data: days.map(d => dailyData[d]),
+ data: revenueValues,
borderColor: chartColors.primary,
backgroundColor: chartColors.primary + '10',
borderWidth: 1.5,
@@ -144,7 +175,7 @@ function Dashboard({ data, showDataLabels, setShowDataLabels, includeVAT, setInc
fill: true,
pointRadius: 0,
pointHoverRadius: 3
- }]
+ }, trendlineDataset(revenueValues)]
};
}
}, [filteredData, trendGranularity, includeVAT]);
@@ -465,7 +496,7 @@ function Dashboard({ data, showDataLabels, setShowDataLabels, includeVAT, setInc
}
>
-