diff --git a/apps/start/src/components/time-window-picker.tsx b/apps/start/src/components/time-window-picker.tsx index e611e3e0..3d0192ad 100644 --- a/apps/start/src/components/time-window-picker.tsx +++ b/apps/start/src/components/time-window-picker.tsx @@ -1,9 +1,10 @@ -import { timeWindows } from '@openpanel/constants'; +import { getDefaultIntervalByDates, timeWindows } from '@openpanel/constants'; import type { IChartRange, IInterval } from '@openpanel/validation'; import { bind } from 'bind-event-listener'; -import { endOfDay, format, startOfDay } from 'date-fns'; +import { endOfDay, format, startOfDay, subDays } from 'date-fns'; import { CalendarIcon } from 'lucide-react'; -import { useCallback, useEffect, useRef } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; +import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { DropdownMenu, @@ -44,6 +45,27 @@ export function TimeWindowPicker({ isDateRangerPickerOpen.current = open; }); const timeWindow = timeWindows[value ?? '30d']; + const [customDays, setCustomDays] = useState(''); + + const handleCustomDays = useCallback( + (days: number) => { + if (days < 1 || days > 365) return; + const now = new Date(); + const end = endOfDay(now); + const start = startOfDay(subDays(now, days - 1)); + onStartDateChange(format(start, 'yyyy-MM-dd HH:mm:ss')); + onEndDateChange(format(end, 'yyyy-MM-dd HH:mm:ss')); + onChange('custom'); + const interval = getDefaultIntervalByDates( + start.toISOString(), + end.toISOString() + ); + if (interval) { + onIntervalChange(interval); + } + }, + [onChange, onStartDateChange, onEndDateChange, onIntervalChange] + ); const handleCustom = useCallback(() => { pushModal('DateRangerPicker', { @@ -194,6 +216,36 @@ export function TimeWindowPicker({ +
e.stopPropagation()} + onKeyDown={(e) => e.stopPropagation()} + > + Last + setCustomDays(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); + const days = Number(customDays); + if (Number.isInteger(days) && days >= 1 && days <= 365) { + handleCustomDays(days); + setCustomDays(''); + } + } + e.stopPropagation(); + }} + className="h-7 w-16 text-center" + /> + days +
handleCustom()}> {timeWindows.custom.label}