Reverted to commit 10950a4034

This commit is contained in:
gpt-engineer-app[bot]
2025-10-11 23:39:40 +00:00
parent c59ab9523f
commit 52e50ebb5e
8 changed files with 14 additions and 468 deletions

View File

@@ -97,10 +97,6 @@ export function FormerNamesEditor({ names, onChange, currentName }: FormerNamesE
<DatePicker <DatePicker
date={name.date_changed ? new Date(name.date_changed) : undefined} date={name.date_changed ? new Date(name.date_changed) : undefined}
onSelect={(date) => updateName(actualIndex, 'date_changed', date || undefined)} onSelect={(date) => updateName(actualIndex, 'date_changed', date || undefined)}
placeholder="Select or type date"
allowTextEntry={true}
fromYear={1800}
toYear={new Date().getFullYear()}
/> />
</div> </div>

View File

@@ -186,8 +186,6 @@ export function ReviewForm({
placeholder="When did you visit?" placeholder="When did you visit?"
disableFuture={true} disableFuture={true}
fromYear={1950} fromYear={1950}
allowTextEntry={true}
dateFormat="yyyy-MM-dd"
/> />
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
Select the date of your visit to help others understand when this experience occurred. Select the date of your visit to help others understand when this experience occurred.

View File

@@ -1,73 +0,0 @@
import * as React from "react";
import { CaptionProps, useNavigation } from "react-day-picker";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { Button } from "@/components/ui/button";
import { YearGridSelector } from "@/components/ui/year-grid-selector";
import { cn } from "@/lib/utils";
interface CustomCaptionProps extends CaptionProps {
fromYear?: number;
toYear?: number;
}
export function CustomCalendarCaption({
displayMonth,
fromYear = 1800,
toYear = new Date().getFullYear() + 10,
}: CustomCaptionProps) {
const { goToMonth, nextMonth, previousMonth, currentMonth } = useNavigation();
const handleYearSelect = (year: number) => {
const newDate = new Date(displayMonth);
newDate.setFullYear(year);
goToMonth(newDate);
};
const monthName = displayMonth.toLocaleString("en-US", { month: "long" });
const selectedYear = displayMonth.getFullYear();
return (
<div className="flex justify-between items-center px-2 py-2">
<Button
variant="outline"
className="h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
onClick={() => previousMonth && goToMonth(previousMonth)}
disabled={!previousMonth}
type="button"
>
<ChevronLeft className="h-4 w-4" />
</Button>
<div className="flex items-center gap-2">
<span className="text-sm font-medium">{monthName}</span>
<YearGridSelector
selectedYear={selectedYear}
onYearSelect={handleYearSelect}
fromYear={fromYear}
toYear={toYear}
>
<Button
variant="ghost"
className={cn(
"h-7 px-2 text-sm font-medium hover:bg-accent",
"focus:bg-accent focus:text-accent-foreground"
)}
type="button"
>
{selectedYear}
</Button>
</YearGridSelector>
</div>
<Button
variant="outline"
className="h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
onClick={() => nextMonth && goToMonth(nextMonth)}
disabled={!nextMonth}
type="button"
>
<ChevronRight className="h-4 w-4" />
</Button>
</div>
);
}

View File

@@ -4,20 +4,13 @@ import { DayPicker } from "react-day-picker";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { buttonVariants } from "@/components/ui/button"; import { buttonVariants } from "@/components/ui/button";
import { CustomCalendarCaption } from "@/components/ui/calendar-custom-caption";
export type CalendarProps = React.ComponentProps<typeof DayPicker> & { export type CalendarProps = React.ComponentProps<typeof DayPicker>;
enableYearGrid?: boolean;
};
function Calendar({ className, classNames, showOutsideDays = true, enableYearGrid = false, ...props }: CalendarProps) { function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {
const captionLayout = enableYearGrid ? undefined : (props.captionLayout || "dropdown-buttons");
return ( return (
<DayPicker <DayPicker
showOutsideDays={showOutsideDays} showOutsideDays={showOutsideDays}
captionLayout={captionLayout}
fromYear={props.fromYear || 1800}
toYear={props.toYear || new Date().getFullYear() + 10}
className={cn("p-3", className)} className={cn("p-3", className)}
classNames={{ classNames={{
months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0", months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
@@ -49,15 +42,6 @@ function Calendar({ className, classNames, showOutsideDays = true, enableYearGri
...classNames, ...classNames,
}} }}
components={{ components={{
Caption: enableYearGrid
? (captionProps) => (
<CustomCalendarCaption
{...captionProps}
fromYear={props.fromYear || 1800}
toYear={props.toYear || new Date().getFullYear() + 10}
/>
)
: undefined,
IconLeft: ({ ..._props }) => <ChevronLeft className="h-4 w-4" />, IconLeft: ({ ..._props }) => <ChevronLeft className="h-4 w-4" />,
IconRight: ({ ..._props }) => <ChevronRight className="h-4 w-4" />, IconRight: ({ ..._props }) => <ChevronRight className="h-4 w-4" />,
}} }}

View File

@@ -1,79 +0,0 @@
import * as React from "react";
import { format, parse, isValid } from "date-fns";
import { cn } from "@/lib/utils";
import { DatePicker, DatePickerProps } from "./date-picker";
interface DateInputWithFeedbackProps extends DatePickerProps {
showFeedback?: boolean;
}
export function DateInputWithFeedback({
showFeedback = true,
onSelect,
...props
}: DateInputWithFeedbackProps) {
const [parseStatus, setParseStatus] = React.useState<{
isValid: boolean;
message: string;
parsed?: Date;
}>({ isValid: true, message: "" });
const parseDate = (input: string): Date | null => {
if (!input) return null;
// Try ISO format: 2005-06-15
let parsed = parse(input, "yyyy-MM-dd", new Date());
if (isValid(parsed)) return parsed;
// Try US format: 06/15/2005
parsed = parse(input, "MM/dd/yyyy", new Date());
if (isValid(parsed)) return parsed;
// Try European format: 15/06/2005
parsed = parse(input, "dd/MM/yyyy", new Date());
if (isValid(parsed)) return parsed;
// Try short format: 6/15/05
parsed = parse(input, "M/d/yy", new Date());
if (isValid(parsed)) return parsed;
// Try short year format: 2005-6-15
parsed = parse(input, "yyyy-M-d", new Date());
if (isValid(parsed)) return parsed;
return null;
};
const handleSelect = (date: Date | undefined) => {
if (date) {
setParseStatus({
isValid: true,
message: `${format(date, "PPP")}`,
parsed: date
});
} else {
setParseStatus({ isValid: true, message: "" });
}
onSelect?.(date);
};
return (
<div className="space-y-1">
<DatePicker
allowTextEntry
onSelect={handleSelect}
{...props}
/>
{showFeedback && parseStatus.message && (
<p className={cn(
"text-xs",
parseStatus.isValid
? "text-green-600 dark:text-green-400"
: "text-amber-600 dark:text-amber-400"
)}>
{parseStatus.message}
</p>
)}
</div>
);
}

View File

@@ -1,10 +1,9 @@
import * as React from "react"; import * as React from "react";
import { format, parse, isValid } from "date-fns"; import { format } from "date-fns";
import { CalendarIcon } from "lucide-react"; import { CalendarIcon } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Calendar } from "@/components/ui/calendar"; import { Calendar } from "@/components/ui/calendar";
import { import {
Popover, Popover,
@@ -22,9 +21,6 @@ export interface DatePickerProps {
disablePast?: boolean; disablePast?: boolean;
fromYear?: number; fromYear?: number;
toYear?: number; toYear?: number;
allowTextEntry?: boolean;
dateFormat?: string;
enableYearGrid?: boolean;
} }
export function DatePicker({ export function DatePicker({
@@ -37,66 +33,12 @@ export function DatePicker({
disablePast = false, disablePast = false,
fromYear, fromYear,
toYear, toYear,
allowTextEntry = false,
dateFormat = "yyyy-MM-dd",
enableYearGrid = false,
}: DatePickerProps) { }: DatePickerProps) {
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const [textInput, setTextInput] = React.useState("");
const [isTyping, setIsTyping] = React.useState(false);
const parseDate = (input: string): Date | null => {
if (!input) return null;
// Try ISO format: 2005-06-15
let parsed = parse(input, "yyyy-MM-dd", new Date());
if (isValid(parsed)) return parsed;
// Try US format: 06/15/2005
parsed = parse(input, "MM/dd/yyyy", new Date());
if (isValid(parsed)) return parsed;
// Try European format: 15/06/2005
parsed = parse(input, "dd/MM/yyyy", new Date());
if (isValid(parsed)) return parsed;
// Try short format: 6/15/05
parsed = parse(input, "M/d/yy", new Date());
if (isValid(parsed)) return parsed;
// Try short year format: 2005-6-15
parsed = parse(input, "yyyy-M-d", new Date());
if (isValid(parsed)) return parsed;
return null;
};
const handleTextChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
setTextInput(value);
setIsTyping(true);
const parsed = parseDate(value);
if (parsed) {
onSelect?.(parsed);
}
};
const handleBlur = () => {
setIsTyping(false);
if (date) {
setTextInput(format(date, dateFormat));
} else {
setTextInput("");
}
};
const handleSelect = (selectedDate: Date | undefined) => { const handleSelect = (selectedDate: Date | undefined) => {
onSelect?.(selectedDate); onSelect?.(selectedDate);
setOpen(false); setOpen(false);
if (selectedDate) {
setTextInput(format(selectedDate, dateFormat));
}
}; };
const getDisabledDates = (date: Date) => { const getDisabledDates = (date: Date) => {
@@ -106,49 +48,6 @@ export function DatePicker({
return false; return false;
}; };
if (allowTextEntry) {
return (
<div className="relative flex gap-1">
<Input
type="text"
value={isTyping ? textInput : (date ? format(date, dateFormat) : "")}
onChange={handleTextChange}
onFocus={() => setIsTyping(true)}
onBlur={handleBlur}
placeholder={placeholder}
disabled={disabled}
className={cn("flex-1", className)}
/>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
size="icon"
disabled={disabled}
className="shrink-0"
type="button"
>
<CalendarIcon className="h-4 w-4" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={date}
onSelect={handleSelect}
disabled={getDisabledDates}
initialFocus
className="p-3 pointer-events-auto"
fromYear={fromYear}
toYear={toYear}
enableYearGrid={enableYearGrid}
/>
</PopoverContent>
</Popover>
</div>
);
}
return ( return (
<Popover open={open} onOpenChange={setOpen}> <Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild> <PopoverTrigger asChild>
@@ -160,7 +59,6 @@ export function DatePicker({
className className
)} )}
disabled={disabled} disabled={disabled}
type="button"
> >
<CalendarIcon className="mr-2 h-4 w-4" /> <CalendarIcon className="mr-2 h-4 w-4" />
<span className="truncate"> <span className="truncate">
@@ -178,7 +76,6 @@ export function DatePicker({
className="p-3 pointer-events-auto" className="p-3 pointer-events-auto"
fromYear={fromYear} fromYear={fromYear}
toYear={toYear} toYear={toYear}
enableYearGrid={enableYearGrid}
/> />
</PopoverContent> </PopoverContent>
</Popover> </Popover>

View File

@@ -128,7 +128,6 @@ export function FlexibleDateInput({
disablePast={disablePast} disablePast={disablePast}
fromYear={fromYear} fromYear={fromYear}
toYear={toYear} toYear={toYear}
allowTextEntry={true}
/> />
)} )}

View File

@@ -1,176 +0,0 @@
import * as React from "react";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
interface YearGridSelectorProps {
selectedYear: number;
onYearSelect: (year: number) => void;
fromYear?: number;
toYear?: number;
children: React.ReactNode;
}
export function YearGridSelector({
selectedYear,
onYearSelect,
fromYear = 1800,
toYear = new Date().getFullYear() + 10,
children,
}: YearGridSelectorProps) {
const [open, setOpen] = React.useState(false);
const [view, setView] = React.useState<"year" | "decade">("year");
const [startYear, setStartYear] = React.useState(() => {
// Start from the decade containing the selected year
return Math.floor(selectedYear / 10) * 10;
});
const handleYearSelect = (year: number) => {
onYearSelect(year);
setOpen(false);
};
const handleDecadeSelect = (decade: number) => {
setStartYear(decade);
setView("year");
};
const navigateYears = (direction: "prev" | "next") => {
setStartYear((prev) => prev + (direction === "next" ? 12 : -12));
};
const navigateDecades = (direction: "prev" | "next") => {
setStartYear((prev) => prev + (direction === "next" ? 120 : -120));
};
const renderYearGrid = () => {
const years: number[] = [];
for (let i = 0; i < 12; i++) {
const year = startYear + i;
if (year >= fromYear && year <= toYear) {
years.push(year);
}
}
const endYear = startYear + 11;
const currentYear = new Date().getFullYear();
return (
<div className="p-3 space-y-3">
<div className="flex items-center justify-between">
<Button
variant="ghost"
size="icon"
className="h-7 w-7"
onClick={() => navigateYears("prev")}
disabled={startYear <= fromYear}
>
<ChevronLeft className="h-4 w-4" />
</Button>
<Button
variant="ghost"
className="text-sm font-medium hover:bg-accent"
onClick={() => setView("decade")}
>
{startYear} - {endYear}
</Button>
<Button
variant="ghost"
size="icon"
className="h-7 w-7"
onClick={() => navigateYears("next")}
disabled={endYear >= toYear}
>
<ChevronRight className="h-4 w-4" />
</Button>
</div>
<div className="grid grid-cols-4 gap-1">
{years.map((year) => (
<Button
key={year}
variant={year === selectedYear ? "default" : "ghost"}
className={cn(
"h-9 w-full text-sm font-normal",
year === currentYear && year !== selectedYear && "border border-primary"
)}
onClick={() => handleYearSelect(year)}
>
{year}
</Button>
))}
</div>
</div>
);
};
const renderDecadeGrid = () => {
const decades: number[] = [];
const decadeStart = Math.floor(startYear / 100) * 100;
for (let i = 0; i < 12; i++) {
const decade = decadeStart + i * 10;
if (decade >= Math.floor(fromYear / 10) * 10 && decade <= Math.ceil(toYear / 10) * 10) {
decades.push(decade);
}
}
const decadeEnd = decadeStart + 110;
return (
<div className="p-3 space-y-3">
<div className="flex items-center justify-between">
<Button
variant="ghost"
size="icon"
className="h-7 w-7"
onClick={() => navigateDecades("prev")}
disabled={decadeStart <= Math.floor(fromYear / 100) * 100}
>
<ChevronLeft className="h-4 w-4" />
</Button>
<Button
variant="ghost"
className="text-sm font-medium hover:bg-accent"
onClick={() => setView("year")}
>
{decadeStart}s - {decadeEnd}s
</Button>
<Button
variant="ghost"
size="icon"
className="h-7 w-7"
onClick={() => navigateDecades("next")}
disabled={decadeEnd >= Math.ceil(toYear / 100) * 100}
>
<ChevronRight className="h-4 w-4" />
</Button>
</div>
<div className="grid grid-cols-3 gap-2">
{decades.map((decade) => (
<Button
key={decade}
variant="ghost"
className="h-10 w-full text-sm font-normal"
onClick={() => handleDecadeSelect(decade)}
>
{decade}s
</Button>
))}
</div>
</div>
);
};
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>{children}</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
{view === "year" ? renderYearGrid() : renderDecadeGrid()}
</PopoverContent>
</Popover>
);
}