Refactored useDateRange to always use query string. Fixed all time filter.

This commit is contained in:
Mike Cao 2025-10-03 17:55:39 -07:00
parent 4d06b0ca5b
commit 92ee44756c
28 changed files with 106 additions and 112 deletions

View file

@ -12,7 +12,7 @@ export function RefreshButton({
isLoading?: boolean;
}) {
const { formatMessage, labels } = useMessages();
const { dateRange } = useDateRange(websiteId);
const { dateRange } = useDateRange();
function handleClick() {
if (!isLoading && dateRange) {

View file

@ -1,7 +1,8 @@
import { List, ListItem } from '@umami/react-zen';
import { IconLabel, List, ListItem } from '@umami/react-zen';
import { useWebsiteSegmentsQuery } from '@/components/hooks';
import { LoadingPanel } from '@/components/common/LoadingPanel';
import { Empty } from '@/components/common/Empty';
import { ChartPie, UserPlus } from '@/components/icons';
export interface SegmentFiltersProps {
websiteId: string;
@ -29,7 +30,9 @@ export function SegmentFilters({
{data?.data?.map(item => {
return (
<ListItem key={item.id} id={item.id}>
{item.name}
<IconLabel icon={type === 'segment' ? <ChartPie /> : <UserPlus />}>
{item.name}
</IconLabel>
</ListItem>
);
})}

View file

@ -1,10 +1,10 @@
import { useCallback, useMemo } from 'react';
import { Button, Icon, Row, Text, Select, ListItem } from '@umami/react-zen';
import { isAfter } from 'date-fns';
import { ChevronRight } from '@/components/icons';
import { useDateRange, useMessages, useNavigation } from '@/components/hooks';
import { useDateRange, useDateRangeQuery, useMessages, useNavigation } from '@/components/hooks';
import { getDateRangeValue } from '@/lib/date';
import { DateFilter } from './DateFilter';
import { getOffsetDateRange } from '@/lib/date';
import { useCallback } from 'react';
export interface WebsiteDateFilterProps {
websiteId: string;
@ -20,30 +20,33 @@ export function WebsiteDateFilter({
showButtons = true,
allowCompare,
}: WebsiteDateFilterProps) {
const { dateRange, setDateRange, setDateRangeValue } = useDateRange(websiteId);
const { value, endDate } = dateRange;
const { dateRange, isAllTime, isCustomRange } = useDateRange();
const { formatMessage, labels } = useMessages();
const {
router,
updateParams,
query: { compare = 'prev', offset = 0 },
} = useNavigation();
const isAllTime = value === 'all';
const disableForward = isAllTime || isAfter(dateRange.endDate, new Date());
const isCustomRange = value.startsWith('range');
const disableForward = value === 'all' || isAfter(endDate, new Date());
const websiteDateRange = useDateRangeQuery(websiteId);
const handleChange = (date: string) => {
setDateRangeValue(date);
router.push(updateParams({ date, offset: undefined }));
if (date === 'all') {
router.push(
updateParams({
date: getDateRangeValue(websiteDateRange.startDate, websiteDateRange.endDate),
offset: undefined,
all: 1,
}),
);
} else {
router.push(updateParams({ date, offset: undefined }));
}
};
const handleIncrement = useCallback(
(increment: number) => {
const offsetDate = getOffsetDateRange(dateRange, +offset + increment);
setDateRange(offsetDate);
router.push(updateParams({ offset: +offset + increment }));
},
[offset],
@ -53,6 +56,12 @@ export function WebsiteDateFilter({
router.push(updateParams({ compare }));
};
const dateValue = useMemo(() => {
return offset !== 0
? getDateRangeValue(dateRange.startDate, dateRange.endDate)
: dateRange.value;
}, [dateRange]);
return (
<Row gap>
{showButtons && !isAllTime && !isCustomRange && (
@ -71,7 +80,7 @@ export function WebsiteDateFilter({
)}
<Row minWidth="200px">
<DateFilter
value={value}
value={dateValue}
onChange={handleChange}
showAllTime={showAllTime}
renderDate={+offset !== 0}

View file

@ -0,0 +1,44 @@
import { Button, Icon, DialogTrigger, Dialog, Modal, Text } from '@umami/react-zen';
import { ListFilter } from '@/components/icons';
import { FilterEditForm } from '@/components/input/FilterEditForm';
import { useMessages, useNavigation } from '@/components/hooks';
import { filtersArrayToObject } from '@/lib/params';
export function WebsiteFilterButton({
websiteId,
showText = true,
}: {
websiteId: string;
position?: 'bottom' | 'top' | 'left' | 'right';
alignment?: 'end' | 'center' | 'start';
showText?: boolean;
}) {
const { formatMessage, labels } = useMessages();
const { updateParams, router } = useNavigation();
const handleChange = ({ filters, segment, cohort }: any) => {
const params = filtersArrayToObject(filters);
const url = updateParams({ ...params, segment, cohort });
router.push(url);
};
return (
<DialogTrigger>
<Button variant="outline">
<Icon>
<ListFilter />
</Icon>
{showText && <Text>{formatMessage(labels.filter)}</Text>}
</Button>
<Modal>
<Dialog title={formatMessage(labels.filters)} style={{ width: 800, minHeight: 600 }}>
{({ close }) => {
return <FilterEditForm websiteId={websiteId} onChange={handleChange} onClose={close} />;
}}
</Dialog>
</Modal>
</DialogTrigger>
);
}

View file

@ -1,16 +1,17 @@
import { useDateRange } from '@/components/hooks';
import { dateToRangeValue } from '@/lib/date';
import { useDateRange, useNavigation } from '@/components/hooks';
import { getMonthDateRangeValue } from '@/lib/date';
import { MonthSelect } from './MonthSelect';
export function WebsiteMonthSelect({ websiteId }: { websiteId: string }) {
export function WebsiteMonthSelect() {
const { router, updateParams } = useNavigation();
const {
dateRange: { startDate },
saveDateRange,
} = useDateRange(websiteId);
} = useDateRange();
const handleMonthSelect = (date: Date) => {
const range = dateToRangeValue(date);
saveDateRange(range);
const range = getMonthDateRangeValue(date);
router.push(updateParams({ date: range, offset: undefined }));
};
return <MonthSelect date={startDate} onChange={handleMonthSelect} />;