Skip to content

Commit fb4c190

Browse files
gregfromstlclaude
andauthored
[Dashboard] Feature: Default analytics range to 30 days and save preference (#7039)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1c31a1e commit fb4c190

File tree

6 files changed

+89
-9
lines changed

6 files changed

+89
-9
lines changed

apps/dashboard/src/@/components/blocks/SidebarLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ function RenderSidebarGroup(props: {
137137
}
138138

139139
if ("separator" in link) {
140-
return <SidebarSeparator className="my-1" />;
140+
return <SidebarSeparator key={Math.random()} className="my-1" />;
141141
}
142142

143143
return (

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/components/ProjectSidebarLayout.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,13 @@ export function ProjectSidebarLayout(props: {
5050
tracking: tracking("account-abstraction"),
5151
},
5252
{
53-
label: "Universal Bridge",
5453
href: `${layoutPath}/connect/universal-bridge`,
5554
icon: PayIcon,
55+
label: (
56+
<span className="flex items-center gap-2">
57+
Universal Bridge <Badge>New</Badge>
58+
</span>
59+
),
5660
tracking: tracking("universal-bridge"),
5761
},
5862
{

apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/connect/universal-bridge/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export default async function Page(props: {
3232
from: searchParams.from,
3333
to: searchParams.to,
3434
interval: searchParams.interval,
35+
defaultRange: "last-30",
3536
});
3637

3738
return (

apps/dashboard/src/components/analytics/date-range-selector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ export function DateRangeSelector(props: {
8080
export function getLastNDaysRange(id: DurationId) {
8181
const durationInfo = durationPresets.find((preset) => preset.id === id);
8282
if (!durationInfo) {
83-
throw new Error("Invalid duration id");
83+
throw new Error(`Invalid duration id: ${id}`);
8484
}
8585

8686
const todayDate = new Date(Date.now() + 1000 * 60 * 60 * 24); // add 1 day to avoid timezone issues

apps/dashboard/src/components/pay/PayAnalytics/components/PayAnalyticsFilter.tsx

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,121 @@
11
"use client";
22

33
import { normalizeTimeISOString } from "@/lib/time";
4-
import { DateRangeSelector } from "components/analytics/date-range-selector";
4+
import { useQuery } from "@tanstack/react-query";
5+
import {
6+
DateRangeSelector,
7+
type DurationId,
8+
} from "components/analytics/date-range-selector";
59
import { IntervalSelector } from "components/analytics/interval-selector";
610
import { getUniversalBridgeFiltersFromSearchParams } from "lib/time";
711
import {
812
useResponsiveSearchParams,
913
useSetResponsiveSearchParams,
1014
} from "responsive-rsc";
1115

16+
const STORAGE_KEY = "thirdweb:ub-analytics-range";
17+
18+
type SavedRange = {
19+
rangeType: string;
20+
interval: "day" | "week";
21+
};
22+
23+
type SearchParams = {
24+
from?: string;
25+
to?: string;
26+
interval?: "day" | "week";
27+
};
28+
1229
export function PayAnalyticsFilter() {
1330
const responsiveSearchParams = useResponsiveSearchParams();
1431
const setResponsiveSearchParams = useSetResponsiveSearchParams();
1532

33+
// Load saved range from localStorage using useQuery
34+
useQuery<SavedRange | null>({
35+
queryKey: [
36+
"savedRange",
37+
responsiveSearchParams.from,
38+
responsiveSearchParams.to,
39+
],
40+
queryFn: () => {
41+
const savedRangeString = localStorage.getItem(STORAGE_KEY);
42+
if (savedRangeString) {
43+
try {
44+
const savedRange = JSON.parse(savedRangeString) as SavedRange;
45+
// Get the current range based on the saved range type
46+
const { range } = getUniversalBridgeFiltersFromSearchParams({
47+
from: undefined,
48+
to: undefined,
49+
interval: savedRange.interval,
50+
defaultRange: (savedRange.rangeType || "last-30") as DurationId,
51+
});
52+
53+
setResponsiveSearchParams((v) => ({
54+
...v,
55+
from: normalizeTimeISOString(range.from),
56+
to: normalizeTimeISOString(range.to),
57+
interval: savedRange.interval,
58+
}));
59+
} catch (e) {
60+
localStorage.removeItem(STORAGE_KEY);
61+
console.error("Failed to parse saved range:", e);
62+
}
63+
}
64+
return null;
65+
},
66+
enabled: !responsiveSearchParams.from && !responsiveSearchParams.to,
67+
});
68+
1669
const { range, interval } = getUniversalBridgeFiltersFromSearchParams({
1770
from: responsiveSearchParams.from,
1871
to: responsiveSearchParams.to,
1972
interval: responsiveSearchParams.interval,
73+
defaultRange: "last-30",
2074
});
2175

76+
const saveToLocalStorage = (params: {
77+
rangeType: string;
78+
interval: "day" | "week";
79+
}) => {
80+
localStorage.setItem(STORAGE_KEY, JSON.stringify(params));
81+
};
82+
2283
return (
2384
<div className="no-scrollbar flex items-center gap-3 max-sm:overflow-auto">
2485
<DateRangeSelector
2586
range={range}
2687
popoverAlign="end"
2788
setRange={(newRange) => {
28-
setResponsiveSearchParams((v) => {
29-
return {
89+
setResponsiveSearchParams((v: SearchParams) => {
90+
const newParams = {
3091
...v,
3192
from: normalizeTimeISOString(newRange.from),
3293
to: normalizeTimeISOString(newRange.to),
3394
};
95+
// Save to localStorage
96+
saveToLocalStorage({
97+
rangeType: newRange.type || "last-30",
98+
interval: newParams.interval || "day",
99+
});
100+
return newParams;
34101
});
35102
}}
36103
/>
37104

38105
<IntervalSelector
39106
intervalType={interval}
40107
setIntervalType={(newInterval) => {
41-
setResponsiveSearchParams((v) => {
42-
return {
108+
setResponsiveSearchParams((v: SearchParams) => {
109+
const newParams = {
43110
...v,
44111
interval: newInterval,
45112
};
113+
// Save to localStorage
114+
saveToLocalStorage({
115+
rangeType: range.type || "last-30",
116+
interval: newInterval,
117+
});
118+
return newParams;
46119
});
47120
}}
48121
/>

apps/dashboard/src/lib/time.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { getFiltersFromSearchParams } from "@/lib/time";
2+
import type { DurationId } from "../components/analytics/date-range-selector";
23

34
export function getNebulaFiltersFromSearchParams(params: {
45
from: string | undefined | string[];
@@ -17,11 +18,12 @@ export function getUniversalBridgeFiltersFromSearchParams(params: {
1718
from: string | undefined | string[];
1819
to: string | undefined | string[];
1920
interval: string | undefined | string[];
21+
defaultRange: DurationId;
2022
}) {
2123
return getFiltersFromSearchParams({
2224
from: params.from,
2325
to: params.to,
2426
interval: params.interval,
25-
defaultRange: "last-120",
27+
defaultRange: params.defaultRange,
2628
});
2729
}

0 commit comments

Comments
 (0)