Skip to content

Commit 41cc638

Browse files
committed
Add weekly controls
1 parent ad8a4ae commit 41cc638

File tree

3 files changed

+142
-18
lines changed

3 files changed

+142
-18
lines changed

site/src/pages/TemplatePage/TemplateInsightsPage/TemplateInsightsPage.tsx

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@ import {
2626
UserLatencyInsightsResponse,
2727
} from "api/typesGenerated";
2828
import { ComponentProps, ReactNode, useState } from "react";
29-
import { subDays, isToday } from "date-fns";
29+
import {
30+
subDays,
31+
subWeeks,
32+
startOfWeek,
33+
endOfWeek,
34+
isSunday,
35+
endOfDay,
36+
} from "date-fns";
3037
import "react-date-range/dist/styles.css";
3138
import "react-date-range/dist/theme/default.css";
3239
import { DateRange, DateRangeValue } from "./DateRange";
@@ -37,23 +44,30 @@ import { getDateRangeFilter } from "./utils";
3744
import Tooltip from "@mui/material/Tooltip";
3845
import LinkOutlined from "@mui/icons-material/LinkOutlined";
3946
import { InsightsInterval, IntervalMenu } from "./IntervalMenu";
47+
import { WeeklyPreset, WeeklyPresetsMenu } from "./WeeklyPresetsMenu";
4048

