import { Button, Calendar, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, FormControl, FormDescription, FormItem, FormLabel, FormMessage, Popover, PopoverContent, PopoverTrigger, } from "@repo/shadcn-ui/components"; import { CalendarIcon, LockIcon, XIcon } from "lucide-react"; import { cn } from "@repo/shadcn-ui/lib/utils"; import { format, isValid, parse } from "date-fns"; import { useEffect, useState } from "react"; import { FieldValues } from "react-hook-form"; import { useTranslation } from "../../../locales/i18n.ts"; import { ControllerFieldState, ControllerRenderProps, UseFormStateReturn } from "react-hook-form"; export type SUICalendarProps = Omit, "select" | "onSelect"> type DatePickerInputCompProps = SUICalendarProps & { field: ControllerRenderProps; fieldState: ControllerFieldState; formState: UseFormStateReturn; displayDateFormat: string; // e.g. "dd/MM/yyyy" parseDateFormat: string; // e.g. "yyyy/MM/dd" label: string; placeholder?: string; description?: string; disabled?: boolean; required?: boolean; readOnly?: boolean; className?: string; }; export function DatePickerInputComp({ field, fieldState, formState, parseDateFormat, displayDateFormat, label, placeholder, description, disabled = false, required = false, readOnly = false, className, ...calendarProps }: DatePickerInputCompProps) { const { t } = useTranslation(); const isDisabled = disabled; const isReadOnly = readOnly && !disabled; const describedById = description ? `${field.name}-desc` : undefined; const errorId = fieldState.error ? `${field.name}-err` : undefined; const [open, setOpen] = useState(false); // Popover const [displayValue, setDisplayValue] = useState(""); // Sync cuando RHF actualiza el valor externamente useEffect(() => { if (field.value) { // field.value ya viene en formato parseDateFormat console.log(field.value, parseDateFormat); const parsed = parse(field.value, parseDateFormat, new Date()); console.log("parsed =>", parsed); if (isValid(parsed)) { setDisplayValue(format(parsed, displayDateFormat)); } } else { setDisplayValue(""); } }, [field.value, parseDateFormat, displayDateFormat]); const [inputError, setInputError] = useState(null); const handleDisplayValueChange = (value: string) => { console.log("handleDisplayValueChange => ", value) setDisplayValue(value); setInputError(null); }; const handleClearDate = () => { handleDisplayValueChange(""); } const validateAndSetDate = () => { const trimmed = displayValue.trim(); if (!trimmed) { field.onChange(""); // guardar vacío en el form setInputError(null); return; } const parsed = parse(trimmed, displayDateFormat, new Date()); if (isValid(parsed)) { // Guardar en form como string con parseDateFormat const newDateStr = format(parsed, parseDateFormat); field.onChange(newDateStr); // Asegurar displayValue consistente handleDisplayValueChange(newDateStr); } else { setInputError(t("components.date_picker_input_field.invalid_date")); } }; return ( {label && (
{label} {required && {t("common.required")}}
{/* Punto “unsaved” */} {fieldState.isDirty && ( {t("common.modified")} )}
)}
handleDisplayValueChange(e.target.value)} onBlur={() => { if (!open) validateAndSetDate(); }} onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); validateAndSetDate(); } }} readOnly={isReadOnly} disabled={isDisabled} className={cn( "w-full rounded-md border px-3 py-2 text-sm shadow-sm focus:outline-none focus:ring-2 focus:ring-ring placeholder:font-normal placeholder:italic", isDisabled && "bg-muted text-muted-foreground cursor-not-allowed", isReadOnly && "bg-muted text-foreground cursor-default", !isDisabled && !isReadOnly && "bg-white text-foreground", inputError && "border-destructive ring-destructive" )} placeholder={placeholder} />
{!isReadOnly && !required && displayValue && ( )} {isReadOnly ? ( ) : ( )}
{!isDisabled && !isReadOnly && ( {label} {description || "\u00A0"} { const newDateStr = date ? format(date, parseDateFormat) : ""; field.onChange(newDateStr); handleDisplayValueChange(newDateStr); setOpen(false); }} initialFocus /> )}
{isReadOnly && (

{t("common.read_only") || "Solo lectura"}

)}
{description || "\u00A0"}
); }