101 lines
3.2 KiB
TypeScript
101 lines
3.2 KiB
TypeScript
import * as React from 'react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Calendar } from '@/components/ui/calendar';
|
|
import {
|
|
Popover,
|
|
PopoverContent,
|
|
PopoverTrigger,
|
|
} from '@/components/ui/popover';
|
|
import { useBreakpoint } from '@/hooks/useBreakpoint';
|
|
import { cn } from '@/utils/cn';
|
|
import { format } from 'date-fns';
|
|
import { CalendarIcon, ChevronsUpDownIcon } from 'lucide-react';
|
|
import type { SelectRangeEventHandler } from 'react-day-picker';
|
|
|
|
import { timeRanges } from '@openpanel/constants';
|
|
import type { IChartRange } from '@openpanel/validation';
|
|
|
|
import type { ExtendedComboboxProps } from '../ui/combobox';
|
|
import { ToggleGroup, ToggleGroupItem } from '../ui/toggle-group';
|
|
|
|
export function ReportRange({
|
|
range,
|
|
onRangeChange,
|
|
onDatesChange,
|
|
dates,
|
|
className,
|
|
...props
|
|
}: {
|
|
range: IChartRange;
|
|
onRangeChange: (range: IChartRange) => void;
|
|
onDatesChange: SelectRangeEventHandler;
|
|
dates: { startDate: string | null; endDate: string | null };
|
|
} & Omit<ExtendedComboboxProps<string>, 'value' | 'onChange'>) {
|
|
const { isBelowSm } = useBreakpoint('sm');
|
|
|
|
return (
|
|
<>
|
|
<Popover>
|
|
<PopoverTrigger asChild>
|
|
<Button
|
|
id="date"
|
|
variant={'outline'}
|
|
className={cn('justify-start text-left font-normal', className)}
|
|
icon={CalendarIcon}
|
|
{...props}
|
|
>
|
|
<span className="min-w-0 overflow-hidden text-ellipsis whitespace-nowrap">
|
|
{dates.startDate ? (
|
|
dates.endDate ? (
|
|
<>
|
|
{format(dates.startDate, 'LLL dd')} -{' '}
|
|
{format(dates.endDate, 'LLL dd')}
|
|
</>
|
|
) : (
|
|
format(dates.startDate, 'LLL dd, y')
|
|
)
|
|
) : (
|
|
<span>{range}</span>
|
|
)}
|
|
</span>
|
|
<ChevronsUpDownIcon className="ml-auto h-4 w-4 shrink-0 opacity-50" />
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent className="w-auto p-0" align="start">
|
|
<div className="border-b border-border p-4">
|
|
<ToggleGroup
|
|
value={range}
|
|
onValueChange={(value) => {
|
|
if (value) onRangeChange(value as IChartRange);
|
|
}}
|
|
type="single"
|
|
variant="outline"
|
|
className="flex-wrap max-sm:max-w-xs"
|
|
>
|
|
{Object.values(timeRanges).map((key) => (
|
|
<ToggleGroupItem value={key} aria-label={key} key={key}>
|
|
{key}
|
|
</ToggleGroupItem>
|
|
))}
|
|
</ToggleGroup>
|
|
</div>
|
|
<Calendar
|
|
initialFocus
|
|
mode="range"
|
|
defaultMonth={
|
|
dates.startDate ? new Date(dates.startDate) : new Date()
|
|
}
|
|
selected={{
|
|
from: dates.startDate ? new Date(dates.startDate) : undefined,
|
|
to: dates.endDate ? new Date(dates.endDate) : undefined,
|
|
}}
|
|
onSelect={onDatesChange}
|
|
numberOfMonths={isBelowSm ? 1 : 2}
|
|
className="[&_table]:mx-auto [&_table]:w-auto"
|
|
/>
|
|
</PopoverContent>
|
|
</Popover>
|
|
</>
|
|
);
|
|
}
|