Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 76b1594

Browse files
feat(site): add date range picker for the template insights (coder#8976)
1 parent f4122fa commit 76b1594

File tree

6 files changed

+391
-37
lines changed

6 files changed

+391
-37
lines changed

site/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"@types/color-convert": "2.0.0",
4949
"@types/lodash": "4.14.196",
5050
"@types/react-color": "3.0.6",
51+
"@types/react-date-range": "1.4.4",
5152
"@types/semver": "7.5.0",
5253
"@vitejs/plugin-react": "4.0.1",
5354
"@xstate/inspect": "0.8.0",
@@ -77,6 +78,7 @@
7778
"react-chartjs-2": "5.2.0",
7879
"react-color": "2.19.3",
7980
"react-confetti": "6.1.0",
81+
"react-date-range": "1.4.0",
8082
"react-dom": "18.2.0",
8183
"react-headless-tabs": "6.0.3",
8284
"react-helmet-async": "1.3.0",

site/pnpm-lock.yaml

+44
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
import Box from "@mui/material/Box"
2+
import { styled } from "@mui/material/styles"
3+
import { ComponentProps, useRef, useState } from "react"
4+
import "react-date-range/dist/styles.css"
5+
import "react-date-range/dist/theme/default.css"
6+
import Button from "@mui/material/Button"
7+
import ArrowRightAltOutlined from "@mui/icons-material/ArrowRightAltOutlined"
8+
import Popover from "@mui/material/Popover"
9+
import { DateRangePicker, createStaticRanges } from "react-date-range"
10+
import { format, subDays } from "date-fns"
11+
12+
// The type definition from @types is wrong
13+
declare module "react-date-range" {
14+
export function createStaticRanges(
15+
ranges: Omit<StaticRange, "isSelected">[],
16+
): StaticRange[]
17+
}
18+
19+
export type DateRangeValue = {
20+
startDate: Date
21+
endDate: Date
22+
}
23+
24+
type RangesState = NonNullable<ComponentProps<typeof DateRangePicker>["ranges"]>
25+
26+
export const DateRange = ({
27+
value,
28+
onChange,
29+
}: {
30+
value: DateRangeValue
31+
onChange: (value: DateRangeValue) => void
32+
}) => {
33+
const selectionStatusRef = useRef<"idle" | "selecting">("idle")
34+
const anchorRef = useRef<HTMLButtonElement>(null)
35+
const [isOpen, setIsOpen] = useState(false)
36+
const [ranges, setRanges] = useState<RangesState>([
37+
{
38+
...value,
39+
key: "selection",
40+
},
41+
])
42+
const currentRange = {
43+
startDate: ranges[0].startDate as Date,
44+
endDate: ranges[0].endDate as Date,
45+
}
46+
const handleClose = () => {
47+
onChange({
48+
startDate: currentRange.startDate,
49+
endDate: currentRange.endDate,
50+
})
51+
setIsOpen(false)
52+
}
53+
54+
return (
55+
<>
56+
<Button ref={anchorRef} onClick={() => setIsOpen(true)}>
57+
<span>{format(currentRange.startDate, "MMM d, Y")}</span>
58+
<ArrowRightAltOutlined sx={{ width: 16, height: 16, mx: 1 }} />
59+
<span>{format(currentRange.endDate, "MMM d, Y")}</span>
60+
</Button>
61+
<Popover
62+
anchorEl={anchorRef.current}
63+
open={isOpen}
64+
onClose={handleClose}
65+
anchorOrigin={{
66+
vertical: "bottom",
67+
horizontal: "left",
68+
}}
69+
sx={{
70+
"& .MuiPaper-root": {
71+
marginTop: 1,
72+
},
73+
}}
74+
>
75+
<DateRangePickerWrapper
76+
component={DateRangePicker}
77+
onChange={(item) => {
78+
const range = item.selection
79+
setRanges([range])
80+
81+
// When it is the first selection, we don't want to close the popover
82+
// We have to do that ourselves because the library doesn't provide a way to do it
83+
if (selectionStatusRef.current === "idle") {
84+
selectionStatusRef.current = "selecting"
85+
return
86+
}
87+
88+
selectionStatusRef.current = "idle"
89+
const startDate = range.startDate as Date
90+
const endDate = range.endDate as Date
91+
onChange({
92+
startDate,
93+
endDate,
94+
})
95+
setIsOpen(false)
96+
}}
97+
moveRangeOnFirstSelection={false}
98+
months={2}
99+
ranges={ranges}
100+
maxDate={new Date()}
101+
direction="horizontal"
102+
staticRanges={createStaticRanges([
103+
{
104+
label: "Today",
105+
range: () => ({
106+
startDate: new Date(),
107+
endDate: new Date(),
108+
}),
109+
},
110+
{
111+
label: "Yesterday",
112+
range: () => ({
113+
startDate: subDays(new Date(), 1),
114+
endDate: subDays(new Date(), 1),
115+
}),
116+
},
117+
{
118+
label: "Last 7 days",
119+
range: () => ({
120+
startDate: subDays(new Date(), 6),
121+
endDate: new Date(),
122+
}),
123+
},
124+
{
125+
label: "Last 14 days",
126+
range: () => ({
127+
startDate: subDays(new Date(), 13),
128+
endDate: new Date(),
129+
}),
130+
},
131+
{
132+
label: "Last 30 days",
133+
range: () => ({
134+
startDate: subDays(new Date(), 29),
135+
endDate: new Date(),
136+
}),
137+
},
138+
])}
139+
/>
140+
</Popover>
141+
</>
142+
)
143+
}
144+
145+
const DateRangePickerWrapper: typeof Box = styled(Box)(({ theme }) => ({
146+
"& .rdrDefinedRangesWrapper": {
147+
background: theme.palette.background.paper,
148+
borderColor: theme.palette.divider,
149+
},
150+
151+
"& .rdrStaticRange": {
152+
background: theme.palette.background.paper,
153+
border: 0,
154+
fontSize: 14,
155+
color: theme.palette.text.secondary,
156+
157+
"&:hover .rdrStaticRangeLabel": {
158+
background: theme.palette.background.paperLight,
159+
color: theme.palette.text.primary,
160+
},
161+
162+
"&.rdrStaticRangeSelected": {
163+
color: `${theme.palette.text.primary} !important`,
164+
},
165+
},
166+
167+
"& .rdrInputRanges": {
168+
display: "none",
169+
},
170+
171+
"& .rdrDateDisplayWrapper": {
172+
backgroundColor: theme.palette.background.paper,
173+
},
174+
175+
"& .rdrCalendarWrapper": {
176+
backgroundColor: theme.palette.background.paperLight,
177+
},
178+
179+
"& .rdrDateDisplayItem": {
180+
background: "transparent",
181+
borderColor: theme.palette.divider,
182+
183+
"& input": {
184+
color: theme.palette.text.secondary,
185+
},
186+
187+
"&.rdrDateDisplayItemActive": {
188+
borderColor: theme.palette.text.primary,
189+
backgroundColor: theme.palette.background.paperLight,
190+
191+
"& input": {
192+
color: theme.palette.text.primary,
193+
},
194+
},
195+
},
196+
197+
"& .rdrMonthPicker select, & .rdrYearPicker select": {
198+
color: theme.palette.text.primary,
199+
appearance: "auto",
200+
background: "transparent",
201+
},
202+
203+
"& .rdrMonthName, & .rdrWeekDay": {
204+
color: theme.palette.text.secondary,
205+
},
206+
207+
"& .rdrDayPassive .rdrDayNumber span": {
208+
color: theme.palette.text.disabled,
209+
},
210+
211+
"& .rdrDayNumber span": {
212+
color: theme.palette.text.primary,
213+
},
214+
215+
"& .rdrDayToday .rdrDayNumber span": {
216+
fontWeight: 900,
217+
218+
"&:after": {
219+
display: "none",
220+
},
221+
},
222+
223+
"& .rdrInRange, & .rdrEndEdge, & .rdrStartEdge": {
224+
color: theme.palette.primary.main,
225+
},
226+
227+
"& .rdrDayDisabled": {
228+
backgroundColor: "transparent",
229+
230+
"& .rdrDayNumber span": {
231+
color: theme.palette.text.disabled,
232+
},
233+
},
234+
}))

0 commit comments

Comments
 (0)