Refactor part 2: Electric Boogaloo. Standardize way of passing filter parameters.

This commit is contained in:
Mike Cao 2025-07-04 01:23:11 -07:00
parent f26f1b0581
commit cdf391d5c2
90 changed files with 867 additions and 709 deletions

View file

@ -1,14 +1,16 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { ReactQueryOptions } from '@/lib/types';
export function useEventDataEventsQuery(websiteId: string, options?: ReactQueryOptions<any>) {
const { get, useQuery } = useApi();
const params = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return useQuery({
queryKey: ['websites:event-data:events', { websiteId, ...params }],
queryFn: () => get(`/websites/${websiteId}/event-data/events`, { ...params }),
queryKey: ['websites:event-data:events', { websiteId, ...date, ...filters }],
queryFn: () => get(`/websites/${websiteId}/event-data/events`, { ...date, ...filters }),
enabled: !!websiteId,
...options,
});

View file

@ -1,14 +1,16 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { ReactQueryOptions } from '@/lib/types';
export function useEventDataPropertiesQuery(websiteId: string, options?: ReactQueryOptions<any>) {
const { get, useQuery } = useApi();
const params = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return useQuery<any>({
queryKey: ['websites:event-data:properties', { websiteId, ...params }],
queryFn: () => get(`/websites/${websiteId}/event-data/properties`, { ...params }),
queryKey: ['websites:event-data:properties', { websiteId, ...date, ...filters }],
queryFn: () => get(`/websites/${websiteId}/event-data/properties`, { ...date, ...filters }),
enabled: !!websiteId,
...options,
});

View file

@ -1,5 +1,6 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { ReactQueryOptions } from '@/lib/types';
export function useEventDataQuery(
@ -8,11 +9,12 @@ export function useEventDataQuery(
options?: ReactQueryOptions<any>,
) {
const { get, useQuery } = useApi();
const params = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const params = useFilterParameters();
return useQuery({
queryKey: ['websites:event-data', { websiteId, eventId, ...params }],
queryFn: () => get(`/websites/${websiteId}/event-data/${eventId}`, { ...params }),
queryKey: ['websites:event-data', { websiteId, eventId, ...date, ...params }],
queryFn: () => get(`/websites/${websiteId}/event-data/${eventId}`, { ...date, ...params }),
enabled: !!(websiteId && eventId),
...options,
});

View file

@ -1,5 +1,6 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { ReactQueryOptions } from '@/lib/types';
export function useEventDataValuesQuery(
@ -9,12 +10,21 @@ export function useEventDataValuesQuery(
options?: ReactQueryOptions<any>,
) {
const { get, useQuery } = useApi();
const params = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return useQuery<any>({
queryKey: ['websites:event-data:values', { websiteId, eventName, propertyName, ...params }],
queryKey: [
'websites:event-data:values',
{ websiteId, eventName, propertyName, ...date, ...filters },
],
queryFn: () =>
get(`/websites/${websiteId}/event-data/values`, { ...params, eventName, propertyName }),
get(`/websites/${websiteId}/event-data/values`, {
...date,
...filters,
eventName,
propertyName,
}),
enabled: !!(websiteId && propertyName),
...options,
});

View file

@ -1,15 +1,17 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { ReactQueryOptions } from '@/lib/types';
import { useDateParameters } from '@/components/hooks/useDateParameters';
export function useResultQuery<T = any>(
type: string,
params?: Record<string, any>,
options?: ReactQueryOptions<T>,
) {
const { websiteId } = params;
const { websiteId, ...parameters } = params;
const { post, useQuery } = useApi();
const filters = useFilterParams(websiteId);
const { startDate, endDate, timezone } = useDateParameters(websiteId);
const filters = useFilterParameters();
return useQuery<T>({
queryKey: [
@ -17,11 +19,25 @@ export function useResultQuery<T = any>(
{
type,
websiteId,
...filters,
startDate,
endDate,
timezone,
...params,
...filters,
},
],
queryFn: () => post(`/reports/${type}`, { type, filters, ...params }),
queryFn: () =>
post(`/reports/${type}`, {
websiteId,
type,
filters,
parameters: {
startDate,
endDate,
timezone,
...parameters,
},
}),
enabled: !!type,
...options,
});

View file

@ -1,14 +1,16 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { ReactQueryOptions } from '@/lib/types';
export function useSessionDataPropertiesQuery(websiteId: string, options?: ReactQueryOptions<any>) {
const { get, useQuery } = useApi();
const params = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return useQuery<any>({
queryKey: ['websites:session-data:properties', { websiteId, ...params }],
queryFn: () => get(`/websites/${websiteId}/session-data/properties`, { ...params }),
queryKey: ['websites:session-data:properties', { websiteId, ...date, ...filters }],
queryFn: () => get(`/websites/${websiteId}/session-data/properties`, { ...date, ...filters }),
enabled: !!websiteId,
...options,
});

View file

@ -1,5 +1,6 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { ReactQueryOptions } from '@/lib/types';
export function useSessionDataValuesQuery(
@ -8,11 +9,13 @@ export function useSessionDataValuesQuery(
options?: ReactQueryOptions<any>,
) {
const { get, useQuery } = useApi();
const params = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return useQuery<any>({
queryKey: ['websites:session-data:values', { websiteId, propertyName, ...params }],
queryFn: () => get(`/websites/${websiteId}/session-data/values`, { ...params, propertyName }),
queryKey: ['websites:session-data:values', { websiteId, propertyName, ...date, ...filters }],
queryFn: () =>
get(`/websites/${websiteId}/session-data/values`, { ...date, ...filters, propertyName }),
enabled: !!(websiteId && propertyName),
...options,
});

View file

@ -1,15 +1,17 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { usePagedQuery } from '../usePagedQuery';
import { ReactQueryOptions } from '@/lib/types';
export function useWebsiteEventsQuery(websiteId: string, options?: ReactQueryOptions<any>) {
const { get } = useApi();
const queryParams = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return usePagedQuery({
queryKey: ['websites:events', { websiteId, ...queryParams }],
queryFn: () => get(`/websites/${websiteId}/events`, { ...queryParams, pageSize: 20 }),
queryKey: ['websites:events', { websiteId, ...date, ...filters }],
queryFn: () => get(`/websites/${websiteId}/events`, { ...date, ...filters, pageSize: 20 }),
enabled: !!websiteId,
...options,
});

View file

@ -1,14 +1,16 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { ReactQueryOptions } from '@/lib/types';
export function useWebsiteEventsSeriesQuery(websiteId: string, options?: ReactQueryOptions<any>) {
const { get, useQuery } = useApi();
const params = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return useQuery({
queryKey: ['websites:events:series', { websiteId, ...params }],
queryFn: () => get(`/websites/${websiteId}/events/series`, { ...params }),
queryKey: ['websites:events:series', { websiteId, ...date, ...filters }],
queryFn: () => get(`/websites/${websiteId}/events/series`, { ...date, ...filters }),
enabled: !!websiteId,
...options,
});

View file

@ -1,6 +1,7 @@
import { keepPreviousData } from '@tanstack/react-query';
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { useSearchParams } from 'next/navigation';
import { ReactQueryOptions } from '@/lib/types';
@ -11,11 +12,12 @@ export type WebsiteMetricsData = {
export function useWebsiteMetricsQuery(
websiteId: string,
params: { type: string; limit?: number; search?: string; startAt?: number; endAt?: number },
params: { type: string; limit?: number; search?: string },
options?: ReactQueryOptions<WebsiteMetricsData>,
) {
const { get, useQuery } = useApi();
const queryParams = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
const searchParams = useSearchParams();
return useQuery<WebsiteMetricsData>({
@ -23,13 +25,15 @@ export function useWebsiteMetricsQuery(
'websites:metrics',
{
websiteId,
...queryParams,
...date,
...filters,
...params,
},
],
queryFn: async () =>
get(`/websites/${websiteId}/metrics`, {
...queryParams,
...date,
...filters,
[searchParams.get('view')]: undefined,
...params,
}),

View file

@ -1,5 +1,6 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
import { ReactQueryOptions } from '@/lib/types';
export interface WebsitePageviewsData {
@ -12,11 +13,12 @@ export function useWebsitePageviewsQuery(
options?: ReactQueryOptions<WebsitePageviewsData>,
) {
const { get, useQuery } = useApi();
const queryParams = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const queryParams = useFilterParameters();
return useQuery<WebsitePageviewsData>({
queryKey: ['websites:pageviews', { websiteId, compare, ...queryParams }],
queryFn: () => get(`/websites/${websiteId}/pageviews`, { compare, ...queryParams }),
queryKey: ['websites:pageviews', { websiteId, compare, ...date, ...queryParams }],
queryFn: () => get(`/websites/${websiteId}/pageviews`, { compare, ...date, ...queryParams }),
enabled: !!websiteId,
...options,
});

View file

@ -1,13 +1,15 @@
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
export function useWebsiteSessionStatsQuery(websiteId: string, options?: Record<string, string>) {
const { get, useQuery } = useApi();
const params = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return useQuery({
queryKey: ['sessions:stats', { websiteId, ...params }],
queryFn: () => get(`/websites/${websiteId}/sessions/stats`, { ...params }),
queryKey: ['sessions:stats', { websiteId, ...date, ...filters }],
queryFn: () => get(`/websites/${websiteId}/sessions/stats`, { ...date, ...filters }),
enabled: !!websiteId,
...options,
});

View file

@ -1,7 +1,8 @@
import { useApi } from '../useApi';
import { usePagedQuery } from '../usePagedQuery';
import { useModified } from '../useModified';
import { useFilterParams } from '@/components/hooks/useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '../useDateParameters';
export function useWebsiteSessionsQuery(
websiteId: string,
@ -9,14 +10,16 @@ export function useWebsiteSessionsQuery(
) {
const { get } = useApi();
const { modified } = useModified(`sessions`);
const filters = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return usePagedQuery({
queryKey: ['sessions', { websiteId, modified, ...params, ...filters }],
queryKey: ['sessions', { websiteId, modified, ...params, ...date, ...filters }],
queryFn: () => {
return get(`/websites/${websiteId}/sessions`, {
...params,
...filters,
...date,
pageSize: 20,
});
},

View file

@ -1,6 +1,7 @@
import { useApi } from '../useApi';
import { useModified } from '../useModified';
import { useFilterParams } from '@/components/hooks/useFilterParams';
import { useDateParameters } from '../useDateParameters';
import { useFilterParameters } from '@/components/hooks/useFilterParameters';
export function useWebsiteSessionsWeeklyQuery(
websiteId: string,
@ -8,13 +9,15 @@ export function useWebsiteSessionsWeeklyQuery(
) {
const { get, useQuery } = useApi();
const { modified } = useModified(`sessions`);
const filters = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return useQuery({
queryKey: ['sessions', { websiteId, modified, ...params, ...filters }],
queryKey: ['sessions', { websiteId, modified, ...params, ...date, ...filters }],
queryFn: () => {
return get(`/websites/${websiteId}/sessions/weekly`, {
...params,
...date,
...filters,
});
},

View file

@ -1,6 +1,7 @@
import { UseQueryOptions } from '@tanstack/react-query';
import { useApi } from '../useApi';
import { useFilterParams } from '../useFilterParams';
import { useFilterParameters } from '../useFilterParameters';
import { useDateParameters } from '@/components/hooks/useDateParameters';
export interface WebsiteStatsData {
pageviews: number;
@ -8,7 +9,7 @@ export interface WebsiteStatsData {
visits: number;
bounces: number;
totaltime: number;
previous: {
comparison: {
pageviews: number;
visitors: number;
visits: number;
@ -22,11 +23,12 @@ export function useWebsiteStatsQuery(
options?: UseQueryOptions<WebsiteStatsData, Error, WebsiteStatsData>,
) {
const { get, useQuery } = useApi();
const filterParams = useFilterParams(websiteId);
const date = useDateParameters(websiteId);
const filters = useFilterParameters();
return useQuery<WebsiteStatsData>({
queryKey: ['websites:stats', { websiteId, ...filterParams }],
queryFn: () => get(`/websites/${websiteId}/stats`, { ...filterParams }),
queryKey: ['websites:stats', { websiteId, ...date, ...filters }],
queryFn: () => get(`/websites/${websiteId}/stats`, { ...date, ...filters }),
enabled: !!websiteId,
...options,
});

View file

@ -0,0 +1,16 @@
import { useMemo } from 'react';
import { useNavigation } from './useNavigation';
export function usePageParameters() {
const {
query: { page, pageSize, search },
} = useNavigation();
return useMemo(() => {
return {
page,
pageSize,
search,
};
}, [page, pageSize, search]);
}

View file

@ -0,0 +1,18 @@
import { useDateRange } from './useDateRange';
import { useTimezone } from './useTimezone';
export function useDateParameters(websiteId: string) {
const {
dateRange: { startDate, endDate, unit },
} = useDateRange(websiteId);
const { timezone, toUtc } = useTimezone();
return {
startAt: +toUtc(startDate),
endAt: +toUtc(endDate),
startDate: toUtc(startDate).toISOString(),
endDate: toUtc(endDate).toISOString(),
unit,
timezone,
};
}

View file

@ -8,7 +8,11 @@ import { useApi } from './useApi';
import { useNavigation } from './useNavigation';
import { useMemo } from 'react';
export function useDateRange(websiteId?: string) {
export interface UseDateRangeOptions {
ignoreOffset?: boolean;
}
export function useDateRange(websiteId?: string, options: UseDateRangeOptions = {}) {
const { get } = useApi();
const { locale } = useLocale();
const {
@ -16,14 +20,16 @@ export function useDateRange(websiteId?: string) {
} = useNavigation();
const websiteConfig = useWebsites(state => state[websiteId]?.dateRange);
const globalConfig = useApp(state => state.dateRangeValue);
const dateRangeObject = parseDateRange(
date || websiteConfig?.value || globalConfig || DEFAULT_DATE_RANGE_VALUE,
locale,
);
const dateRange = useMemo(
() => (offset ? getOffsetDateRange(dateRangeObject, +offset) : dateRangeObject),
[date, offset, websiteConfig],
);
const dateValue = date || websiteConfig?.value || globalConfig || DEFAULT_DATE_RANGE_VALUE;
const dateRange = useMemo(() => {
const dateRangeObject = parseDateRange(dateValue, locale);
return !options.ignoreOffset && offset
? getOffsetDateRange(dateRangeObject, +offset)
: dateRangeObject;
}, [date, offset, dateValue, options]);
const dateCompare = useWebsites(state => state[websiteId]?.dateCompare || DEFAULT_DATE_COMPARE);
const saveDateRange = async (value: string) => {

View file

@ -1,11 +1,7 @@
import { useMemo } from 'react';
import { useNavigation } from './useNavigation';
import { useDateRange } from './useDateRange';
import { useTimezone } from './useTimezone';
export function useFilterParams(websiteId: string) {
const { dateRange } = useDateRange(websiteId);
const { startDate, endDate, unit } = dateRange;
const { timezone, toUtc } = useTimezone();
export function useFilterParameters() {
const {
query: {
path,
@ -28,13 +24,25 @@ export function useFilterParams(websiteId: string) {
},
} = useNavigation();
return {
// Date range
startAt: +toUtc(startDate),
endAt: +toUtc(endDate),
unit,
timezone,
// Filters
return useMemo(() => {
return {
path,
referrer,
title,
query,
host,
os,
browser,
device,
country,
region,
city,
event,
tag,
hostname,
search,
};
}, [
path,
referrer,
title,
@ -49,9 +57,8 @@ export function useFilterParams(websiteId: string) {
event,
tag,
hostname,
// Paging
page,
pageSize,
search,
};
]);
}