Files
thrilltrack-explorer/src-old/components/ui/flexible-date-input.tsx

178 lines
5.0 KiB
TypeScript

import * as React from "react";
import { format } from "date-fns";
import { CalendarIcon } from "lucide-react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { DatePicker } from "@/components/ui/date-picker";
import { MonthYearPicker } from "@/components/ui/month-year-picker";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { toDateOnly, toDateWithPrecision } from "@/lib/dateUtils";
export type DatePrecision = 'day' | 'month' | 'year';
interface FlexibleDateInputProps {
value?: Date;
precision?: DatePrecision;
onChange: (date: Date | undefined, precision: DatePrecision) => void;
placeholder?: string;
disabled?: boolean;
className?: string;
disableFuture?: boolean;
disablePast?: boolean;
fromYear?: number;
toYear?: number;
label?: string;
}
export function FlexibleDateInput({
value,
precision = 'day',
onChange,
placeholder = "Select date",
disabled = false,
className,
disableFuture = false,
disablePast = false,
fromYear = 1800,
toYear = new Date().getFullYear() + 10,
label,
}: FlexibleDateInputProps) {
const [localPrecision, setLocalPrecision] = React.useState<DatePrecision>(precision);
const [yearValue, setYearValue] = React.useState<string>(
value && precision === 'year' ? value.getFullYear().toString() : ''
);
React.useEffect(() => {
setLocalPrecision(precision);
}, [precision]);
React.useEffect(() => {
if (value && precision === 'year') {
setYearValue(value.getFullYear().toString());
}
}, [value, precision]);
const handlePrecisionChange = (newPrecision: DatePrecision) => {
setLocalPrecision(newPrecision);
// If we have a value, adjust it to the new precision
if (value) {
const year = value.getFullYear();
const month = value.getMonth();
let newDate: Date;
switch (newPrecision) {
case 'year':
newDate = new Date(year, 0, 1); // January 1st (local timezone)
setYearValue(year.toString());
break;
case 'month':
newDate = new Date(year, month, 1); // 1st of month (local timezone)
break;
case 'day':
default:
newDate = value; // Keep existing date
break;
}
onChange(newDate, newPrecision);
} else {
onChange(undefined, newPrecision);
}
};
const handleYearChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const yearStr = e.target.value;
setYearValue(yearStr);
const yearNum = parseInt(yearStr, 10);
if (yearStr && !isNaN(yearNum) && yearNum >= fromYear && yearNum <= toYear) {
const newDate = new Date(yearNum, 0, 1);
onChange(newDate, 'year');
} else if (!yearStr) {
onChange(undefined, 'year');
}
};
const getPlaceholderText = () => {
switch (localPrecision) {
case 'year':
return 'Enter year (e.g., 2005)';
case 'month':
return 'Select month and year';
case 'day':
default:
return placeholder;
}
};
return (
<div className={cn("space-y-2", className)}>
{label && <Label>{label}</Label>}
<div className="flex gap-2">
<div className="flex-1">
{localPrecision === 'day' && (
<DatePicker
date={value}
onSelect={(date) => onChange(date, 'day')}
placeholder={getPlaceholderText()}
disabled={disabled}
disableFuture={disableFuture}
disablePast={disablePast}
fromYear={fromYear}
toYear={toYear}
/>
)}
{localPrecision === 'month' && (
<MonthYearPicker
date={value}
onSelect={(date) => onChange(date, 'month')}
placeholder={getPlaceholderText()}
disabled={disabled}
fromYear={fromYear}
toYear={toYear}
/>
)}
{localPrecision === 'year' && (
<Input
type="number"
value={yearValue}
onChange={handleYearChange}
placeholder={getPlaceholderText()}
disabled={disabled}
min={fromYear}
max={toYear}
className="w-full"
/>
)}
</div>
<Select
value={localPrecision}
onValueChange={(value) => handlePrecisionChange(value as DatePrecision)}
disabled={disabled}
>
<SelectTrigger className="w-[160px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="day">Use Full Date</SelectItem>
<SelectItem value="month">Use Month/Year</SelectItem>
<SelectItem value="year">Use Year Only</SelectItem>
</SelectContent>
</Select>
</div>
</div>
);
}