Separated query string date handling. Fixed all time date.

This commit is contained in:
Mike Cao 2025-10-03 01:19:35 -07:00
parent 1def80ba42
commit b36cd48b4a
7 changed files with 86 additions and 66 deletions

View file

@ -1,21 +1,24 @@
import { useState } from 'react';
import { DateFilter } from '@/components/input/DateFilter';
import { Button, Row } from '@umami/react-zen';
import { useDateRange, useMessages } from '@/components/hooks';
import { DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
import { useMessages } from '@/components/hooks';
import { DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
import { setItem, getItem } from '@/lib/storage';
export function DateRangeSetting() {
const { formatMessage, labels } = useMessages();
const { dateRange, saveDateRange } = useDateRange();
const { value } = dateRange;
const [date, setDate] = useState(getItem(DATE_RANGE_CONFIG) || DEFAULT_DATE_RANGE_VALUE);
const handleChange = (value: string) => {
saveDateRange(value);
setItem(DATE_RANGE_CONFIG, value);
setDate(value);
};
const handleReset = () => saveDateRange(DEFAULT_DATE_RANGE_VALUE);
const handleReset = () => setItem(DATE_RANGE_CONFIG, DEFAULT_DATE_RANGE_VALUE);
return (
<Row gap="3">
<DateFilter value={value} onChange={handleChange} placement="bottom start" />
<DateFilter value={date} onChange={handleChange} placement="bottom start" />
<Button onPress={handleReset}>{formatMessage(labels.reset)}</Button>
</Row>
);

View file

@ -15,7 +15,7 @@ export function WebsiteChart({
const { startDate, endDate, unit, value } = dateRange;
const { data, isLoading, isFetching, error } = useWebsitePageviewsQuery({
websiteId,
compare: compareMode ? dateCompare : undefined,
compare: compareMode ? dateCompare?.['value'] : undefined,
});
const { pageviews, sessions, compare } = (data || {}) as any;

View file

@ -9,6 +9,7 @@ export * from './context/useWebsite';
// Query hooks
export * from './queries/useActiveUsersQuery';
export * from './queries/useDateRangeQuery';
export * from './queries/useDeleteQuery';
export * from './queries/useEventDataEventsQuery';
export * from './queries/useEventDataPropertiesQuery';
@ -76,6 +77,7 @@ export * from './useModified';
export * from './useNavigation';
export * from './usePagedQuery';
export * from './usePageParameters';
export * from './useQueryStringDate';
export * from './useRegionNames';
export * from './useSlug';
export * from './useSticky';

View file

@ -0,0 +1,12 @@
import { useApi } from '../useApi';
import { ReactQueryOptions } from '@/lib/types';
export function useDateRangeQuery(websiteId: string, options?: ReactQueryOptions) {
const { get, useQuery } = useApi();
return useQuery<any>({
queryKey: ['date-range', websiteId],
queryFn: () => get(`/websites/${websiteId}/daterange`),
enabled: !!websiteId,
...options,
});
}

View file

@ -1,65 +1,35 @@
import { useMemo } from 'react';
import { getMinimumUnit, parseDateRange, getOffsetDateRange } from '@/lib/date';
import { setItem } from '@/lib/storage';
import { DATE_RANGE_CONFIG, DEFAULT_DATE_COMPARE, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
import { setWebsiteDateCompare, setWebsiteDateRange, useWebsites } from '@/store/websites';
import { setDateRangeValue, useApp } from '@/store/app';
import { useLocale } from './useLocale';
import { useApi } from './useApi';
import { useNavigation } from './useNavigation';
import { getMinimumUnit, parseDateRange } from '@/lib/date';
import { useLocale } from '@/components/hooks/useLocale';
import { useApi } from '@/components/hooks//useApi';
import { useQueryStringDate } from '@/components/hooks/useQueryStringDate';
import { useGlobalState } from '@/components/hooks/useGlobalState';
export interface UseDateRangeOptions {
ignoreOffset?: boolean;
}
export function useDateRange(websiteId?: string, options: UseDateRangeOptions = {}) {
export function useDateRange(websiteId: string) {
const { get } = useApi();
const { locale } = useLocale();
const {
query: { date, offset = 0 },
} = useNavigation();
const websiteConfig = useWebsites(state => state[websiteId]?.dateRange);
const globalConfig = useApp(state => state.dateRangeValue);
const dateValue = websiteConfig?.value || date || globalConfig || DEFAULT_DATE_RANGE_VALUE;
const { dateRange: defaultDateRange, dateCompare } = useQueryStringDate();
const dateRange = useMemo(() => {
const dateRangeObject = parseDateRange(dateValue, locale);
const [dateRange, setDateRange] = useGlobalState(`date-range:${websiteId}`, defaultDateRange);
return !options.ignoreOffset && offset
? getOffsetDateRange(dateRangeObject, +offset)
: dateRangeObject;
}, [date, offset, dateValue, options]);
const setDateRangeValue = async (value: string) => {
if (value === 'all') {
const result = await get(`/websites/${websiteId}/daterange`);
const { mindate, maxdate } = result;
const dateCompare = useWebsites(state => state[websiteId]?.dateCompare || DEFAULT_DATE_COMPARE);
const startDate = new Date(mindate);
const endDate = new Date(maxdate);
const unit = getMinimumUnit(startDate, endDate);
const saveDateRange = async (value: string) => {
if (websiteId) {
if (value === 'all') {
const result: any = await get(`/websites/${websiteId}/daterange`);
const { mindate, maxdate } = result;
const startDate = new Date(mindate);
const endDate = new Date(maxdate);
const unit = getMinimumUnit(startDate, endDate);
setWebsiteDateRange(websiteId, {
startDate,
endDate,
unit,
value,
});
} else {
setWebsiteDateRange(websiteId, parseDateRange(value, locale));
}
setDateRange({
startDate,
endDate,
unit,
value,
});
} else {
setItem(DATE_RANGE_CONFIG, value);
setDateRangeValue(value);
setDateRange(parseDateRange(value, locale));
}
};
const saveDateCompare = (value: string) => {
setWebsiteDateCompare(websiteId, value);
};
return { dateRange, saveDateRange, dateCompare, saveDateCompare };
return { dateRange, dateCompare, setDateRange, setDateRangeValue };
}

View file

@ -0,0 +1,24 @@
import { useNavigation } from '@/components/hooks/useNavigation';
import { useMemo } from 'react';
import { getCompareDate, getOffsetDateRange, parseDateRange } from '@/lib/date';
import { useLocale } from '@/components/hooks/useLocale';
import { DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
export function useQueryStringDate(options: { ignoreOffset?: boolean } = {}) {
const {
query: { date = DEFAULT_DATE_RANGE_VALUE, offset = 0, compare = 'prev' },
} = useNavigation();
const { locale } = useLocale();
const dateRange = useMemo(() => {
const dateRangeObject = parseDateRange(date, locale);
return !options.ignoreOffset && offset
? getOffsetDateRange(dateRangeObject, +offset)
: dateRangeObject;
}, [date, offset, options]);
const dateCompare = getCompareDate(compare, dateRange.startDate, dateRange.endDate);
return { date, offset, dateRange, dateCompare };
}

View file

@ -3,6 +3,8 @@ import { isAfter } from 'date-fns';
import { ChevronRight } from '@/components/icons';
import { useDateRange, useMessages, useNavigation } from '@/components/hooks';
import { DateFilter } from './DateFilter';
import { getOffsetDateRange } from '@/lib/date';
import { useCallback } from 'react';
export interface WebsiteDateFilterProps {
websiteId: string;
@ -18,7 +20,7 @@ export function WebsiteDateFilter({
showButtons = true,
allowCompare,
}: WebsiteDateFilterProps) {
const { dateRange, saveDateRange } = useDateRange(websiteId);
const { dateRange, setDateRange, setDateRangeValue } = useDateRange(websiteId);
const { value, endDate } = dateRange;
const { formatMessage, labels } = useMessages();
const {
@ -27,18 +29,25 @@ export function WebsiteDateFilter({
query: { compare = 'prev', offset = 0 },
} = useNavigation();
const isAllTime = value === 'all';
const isCustomRange = value.startsWith('range');
const disableForward = value === 'all' || isAfter(endDate, new Date());
const handleChange = (date: string) => {
saveDateRange(date);
setDateRangeValue(date);
router.push(updateParams({ date, offset: undefined }));
};
const handleIncrement = (increment: number) => {
router.push(updateParams({ offset: +offset + increment }));
};
const handleIncrement = useCallback(
(increment: number) => {
const offsetDate = getOffsetDateRange(dateRange, +offset + increment);
setDateRange(offsetDate);
router.push(updateParams({ offset: +offset + increment }));
},
[offset],
);
const handleSelect = (compare: any) => {
router.push(updateParams({ compare }));