4149
export default function TemplateInsightsPage() {
50+
const { template } = useTemplateLayoutContext();
4251
const now = new Date();
43-
const [interval, setInterval] = useState<InsightsInterval>("day");
44-
const [dateRangeValue, setDateRangeValue] = useState<DateRangeValue>({
52+
53+
const defaultWeeklyPreset = 4;
54+
const defaultDateRangeValue = {
4555
startDate: subDays(now, 6),
4656
endDate: now,
47-
});
48-
const { template } = useTemplateLayoutContext();
57+
};
58+
59+
const [interval, setInterval] = useState<InsightsInterval>("day");
60+
const [weeklyPreset, setWeeklyPreset] =
61+
useState<WeeklyPreset>(defaultWeeklyPreset);
62+
const [dateRangeValue, setDateRangeValue] = useState<DateRangeValue>(
63+
defaultDateRangeValue,
64+
);
65+
66+
const dateRange =
67+
interval === "day" ? dateRangeValue : getWeeklyRange(weeklyPreset);
4968
const commonFilters = {
5069
template_ids: template.id,
51-
...getDateRangeFilter({
52-
startDate: dateRangeValue.startDate,
53-
endDate: dateRangeValue.endDate,
54-
now,
55-
isToday,
56-
}),
70+
...getDateRangeFilter(dateRange),
5771
};
5872
const insightsFilter = { ...commonFilters, interval };
5973
const { data: templateInsights } = useQuery({
@@ -73,8 +87,25 @@ export default function TemplateInsightsPage() {
7387
<TemplateInsightsPageView
7488
controls={
7589
<>
76-
<IntervalMenu value={interval} onChange={setInterval} />
77-
<DateRange value={dateRangeValue} onChange={setDateRangeValue} />
90+
<IntervalMenu
91+
value={interval}
92+
onChange={(interval) => {
93+
setInterval(interval);
94+
if (interval === "week") {
95+
setWeeklyPreset(defaultWeeklyPreset);
96+
} else {
97+
setDateRangeValue(defaultDateRangeValue);
98+
}
99+
}}
100+
/>
101+
{interval === "day" ? (
102+
<DateRange value={dateRangeValue} onChange={setDateRangeValue} />
103+
) : (
104+
<WeeklyPresetsMenu
105+
value={weeklyPreset}
106+
onChange={setWeeklyPreset}
107+
/>
108+
)}
78109
</>
79110
}
80111
templateInsights={templateInsights}
@@ -598,6 +629,13 @@ const TextValue = ({ children }: { children: ReactNode }) => {
598629
);
599630
};
600631

632+
const getWeeklyRange = (numberOfWeeks: WeeklyPreset) => {
633+
const now = new Date();
634+
const startDate = startOfWeek(subWeeks(now, numberOfWeeks));
635+
const endDate = isSunday(now) ? endOfDay(now) : endOfWeek(subWeeks(now, 1));
636+
return { startDate, endDate };
637+
};
638+
601639
function mapToDAUsResponse(
602640
data: TemplateInsightsResponse["interval_reports"],
603641
): DAUsResponse {
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import CheckOutlined from "@mui/icons-material/CheckOutlined";
2+
import ExpandMoreOutlined from "@mui/icons-material/ExpandMoreOutlined";
3+
import Box from "@mui/material/Box";
4+
import Button from "@mui/material/Button";
5+
import Menu from "@mui/material/Menu";
6+
import MenuItem from "@mui/material/MenuItem";
7+
import { useState, useRef } from "react";
8+
9+
export const weeklyPresets = [4, 12, 24, 48] as const;
10+
11+
export type WeeklyPreset = (typeof weeklyPresets)[number];
12+
13+
export const WeeklyPresetsMenu = ({
14+
value,
15+
onChange,
16+
}: {
17+
value: WeeklyPreset;
18+
onChange: (value: WeeklyPreset) => void;
19+
}) => {
20+
const anchorRef = useRef<HTMLButtonElement>(null);
21+
const [open, setOpen] = useState(false);
22+
23+
const handleClose = () => {
24+
setOpen(false);
25+
};
26+
27+
return (
28+
<div>
29+
<Button
30+
ref={anchorRef}
31+
id="interval-button"
32+
aria-controls={open ? "interval-menu" : undefined}
33+
aria-haspopup="true"
34+
aria-expanded={open ? "true" : undefined}
35+
onClick={() => setOpen(true)}
36+
endIcon={<ExpandMoreOutlined />}
37+
>
38+
{value} weeks ago
39+
</Button>
40+
<Menu
41+
id="interval-menu"
42+
anchorEl={anchorRef.current}
43+
open={open}
44+
onClose={handleClose}
45+
MenuListProps={{
46+
"aria-labelledby": "interval-button",
47+
}}
48+
anchorOrigin={{
49+
vertical: "bottom",
50+
horizontal: "left",
51+
}}
52+
transformOrigin={{
53+
vertical: "top",
54+
horizontal: "left",
55+
}}
56+
>
57+
{weeklyPresets.map((numberOfWeeks) => {
58+
return (
59+
<MenuItem
60+
css={{ fontSize: 14, justifyContent: "space-between" }}
61+
key={numberOfWeeks}
62+
onClick={() => {
63+
onChange(numberOfWeeks);
64+
handleClose();
65+
}}
66+
>
67+
{numberOfWeeks} weeks ago
68+
<Box css={{ width: 16, height: 16 }}>
69+
{value === numberOfWeeks && (
70+
<CheckOutlined css={{ width: 16, height: 16 }} />
71+
)}
72+
</Box>
73+
</MenuItem>
74+
);
75+
})}
76+
</Menu>
77+
</div>
78+
);
79+
};

site/src/pages/TemplatePage/TemplateInsightsPage/utils.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1-
import { addDays, addHours, format, startOfDay, startOfHour } from "date-fns";
1+
import {
2+
addDays,
3+
addHours,
4+
format,
5+
startOfDay,
6+
startOfHour,
7+
isToday as isTodayDefault,
8+
} from "date-fns";
29

310
export function getDateRangeFilter({
411
startDate,
512
endDate,
6-
now,
7-
isToday,
13+
now = new Date(),
14+
isToday = isTodayDefault,
815
}: {
916
startDate: Date;
1017
endDate: Date;
11-
now: Date;
12-
isToday: (date: Date) => boolean;
18+
now?: Date;
19+
isToday?: (date: Date) => boolean;
1320
}) {
1421
return {
1522
start_time: toISOLocal(startOfDay(startDate)),

0 commit comments

Comments
 (0)