Add average order value to analytics chart

Enhanced the AdminAnalytics component to display average order value (AOV) alongside revenue and orders in the analytics chart. Updated data structures and chart rendering to support and visualize AOV, providing more detailed business insights.
This commit is contained in:
g
2025-12-03 18:03:01 +00:00
parent 98f14304b7
commit 884574ccce
2 changed files with 21 additions and 9 deletions

View File

@@ -41,7 +41,7 @@ interface AnalyticsData {
total?: number;
today?: number;
thisWeek?: number;
dailyRevenue?: { date: string; amount: number }[];
dailyRevenue?: { date: string; amount: number; orders?: number; avgOrderValue?: number }[];
};
engagement?: {
totalChats?: number;
@@ -130,14 +130,17 @@ export default function AdminAnalytics() {
};
// Helper to combine orders and revenue data for dual-axis chart
const combineOrdersAndRevenue = (orders: Array<{ date: string; count: number }>, revenue: Array<{ date: string; amount: number }>) => {
const combineOrdersAndRevenue = (orders: Array<{ date: string; count: number }>, revenue: Array<{ date: string; amount: number; orders?: number; avgOrderValue?: number }>) => {
if (!orders || orders.length === 0) return [];
// Create a map of revenue by date for quick lookup
const revenueMap = new Map<string, number>();
// Create a map of revenue and AOV by date for quick lookup
const revenueMap = new Map<string, { amount: number; avgOrderValue: number }>();
if (revenue && revenue.length > 0) {
revenue.forEach(r => {
revenueMap.set(r.date, r.amount || 0);
revenueMap.set(r.date, {
amount: r.amount || 0,
avgOrderValue: r.avgOrderValue || 0
});
});
}
@@ -152,11 +155,14 @@ export default function AdminAnalytics() {
const dayOfWeek = date.toLocaleDateString('en-GB', { weekday: 'short' });
const monthDay = date.toLocaleDateString('en-GB', { month: 'short', day: 'numeric' });
const revenueData = revenueMap.get(dateStr) || { amount: 0, avgOrderValue: 0 };
return {
date: dateStr,
formattedDate: `${dayOfWeek}, ${monthDay}`,
orders: order.count || 0,
revenue: revenueMap.get(dateStr) || 0
revenue: revenueData.amount,
avgOrderValue: revenueData.avgOrderValue
};
});
};
@@ -185,6 +191,11 @@ export default function AdminAnalytics() {
<p className="text-sm text-green-600">
Revenue: <span className="font-semibold">{formatGBP(data.revenue)}</span>
</p>
{data.avgOrderValue !== undefined && data.avgOrderValue > 0 && (
<p className="text-sm text-purple-600">
Avg Order Value: <span className="font-semibold">{formatGBP(data.avgOrderValue)}</span>
</p>
)}
</div>
) : (
<p className="text-sm text-primary">
@@ -601,11 +612,12 @@ export default function AdminAnalytics() {
orientation="right"
tick={{ fontSize: 12 }}
tickFormatter={(value) => `£${(value / 1000).toFixed(0)}k`}
label={{ value: 'Revenue', angle: 90, position: 'insideRight' }}
label={{ value: 'Revenue / AOV', angle: 90, position: 'insideRight' }}
/>
<Tooltip content={<CustomTooltip />} />
<Bar yAxisId="left" dataKey="orders" fill="#3b82f6" radius={[2, 2, 0, 0]} name="Orders" />
<Line yAxisId="right" type="monotone" dataKey="revenue" stroke="#10b981" strokeWidth={2} dot={{ fill: '#10b981', r: 4 }} name="Revenue" />
<Line yAxisId="right" type="monotone" dataKey="avgOrderValue" stroke="#a855f7" strokeWidth={2} strokeDasharray="5 5" dot={{ fill: '#a855f7', r: 3 }} name="Avg Order Value" />
</ComposedChart>
</ResponsiveContainer>
</div>

View File

@@ -1,4 +1,4 @@
{
"commitHash": "4ef0fd1",
"buildTime": "2025-11-30T15:39:38.047Z"
"commitHash": "93214ce",
"buildTime": "2025-12-01T13:19:53.318Z"
}