Updated date range handling.

This commit is contained in:
Mike Cao 2025-06-25 14:27:17 -07:00
parent 6d1603fa28
commit 5ca51b3e8f
19 changed files with 101 additions and 99 deletions

View file

@ -1,55 +1,53 @@
import { getMinimumUnit, parseDateRange } from '@/lib/date';
import { getMinimumUnit, parseDateRange, getOffsetDateRange } from '@/lib/date';
import { setItem } from '@/lib/storage';
import { DATE_RANGE_CONFIG, DEFAULT_DATE_COMPARE, DEFAULT_DATE_RANGE } from '@/lib/constants';
import { DATE_RANGE_CONFIG, DEFAULT_DATE_COMPARE, DEFAULT_DATE_RANGE_VALUE } from '@/lib/constants';
import { setWebsiteDateCompare, setWebsiteDateRange, useWebsites } from '@/store/websites';
import { setDateRange, useApp } from '@/store/app';
import { DateRange } from '@/lib/types';
import { setDateRangeValue, useApp } from '@/store/app';
import { useLocale } from './useLocale';
import { useApi } from './useApi';
import { useNavigation } from './useNavigation';
import { useMemo } from 'react';
export function useDateRange(websiteId?: string) {
const { get } = useApi();
const { locale } = useLocale();
const {
query: { date },
query: { date, offset = 0 },
} = useNavigation();
const websiteConfig = useWebsites(state => state[websiteId]?.dateRange);
const globalConfig = useApp(state => state.dateRange);
const dateRange = parseDateRange(
date || websiteConfig || globalConfig || DEFAULT_DATE_RANGE,
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],
);
const dateCompare = useWebsites(state => state[websiteId]?.dateCompare || DEFAULT_DATE_COMPARE);
const saveDateRange = async (value: DateRange | string) => {
const saveDateRange = async (value: string) => {
if (websiteId) {
let dateRange: DateRange | string = value;
if (value === 'all') {
const result: any = await get(`/websites/${websiteId}/daterange`);
const { mindate, maxdate } = result;
if (typeof value === 'string') {
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);
const startDate = new Date(mindate);
const endDate = new Date(maxdate);
const unit = getMinimumUnit(startDate, endDate);
dateRange = {
startDate,
endDate,
unit,
value,
};
} else {
dateRange = parseDateRange(value, locale);
}
setWebsiteDateRange(websiteId, {
startDate,
endDate,
unit,
value,
});
} else {
setWebsiteDateRange(websiteId, parseDateRange(value, locale));
}
setWebsiteDateRange(websiteId, dateRange as DateRange);
} else {
setItem(DATE_RANGE_CONFIG, value);
setDateRange(value);
setDateRangeValue(value);
}
};

View file

@ -11,6 +11,7 @@ export interface DateFilterProps {
endDate: Date;
onChange?: (value: string) => void;
showAllTime?: boolean;
renderDate?: boolean;
}
export function DateFilter({
@ -18,7 +19,8 @@ export function DateFilter({
startDate,
endDate,
onChange,
showAllTime = false,
showAllTime,
renderDate,
}: DateFilterProps) {
const { formatMessage, labels } = useMessages();
const [showPicker, setShowPicker] = useState(false);
@ -89,7 +91,7 @@ export function DateFilter({
};
const renderValue = ({ defaultChildren }) => {
return value?.startsWith('range') ? (
return value?.startsWith('range') || renderDate ? (
<DateDisplay startDate={startDate} endDate={endDate} />
) : (
defaultChildren

View file

@ -11,7 +11,6 @@ import {
import { isAfter } from 'date-fns';
import { Chevron, Close, Compare } from '@/components/icons';
import { useDateRange, useMessages, useNavigation } from '@/components/hooks';
import { getOffsetDateRange } from '@/lib/date';
import { DateFilter } from './DateFilter';
export function WebsiteDateFilter({
@ -26,13 +25,13 @@ export function WebsiteDateFilter({
showButtons?: boolean;
allowCompare?: boolean;
}) {
const { dateRange, saveDateRange } = useDateRange(websiteId);
const { value, startDate, endDate, offset } = dateRange;
const { dateRange } = useDateRange(websiteId);
const { value, startDate, endDate } = dateRange;
const { formatMessage, labels } = useMessages();
const {
router,
updateParams,
query: { compare },
query: { compare, offset = 0 },
} = useNavigation();
const isAllTime = value === 'all';
const isCustomRange = value.startsWith('range');
@ -40,13 +39,11 @@ export function WebsiteDateFilter({
const disableForward = value === 'all' || isAfter(endDate, new Date());
const handleChange = (date: string) => {
router.push(updateParams({ date }));
saveDateRange(date);
router.push(updateParams({ date, offset: undefined }));
};
const handleIncrement = (increment: number) => {
router.push(updateParams({ offset: offset + increment }));
saveDateRange(getOffsetDateRange(dateRange, increment));
router.push(updateParams({ offset: +offset + increment }));
};
const handleSelect = (compare: any) => {
@ -79,6 +76,7 @@ export function WebsiteDateFilter({
endDate={endDate}
onChange={handleChange}
showAllTime={showAllTime}
renderDate={+offset !== 0}
/>
{!isAllTime && compare && (
<Row alignItems="center" gap>

View file

@ -330,6 +330,7 @@ export const labels = defineMessages({
conversion: { id: 'label.conversion', defaultMessage: 'Conversion' },
firstClick: { id: 'label.first-click', defaultMessage: 'First click' },
lastClick: { id: 'label.last-click', defaultMessage: 'Last click' },
online: { id: 'label.online', defaultMessage: 'Online' },
});
export const messages = defineMessages({

View file

@ -11,7 +11,7 @@ export function ActiveUsers({
value?: number;
refetchInterval?: number;
}) {
const { formatMessage, messages } = useMessages();
const { formatMessage, labels } = useMessages();
const { data } = useActyiveUsersQuery(websiteId, { refetchInterval });
const count = useMemo(() => {
@ -28,8 +28,8 @@ export function ActiveUsers({
return (
<StatusLight variant="success">
<Text size="2" weight="bold">
{formatMessage(messages.numberOfUsers, { x: count })}
<Text size="2" weight="medium">
{count} {formatMessage(labels.online)}
</Text>
</StatusLight>
);