ARTEX — AI 自主渗透测试系统(Go 后端 + Next.js 前端,单二进制内嵌)。 Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import * as React from "react";
|
|
|
|
import { format, subDays } from "date-fns";
|
|
import type { DateRange } from "react-day-picker";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import { Calendar } from "@/components/ui/calendar";
|
|
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
|
|
|
interface DateRangePickerProps {
|
|
value?: DateRange;
|
|
onChange?: (value: DateRange | undefined) => void;
|
|
}
|
|
|
|
export function DateRangePicker({ value, onChange }: DateRangePickerProps) {
|
|
const [open, setOpen] = React.useState(false);
|
|
const [internalDateRange, setInternalDateRange] = React.useState<DateRange | undefined>(() => {
|
|
const to = new Date();
|
|
const from = subDays(to, 29);
|
|
return { from, to };
|
|
});
|
|
const dateRange = value ?? internalDateRange;
|
|
let dateRangeLabel = "Select date";
|
|
|
|
if (dateRange?.from) {
|
|
dateRangeLabel = format(dateRange.from, "d MMM yyyy");
|
|
}
|
|
|
|
if (dateRange?.from && dateRange.to) {
|
|
dateRangeLabel = `${format(dateRange.from, "d MMM yyyy")} - ${format(dateRange.to, "d MMM yyyy")}`;
|
|
}
|
|
|
|
const handleDateChange = (nextValue: DateRange | undefined) => {
|
|
if (!value) {
|
|
setInternalDateRange(nextValue);
|
|
}
|
|
onChange?.(nextValue);
|
|
};
|
|
|
|
return (
|
|
<Popover open={open} onOpenChange={setOpen}>
|
|
<PopoverTrigger asChild>
|
|
<Button variant="outline" id="date" className="font-normal">
|
|
{dateRangeLabel}
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent className="w-auto overflow-hidden p-0" align="end">
|
|
<Calendar
|
|
mode="range"
|
|
defaultMonth={dateRange?.from}
|
|
selected={dateRange}
|
|
onSelect={handleDateChange}
|
|
numberOfMonths={2}
|
|
/>
|
|
</PopoverContent>
|
|
</Popover>
|
|
);
|
|
}
|