1import { type FC, useEffect, useState } from "react";
2import { format } from "date-fns";
3import { CalendarIcon } from "@radix-ui/react-icons";
4import { cn } from "@marzneshin/common/utils";
5import { useFormContext, type FieldValues } from "react-hook-form";
6import { useTranslation } from "react-i18next";
7import {
8 Popover,
9 PopoverTrigger,
10 FormControl,
11 Button,
12 Calendar,
13 PopoverContent,
14 FormLabel,
15 FormItem,
16 FormField,
17 FormMessage,
18} from "@marzneshin/common/components";
19
20interface DateFieldProps {
21 name: keyof FieldValues;
22 label: string;
23}
24
25function parseISODate(isoDateString: string | undefined): Date | undefined {
26 if (!isoDateString) return undefined;
27 const date = new Date(isoDateString);
28 return isNaN(date.getTime()) ? undefined : date;
29}
30
31export const DateField: FC<DateFieldProps> = ({ name, label }) => {
32 const { t } = useTranslation();
33 const form = useFormContext();
34 const [selectedDate, setSelectedDate] = useState<Date | undefined>(
35 parseISODate(form.getValues(name)),
36 );
37
38 useEffect(() => {
39 const newValue = selectedDate?.toISOString().slice(0, -5);
40 const prevValue = form.getValues(name);
41 if (newValue !== prevValue) {
42 form.setValue(name, newValue, {
43 shouldValidate: true,
44 shouldTouch: true,
45 shouldDirty: true,
46 });
47 }
48 }, [form, name, selectedDate]);
49
50 return (
51 <FormField
52 control={form.control}
53 name={name}
54 render={({ field }) => (
55 <FormItem className="flex flex-col mt-2 w-full">
56 <FormLabel>{t(label)}</FormLabel>
57 <Popover>
58 <PopoverTrigger asChild>
59 <FormControl>
60 <Button
61 variant={"outline"}
62 className={cn(
63 "w-full pl-3 text-left font-normal",
64 !field.value && "text-muted-foreground",
65 )}
66 >
67 {field.value ? (
68 format(field.value + "Z", "PPP")
69 ) : (
70 <span>Pick a date</span>
71 )}
72 <CalendarIcon className="ml-auto w-4 h-4 opacity-50" />
73 </Button>
74 </FormControl>
75 </PopoverTrigger>
76 <PopoverContent className="p-0 w-auto" align="start">
77 <Calendar
78 mode="single"
79 {...field}
80 selected={selectedDate}
81 onSelect={(date) => {
82 setSelectedDate(date);
83 }}
84 disabled={(date) => date < new Date()}
85 initialFocus
86 />
87 </PopoverContent>
88 </Popover>
89 <FormMessage />
90 </FormItem>
91 )}
92 />
93 );
94};