gitscope
← marzneshin / v0.6.0 / dashboard/src/components/form-fields/date.tsx
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/components/form-fields/date.tsx · TypeScript
Blame Raw
 1import { type FC, useEffect, useState } from "react";
 2import { format } from "date-fns";
 3import { CalendarIcon } from "@radix-ui/react-icons";
 4import { cn } from "@marzneshin/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/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};