Skip to content

Commit bd7fbd6

Browse files
authored
Merge pull request #254 from rybbit-io/time-format
Improving date and time formatting in the app, with attention to localization, user preferences, and code clarity
2 parents 99d612e + 5d3f7b6 commit bd7fbd6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+330
-250
lines changed

client/src/api/analytics/useGetEvents.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Time } from "../../components/DateSelector/types";
33
import { BACKEND_URL } from "../../lib/const";
44
import { useStore } from "../../lib/store";
55
import { authedFetchWithError, buildUrl, getStartAndEndDate } from "../utils";
6+
import { timeZone } from "../../lib/dateTimeUtils";
67

78
export type Event = {
89
timestamp: string;
@@ -57,7 +58,6 @@ export function useGetEventsInfinite(options: GetEventsOptions = {}) {
5758
const { startDate, endDate } = options.time
5859
? getStartAndEndDate(options.time)
5960
: getStartAndEndDate(time);
60-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
6161
const pageSize = options.pageSize || 20;
6262

6363
return useInfiniteQuery<EventsResponse, Error>({
@@ -66,7 +66,7 @@ export function useGetEventsInfinite(options: GetEventsOptions = {}) {
6666
site,
6767
startDate,
6868
endDate,
69-
timezone,
69+
timeZone,
7070
filters,
7171
pageSize,
7272
options.isRealtime,
@@ -76,7 +76,7 @@ export function useGetEventsInfinite(options: GetEventsOptions = {}) {
7676
const params: Record<string, any> = {
7777
startDate,
7878
endDate,
79-
timezone,
79+
timeZone,
8080
page: pageParam,
8181
pageSize,
8282
};

client/src/api/analytics/useGetFunnel.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
22
import { BACKEND_URL } from "../../lib/const";
33
import { authedFetch, authedFetchWithError } from "../utils";
44
import { useStore, Filter } from "../../lib/store";
5+
import { timeZone } from "../../lib/dateTimeUtils";
56
import { useDebounce } from "@uidotdev/usehooks";
67

78
export type FunnelStep = {
@@ -62,11 +63,10 @@ export function useGetFunnel(config?: FunnelRequest, debounce?: boolean) {
6263
throw new Error("Funnel configuration is required");
6364
}
6465

65-
// Add timezone to the request
66-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
66+
// Add time zone to the request
6767
const fullConfig = {
6868
...configToUse,
69-
timezone,
69+
timeZone,
7070
};
7171
try {
7272
const response = await authedFetchWithError<{ data: FunnelResponse[] }>(
@@ -102,11 +102,10 @@ export function useSaveFunnel() {
102102
SaveFunnelRequest
103103
>({
104104
mutationFn: async (funnelConfig) => {
105-
// Add timezone to the request
106-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
105+
// Add time zone to the request
107106
const fullConfig = {
108107
...funnelConfig,
109-
timezone,
108+
timeZone,
110109
};
111110

112111
try {

client/src/api/analytics/useGetGoal.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useQuery } from "@tanstack/react-query";
22
import { BACKEND_URL } from "../../lib/const";
3+
import { timeZone } from "../../lib/dateTimeUtils";
34
import { authedFetch } from "../utils";
45
import { useStore, Filter } from "../../lib/store";
56
import { Goal } from "./useGetGoals";
@@ -22,15 +23,14 @@ export function useGetGoal({
2223
enabled?: boolean;
2324
}) {
2425
const { site } = useStore();
25-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
2626

2727
return useQuery({
28-
queryKey: ["goal", site, goalId, startDate, endDate, timezone, filters],
28+
queryKey: ["goal", site, goalId, startDate, endDate, timeZone, filters],
2929
queryFn: async () => {
3030
return authedFetch(`${BACKEND_URL}/goal/${goalId}/${site}`, {
3131
startDate,
3232
endDate,
33-
timezone,
33+
timeZone,
3434
filters,
3535
}).then((res) => res.json());
3636
},

client/src/api/analytics/useGetGoals.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useQuery } from "@tanstack/react-query";
22
import { BACKEND_URL } from "../../lib/const";
3+
import { timeZone } from "../../lib/dateTimeUtils";
34
import {
45
getFilteredFilters,
56
GOALS_PAGE_FILTERS,
@@ -56,23 +57,22 @@ export function useGetGoals({
5657
minutes?: number;
5758
}) {
5859
const { site, time } = useStore();
59-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
6060
const filteredFilters = getFilteredFilters(GOALS_PAGE_FILTERS);
6161

6262
// If startDate and endDate are not provided, use time from store
6363
let timeParams: Record<string, string> = {};
6464

6565
if (minutes) {
6666
// If minutes is explicitly provided, use it
67-
timeParams = { minutes: minutes.toString(), timezone };
67+
timeParams = { minutes: minutes.toString(), timeZone };
6868
} else if (!startDate || !endDate) {
6969
// Otherwise get time parameters from the store's time
7070
// This will handle last-24-hours mode automatically
7171
const queryParams = getQueryTimeParams(time);
7272
timeParams = Object.fromEntries(new URLSearchParams(queryParams));
7373
} else {
7474
// Use explicitly provided dates if available
75-
timeParams = { startDate, endDate, timezone };
75+
timeParams = { startDate, endDate, timeZone };
7676
}
7777

7878
return useQuery({

client/src/api/analytics/useGetOverview.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useQuery } from "@tanstack/react-query";
22
import { useStore } from "../../lib/store";
33
import { authedFetch, getStartAndEndDate } from "../utils";
44
import { BACKEND_URL } from "../../lib/const";
5+
import { timeZone } from "../../lib/dateTimeUtils";
56

67
export type GetOverviewResponse = {
78
sessions: number;
@@ -28,11 +29,10 @@ export function useGetOverview({
2829
return useQuery({
2930
queryKey: ["overview", timeToUse, site, filters],
3031
queryFn: () => {
31-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
3232
return authedFetch(`${BACKEND_URL}/overview/${site}`, {
3333
startDate,
3434
endDate,
35-
timezone,
35+
timeZone,
3636
filters,
3737
}).then((res) => res.json());
3838
},
@@ -60,10 +60,9 @@ export function useGetOverviewPastMinutes({
6060
return useQuery({
6161
queryKey: ["overview-past-minutes", pastMinutes, site],
6262
queryFn: () => {
63-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
6463
return authedFetch(`${BACKEND_URL}/overview/${site}`, {
6564
pastMinutes,
66-
timezone,
65+
timeZone,
6766
}).then((res) => res.json());
6867
},
6968
staleTime: Infinity,

client/src/api/analytics/useGetOverviewBucketed.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
} from "@tanstack/react-query";
66
import { BACKEND_URL } from "../../lib/const";
77
import { TimeBucket, useStore } from "../../lib/store";
8+
import { timeZone } from "../../lib/dateTimeUtils";
89
import { APIResponse } from "../types";
910
import { authedFetch, getStartAndEndDate } from "../utils";
1011

@@ -40,11 +41,10 @@ export function useGetOverviewBucketed({
4041
return useQuery({
4142
queryKey: ["overview-bucketed", timeToUse, bucket, site, filters],
4243
queryFn: () => {
43-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
4444
return authedFetch(`${BACKEND_URL}/overview-bucketed/${site}`, {
4545
startDate,
4646
endDate,
47-
timezone,
47+
timeZone,
4848
bucket,
4949
filters,
5050
}).then((res) => res.json());
@@ -99,19 +99,18 @@ export function useGetOverviewBucketedPastMinutes({
9999
]
100100
: ["overview-bucketed-past-minutes", pastMinutes, site, bucket, filters],
101101
queryFn: () => {
102-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
103102
return authedFetch(
104103
`${BACKEND_URL}/overview-bucketed/${site}`,
105104
useRange
106105
? {
107-
timezone,
106+
timeZone,
108107
bucket,
109108
pastMinutesStart,
110109
pastMinutesEnd,
111110
filters,
112111
}
113112
: {
114-
timezone,
113+
timeZone,
115114
bucket,
116115
pastMinutes,
117116
filters,
@@ -167,9 +166,8 @@ export function useGetOverviewBucketedPreviousPastMinutes({
167166
filters,
168167
],
169168
queryFn: () => {
170-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
171169
return authedFetch(`${BACKEND_URL}/overview-bucketed/${site}`, {
172-
timezone,
170+
timeZone,
173171
bucket,
174172
pastMinutesStart,
175173
pastMinutesEnd,

client/src/api/analytics/useGetOverviewBucketedWithInView.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useQuery } from "@tanstack/react-query";
22
import { TimeBucket } from "../../lib/store";
33
import { BACKEND_URL } from "../../lib/const";
4+
import { timeZone } from "../../lib/dateTimeUtils";
45
import { authedFetch } from "../utils";
56
import { APIResponse } from "../types";
67
import { GetOverviewBucketedResponse } from "./useGetOverviewBucketed";
@@ -25,9 +26,8 @@ export function useGetOverviewBucketedWithInView({
2526
return useQuery<APIResponse<GetOverviewBucketedResponse>>({
2627
queryKey: ["overview-bucketed-past-minutes", pastMinutes, site, bucket],
2728
queryFn: () => {
28-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
2929
return authedFetch(`${BACKEND_URL}/overview-bucketed/${site}`, {
30-
timezone,
30+
timeZone,
3131
bucket,
3232
pastMinutes,
3333
}).then((res) => res.json());

client/src/api/analytics/useGetOverviewWithInView.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useGetOverviewPastMinutes } from "./useGetOverview";
22
import { useQuery } from "@tanstack/react-query";
33
import { BACKEND_URL } from "../../lib/const";
4+
import { timeZone } from "../../lib/dateTimeUtils";
45
import { authedFetch } from "../utils";
56

67
/**
@@ -20,10 +21,9 @@ export function useGetOverviewWithInView({
2021
return useQuery({
2122
queryKey: ["overview-past-minutes", pastMinutes, site],
2223
queryFn: () => {
23-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
2424
return authedFetch(`${BACKEND_URL}/overview/${site}`, {
2525
pastMinutes,
26-
timezone,
26+
timeZone,
2727
}).then((res) => res.json());
2828
},
2929
enabled: isInView, // Only fetch when in view

client/src/api/analytics/useJourneys.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Time } from "../../components/DateSelector/types";
66
export interface JourneyParams {
77
siteId?: number;
88
steps?: number;
9-
timezone?: string;
9+
timeZone?: string;
1010
time: Time;
1111
limit?: number;
1212
}
@@ -24,22 +24,22 @@ export interface JourneysResponse {
2424
export const useJourneys = ({
2525
siteId,
2626
steps = 3,
27-
timezone = "UTC",
27+
timeZone = "UTC",
2828
time,
2929
limit = 100,
3030
}: JourneyParams) => {
3131
const { startDate, endDate } = getStartAndEndDate(time);
3232

3333
return useQuery<JourneysResponse>({
34-
queryKey: ["journeys", siteId, steps, startDate, endDate, timezone, limit],
34+
queryKey: ["journeys", siteId, steps, startDate, endDate, timeZone, limit],
3535
queryFn: async () => {
3636
let url = `${BACKEND_URL}/journeys/${siteId}`;
3737
const params = new URLSearchParams();
3838

3939
if (steps) params.append("steps", steps.toString());
4040
if (startDate) params.append("startDate", startDate);
4141
if (endDate) params.append("endDate", endDate);
42-
if (timezone) params.append("timezone", timezone);
42+
if (timeZone) params.append("timeZone", timeZone);
4343
if (limit) params.append("limit", limit.toString());
4444

4545
const queryString = params.toString();

client/src/api/analytics/useSingleCol.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useQuery, UseQueryResult } from "@tanstack/react-query";
22
import { FilterParameter, useStore } from "../../lib/store";
3+
import { timeZone } from "../../lib/dateTimeUtils";
34
import { APIResponse } from "../types";
45
import { BACKEND_URL } from "../../lib/const";
56
import { getStartAndEndDate, authedFetch } from "../utils";
@@ -36,7 +37,7 @@ export function useSingleCol({
3637
const queryParams = isPast24HoursMode
3738
? {
3839
// Past minutes approach
39-
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
40+
timeZone: timeZone,
4041
parameter,
4142
limit,
4243
minutes: periodTime === "previous" ? 48 * 60 : 24 * 60,
@@ -45,7 +46,7 @@ export function useSingleCol({
4546
: {
4647
// Regular date-based approach
4748
...getStartAndEndDate(timeToUse),
48-
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
49+
timeZone: timeZone,
4950
parameter,
5051
limit,
5152
filters: useFilters ? filters : undefined,
@@ -97,9 +98,8 @@ export function useSingleColRealtime({
9798
return useQuery({
9899
queryKey: [parameter, site, limit, minutes, "realtime"],
99100
queryFn: () => {
100-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
101101
return authedFetch(`${BACKEND_URL}/single-col/${site}`, {
102-
timezone,
102+
timeZone,
103103
parameter,
104104
limit,
105105
minutes,

0 commit comments

Comments
 (0)