Skip to content

Commit 0fd4f70

Browse files
committed
Add Date Range Selector for Connect Analaytics
1 parent ec53366 commit 0fd4f70

File tree

1 file changed

+137
-18
lines changed

1 file changed

+137
-18
lines changed
Lines changed: 137 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,161 @@
11
"use client";
2+
import { DatePickerWithRange } from "@/components/ui/DatePickerWithRange";
3+
import {
4+
Select,
5+
SelectContent,
6+
SelectItem,
7+
SelectTrigger,
8+
SelectValue,
9+
} from "@/components/ui/select";
210
import {
311
useWalletUsageAggregate,
412
useWalletUsagePeriod,
513
} from "@3rdweb-sdk/react/hooks/useApi";
6-
import { useMemo } from "react";
14+
import { format } from "date-fns";
15+
import { useState } from "react";
716
import { ConnectAnalyticsDashboardUI } from "./ConnectAnalyticsDashboardUI";
817

918
export function ConnectAnalyticsDashboard(props: {
1019
clientId: string;
1120
}) {
12-
const allTimeFrom = useMemo(
13-
() => new Date(Date.now() - 135 * 24 * 60 * 60 * 1000),
14-
[],
15-
);
16-
const from = useMemo(
17-
() => new Date(Date.now() - 135 * 24 * 60 * 60 * 1000),
18-
[],
21+
const [range, setRange] = useState<Range>(() =>
22+
getLastNDaysRange("last-120"),
1923
);
20-
const to = useMemo(() => new Date(), []);
24+
2125
const walletUsageQuery = useWalletUsagePeriod({
2226
clientId: props.clientId,
23-
from,
24-
to,
27+
from: range.from,
28+
to: range.to,
2529
period: "day",
2630
});
31+
2732
const walletUsageAggregateQuery = useWalletUsageAggregate({
2833
clientId: props.clientId,
29-
from: allTimeFrom,
30-
to,
34+
from: range.from,
35+
to: range.to,
3136
});
3237

3338
return (
34-
<ConnectAnalyticsDashboardUI
35-
walletUsage={walletUsageQuery.data || []}
36-
aggregateWalletUsage={walletUsageAggregateQuery.data || []}
37-
isPending={
38-
walletUsageQuery.isPending || walletUsageAggregateQuery.isPending
39+
<div>
40+
<Filters range={range} setRange={setRange} />
41+
<div className="h-2" />
42+
<ConnectAnalyticsDashboardUI
43+
walletUsage={walletUsageQuery.data || []}
44+
aggregateWalletUsage={walletUsageAggregateQuery.data || []}
45+
isPending={
46+
walletUsageQuery.isPending || walletUsageAggregateQuery.isPending
47+
}
48+
/>
49+
</div>
50+
);
51+
}
52+
53+
const durationPresets = [
54+
{
55+
name: "Last 7 Days",
56+
id: "last-7",
57+
days: 7,
58+
},
59+
{
60+
name: "Last 30 Days",
61+
id: "last-30",
62+
days: 30,
63+
},
64+
{
65+
name: "Last 60 Days",
66+
id: "last-60",
67+
days: 60,
68+
},
69+
{
70+
name: "Last 120 Days",
71+
id: "last-120",
72+
days: 120,
73+
},
74+
] as const;
75+
76+
type DurationId = (typeof durationPresets)[number]["id"];
77+
78+
type Range = {
79+
type: DurationId | "custom";
80+
label?: string;
81+
from: Date;
82+
to: Date;
83+
};
84+
85+
function getLastNDaysRange(id: DurationId) {
86+
const todayDate = new Date();
87+
const pastDate = new Date(todayDate);
88+
89+
const durationInfo = durationPresets.find((preset) => preset.id === id);
90+
if (!durationInfo) {
91+
throw new Error("Invalid duration id");
92+
}
93+
94+
pastDate.setDate(todayDate.getDate() - durationInfo.days);
95+
96+
const value: Range = {
97+
type: id,
98+
from: pastDate,
99+
to: todayDate,
100+
label: durationInfo.name,
101+
};
102+
103+
return value;
104+
}
105+
106+
function Filters(props: { range: Range; setRange: (range: Range) => void }) {
107+
const { range, setRange } = props;
108+
109+
const presets = (
110+
<div className="mb-2 border-border border-b p-4">
111+
<Select
112+
value={range.type}
113+
onValueChange={(id: DurationId) => {
114+
setRange(getLastNDaysRange(id));
115+
}}
116+
>
117+
<SelectTrigger className="flex bg-transparent">
118+
<SelectValue placeholder="Select" />
119+
</SelectTrigger>
120+
<SelectContent position="popper">
121+
{durationPresets.map((preset) => (
122+
<SelectItem key={preset.id} value={preset.id}>
123+
{preset.name}
124+
</SelectItem>
125+
))}
126+
127+
{range.type === "custom" && (
128+
<SelectItem value="custom">
129+
{format(range.from, "LLL dd, y")} -{" "}
130+
{format(range.to, "LLL dd, y")}
131+
</SelectItem>
132+
)}
133+
</SelectContent>
134+
</Select>
135+
</div>
136+
);
137+
138+
return (
139+
<DatePickerWithRange
140+
from={range.from}
141+
to={range.to}
142+
setFrom={(from) =>
143+
setRange({
144+
from,
145+
to: range.to,
146+
type: "custom",
147+
})
148+
}
149+
setTo={(to) =>
150+
setRange({
151+
from: range.from,
152+
to,
153+
type: "custom",
154+
})
39155
}
156+
header={presets}
157+
labelOverride={range.label}
158+
className="w-auto border-none p-0"
40159
/>
41160
);
42161
}

0 commit comments

Comments
 (0)