-
-
Notifications
You must be signed in to change notification settings - Fork 5.3k
/
Copy pathOrderChart.tsx
124 lines (115 loc) · 4.47 KB
/
OrderChart.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import * as React from 'react';
import { Card, CardHeader, CardContent } from '@mui/material';
import {
ResponsiveContainer,
AreaChart,
Area,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
} from 'recharts';
import { useTranslate } from 'react-admin';
import { format, subDays, addDays } from 'date-fns';
import { Order } from '../types';
const lastDay = new Date();
const lastMonthDays = Array.from({ length: 30 }, (_, i) => subDays(lastDay, i));
const aMonthAgo = subDays(new Date(), 30);
const dateFormatter = (date: number): string =>
new Date(date).toLocaleDateString();
const aggregateOrdersByDay = (orders: Order[]): { [key: string]: number } =>
orders
.filter((order: Order) => order.status !== 'cancelled')
.reduce(
(acc, curr) => {
const day = format(curr.date, 'yyyy-MM-dd');
if (!acc[day]) {
acc[day] = 0;
}
acc[day] += curr.total;
return acc;
},
{} as { [key: string]: number }
);
const getRevenuePerDay = (orders: Order[]): TotalByDay[] => {
const daysWithRevenue = aggregateOrdersByDay(orders);
return lastMonthDays.map(date => ({
date: date.getTime(),
total: daysWithRevenue[format(date, 'yyyy-MM-dd')] || 0,
}));
};
const OrderChart = (props: { orders?: Order[] }) => {
const { orders } = props;
const translate = useTranslate();
if (!orders) return null;
return (
<Card>
<CardHeader title={translate('pos.dashboard.month_history')} />
<CardContent>
<div style={{ width: '100%', height: 300 }}>
<ResponsiveContainer>
<AreaChart data={getRevenuePerDay(orders)}>
<defs>
<linearGradient
id="colorUv"
x1="0"
y1="0"
x2="0"
y2="1"
>
<stop
offset="5%"
stopColor="#8884d8"
stopOpacity={0.8}
/>
<stop
offset="95%"
stopColor="#8884d8"
stopOpacity={0}
/>
</linearGradient>
</defs>
<XAxis
dataKey="date"
name="Date"
type="number"
scale="time"
domain={[
addDays(aMonthAgo, 1).getTime(),
new Date().getTime(),
]}
tickFormatter={dateFormatter}
/>
<YAxis dataKey="total" name="Revenue" unit="€" />
<CartesianGrid strokeDasharray="3 3" />
<Tooltip
cursor={{ strokeDasharray: '3 3' }}
formatter={(value: any) =>
new Intl.NumberFormat(undefined, {
style: 'currency',
currency: 'USD',
}).format(value)
}
labelFormatter={(label: any) =>
dateFormatter(label)
}
/>
<Area
type="monotone"
dataKey="total"
stroke="#8884d8"
strokeWidth={2}
fill="url(#colorUv)"
/>
</AreaChart>
</ResponsiveContainer>
</div>
</CardContent>
</Card>
);
};
interface TotalByDay {
date: number;
total: number;
}
export default OrderChart;