Refactor date input components across forms to use DateInput instead of Popover with Calendar for improved usability and consistency

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
Marco Pedone 2026-05-04 18:31:36 +02:00
parent 76718d5647
commit 20e50d5c6d
16 changed files with 124 additions and 1085 deletions

View file

@ -39,7 +39,8 @@
"@radix-ui/react-tooltip", "@radix-ui/react-tooltip",
"@radix-ui/react-popover", "@radix-ui/react-popover",
"@radix-ui/react-toggle-group", "@radix-ui/react-toggle-group",
"tailwindcss" "tailwindcss",
"@hookform/devtools"
], ],
"project": [ "project": [
"src/**", "src/**",

View file

@ -69,7 +69,6 @@
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"react": "^19.2.3", "react": "^19.2.3",
"react-colorful": "^5.6.1", "react-colorful": "^5.6.1",
"react-day-picker": "^9.14.0",
"react-dom": "^19.2.3", "react-dom": "^19.2.3",
"react-hook-form": "^7.72.1", "react-hook-form": "^7.72.1",
"react-hot-toast": "^2.5.2", "react-hot-toast": "^2.5.2",
@ -594,10 +593,6 @@
"node": ">=20.19.0" "node": ">=20.19.0"
} }
}, },
"node_modules/@date-fns/tz": {
"version": "1.4.1",
"license": "MIT"
},
"node_modules/@discoveryjs/json-ext": { "node_modules/@discoveryjs/json-ext": {
"version": "0.5.7", "version": "0.5.7",
"license": "MIT", "license": "MIT",
@ -5867,15 +5862,6 @@
} }
} }
}, },
"node_modules/@tabby_ai/hijri-converter": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@tabby_ai/hijri-converter/-/hijri-converter-1.0.5.tgz",
"integrity": "sha512-r5bClKrcIusDoo049dSL8CawnHR6mRdDwhlQuIgZRNty68q0x8k3Lf1BtPAMxRf/GgnHBnIO4ujd3+GQdLWzxQ==",
"license": "MIT",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/@tailwindcss/forms": { "node_modules/@tailwindcss/forms": {
"version": "0.5.11", "version": "0.5.11",
"license": "MIT", "license": "MIT",
@ -7701,10 +7687,6 @@
"url": "https://github.com/sponsors/kossnocorp" "url": "https://github.com/sponsors/kossnocorp"
} }
}, },
"node_modules/date-fns-jalali": {
"version": "4.1.0-0",
"license": "MIT"
},
"node_modules/debounce": { "node_modules/debounce": {
"version": "2.2.0", "version": "2.2.0",
"dev": true, "dev": true,
@ -11709,28 +11691,6 @@
"react-dom": ">=16.8.0" "react-dom": ">=16.8.0"
} }
}, },
"node_modules/react-day-picker": {
"version": "9.14.0",
"resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.14.0.tgz",
"integrity": "sha512-tBaoDWjPwe0M5pGrum4H0SR6Lyk+BO9oHnp9JbKpGKW2mlraNPgP9BMfsg5pWpwrssARmeqk7YBl2oXutZTaHA==",
"license": "MIT",
"dependencies": {
"@date-fns/tz": "^1.4.1",
"@tabby_ai/hijri-converter": "1.0.5",
"date-fns": "^4.1.0",
"date-fns-jalali": "4.1.0-0"
},
"engines": {
"node": ">=18"
},
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/gpbl"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/react-dom": { "node_modules/react-dom": {
"version": "19.2.3", "version": "19.2.3",
"license": "MIT", "license": "MIT",

View file

@ -84,7 +84,6 @@
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"react": "^19.2.3", "react": "^19.2.3",
"react-colorful": "^5.6.1", "react-colorful": "^5.6.1",
"react-day-picker": "^9.14.0",
"react-dom": "^19.2.3", "react-dom": "^19.2.3",
"react-hook-form": "^7.72.1", "react-hook-form": "^7.72.1",
"react-hot-toast": "^2.5.2", "react-hot-toast": "^2.5.2",

View file

@ -0,0 +1,27 @@
import type React from "react";
import Input from "~/components/ui/input";
interface DateInputProps
extends Omit<
React.InputHTMLAttributes<HTMLInputElement>,
"type" | "value" | "onChange"
> {
value: Date | null;
onChange: (date: Date | null) => void;
}
export const DateInput = ({ value, onChange, ...rest }: DateInputProps) => {
return (
<Input
{...rest}
onChange={(e) => {
const date = new Date(e.currentTarget.value);
if (!Number.isNaN(date.getTime())) {
onChange(date);
}
}}
type="date"
value={value?.toISOString().split("T")[0] || ""}
/>
);
};

View file

@ -1,6 +1,5 @@
import { format } from "date-fns"; import { format } from "date-fns";
import { it } from "date-fns/locale"; import { Check, SlidersHorizontal } from "lucide-react"
import { CalendarIcon, Check, SlidersHorizontal } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { z } from "zod/v4"; import { z } from "zod/v4";
@ -23,10 +22,10 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "~/components/custom_ui/form"; } from "~/components/custom_ui/form";
import { DateInput } from "~/components/custom_ui/inputDate";
import { MultiSelect, UnpackOptions } from "~/components/custom_ui/multiselect"; import { MultiSelect, UnpackOptions } from "~/components/custom_ui/multiselect";
import { Badge } from "~/components/ui/badge"; import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
@ -36,11 +35,6 @@ import {
DialogTrigger, DialogTrigger,
} from "~/components/ui/dialog"; } from "~/components/ui/dialog";
import { Label } from "~/components/ui/label"; import { Label } from "~/components/ui/label";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { Slider } from "~/components/ui/slider"; import { Slider } from "~/components/ui/slider";
import { Switch } from "~/components/ui/switch"; import { Switch } from "~/components/ui/switch";
import { FieldResetButton } from "~/forms/comps"; import { FieldResetButton } from "~/forms/comps";
@ -526,42 +520,12 @@ const FormServizio = ({
</p> </p>
</div> </div>
) : ( ) : (
<Popover> <DateInput
<PopoverTrigger asChild> id="scadenza_motivazione_transitoria"
<FormControl> onChange={field.onChange}
<Button placeholder={t.anagrafica.scegli_data}
className={cn( value={field.value || new Date()}
"h-10 w-full bg-card pl-3 text-left font-medium", />
!field.value && "text-muted-foreground",
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
)}
id="scadenza_motivazione_transitoria"
variant={"outline"}
>
{field.value ? (
format(field.value, "PPP", {
locale: it,
})
) : (
<span>{t.anagrafica.scegli_data}</span>
)}
<CalendarIcon className="ml-auto size-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent align="end" className="w-auto p-0">
<Calendar
autoFocus
captionLayout="dropdown"
defaultMonth={field.value || new Date()}
endMonth={new Date(2050, 12)}
locale={it}
mode="single"
onSelect={field.onChange}
selected={field.value || undefined}
/>
</PopoverContent>
</Popover>
)} )}
<FormDescription> <FormDescription>
es. scadenza contratto di lavoro, fine corso di studi, ecc. es. scadenza contratto di lavoro, fine corso di studi, ecc.

View file

@ -1,532 +0,0 @@
"use client";
import { differenceInCalendarDays } from "date-fns";
import { ChevronLeft, ChevronRight } from "lucide-react";
import {
type Dispatch,
type HTMLAttributes,
type ReactNode,
type SetStateAction,
type TableHTMLAttributes,
useCallback,
useMemo,
useState,
} from "react";
import {
DayPicker,
type DayPickerProps,
labelNext,
labelPrevious,
useDayPicker,
} from "react-day-picker";
import { Button, buttonVariants } from "~/components/ui/button";
import { cn } from "~/lib/utils";
type CalendarProps = DayPickerProps & {
/**
* In the year view, the number of years to display at once.
* @default 12
*/
yearRange?: number;
/**
* Wether to show the year switcher in the caption.
* @default true
*/
showYearSwitcher?: boolean;
monthsClassName?: string;
monthCaptionClassName?: string;
weekdaysClassName?: string;
weekdayClassName?: string;
monthClassName?: string;
captionClassName?: string;
captionLabelClassName?: string;
buttonNextClassName?: string;
buttonPreviousClassName?: string;
navClassName?: string;
monthGridClassName?: string;
weekClassName?: string;
dayClassName?: string;
dayButtonClassName?: string;
rangeStartClassName?: string;
rangeEndClassName?: string;
selectedClassName?: string;
todayClassName?: string;
outsideClassName?: string;
disabledClassName?: string;
rangeMiddleClassName?: string;
hiddenClassName?: string;
};
type NavView = "days" | "years";
/**
* A custom calendar component built on top of react-day-picker.
* @param props The props for the calendar.
* @default yearRange 12
* @returns
*/
function Calendar({
className,
showOutsideDays = true,
showYearSwitcher = true,
yearRange = 12,
numberOfMonths,
...props
}: CalendarProps) {
const [navView, setNavView] = useState<NavView>("days");
const [displayYears, setDisplayYears] = useState<{
from: number;
to: number;
}>(
useMemo(() => {
const currentYear = new Date().getFullYear();
return {
from: currentYear - Math.floor(yearRange / 2 - 1),
to: currentYear + Math.ceil(yearRange / 2),
};
}, [yearRange]),
);
const { onPrevClick, startMonth, endMonth } = props;
const columnsDisplayed = navView === "years" ? 1 : numberOfMonths;
const _monthsClassName = cn("relative flex", props.monthsClassName);
const _monthCaptionClassName = cn(
"relative mx-10 flex h-7 items-center justify-center",
props.monthCaptionClassName,
);
const _weekdaysClassName = cn("flex flex-row", props.weekdaysClassName);
const _weekdayClassName = cn(
"w-8 text-sm font-normal text-muted-foreground",
props.weekdayClassName,
);
const _monthClassName = cn("w-full", props.monthClassName);
const _captionClassName = cn(
"relative flex items-center justify-center pt-1",
props.captionClassName,
);
const _captionLabelClassName = cn(
"truncate text-sm font-medium",
props.captionLabelClassName,
props.captionLayout === "dropdown" &&
"flex items-center text-sm font-medium border border-neutral-200 rounded-md px-2 py-1",
);
const buttonNavClassName = buttonVariants({
className:
"absolute size-7 bg-transparent p-0 opacity-50 hover:opacity-100",
variant: "outline",
});
const _buttonNextClassName = cn(
buttonNavClassName,
"right-0",
props.buttonNextClassName,
);
const _buttonPreviousClassName = cn(
buttonNavClassName,
"left-0",
props.buttonPreviousClassName,
);
const _navClassName = cn("flex items-start", props.navClassName);
const _monthGridClassName = cn("mx-auto mt-4", props.monthGridClassName);
const _weekClassName = cn("mt-2 flex w-max items-start", props.weekClassName);
const _dayClassName = cn(
"flex size-8 flex-1 items-center justify-center p-0 text-sm",
props.dayClassName,
);
const _dayButtonClassName = cn(
buttonVariants({ variant: "ghost" }),
"size-8 rounded-md p-0 font-normal transition-none aria-selected:opacity-100",
props.dayButtonClassName,
);
const buttonRangeClassName =
"bg-accent [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground";
const _rangeStartClassName = cn(
buttonRangeClassName,
"rounded-s-md",
props.rangeStartClassName,
);
const _rangeEndClassName = cn(
buttonRangeClassName,
"rounded-e-md",
props.rangeEndClassName,
);
const _rangeMiddleClassName = cn(
"bg-accent !text-foreground [&>button]:bg-transparent [&>button]:!text-foreground [&>button]:hover:bg-transparent [&>button]:hover:!text-foreground",
props.rangeMiddleClassName,
);
const _selectedClassName = cn(
"[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground",
props.selectedClassName,
);
const _todayClassName = cn(
"[&>button]:bg-accent [&>button]:text-accent-foreground",
props.todayClassName,
);
const _outsideClassName = cn(
"text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
props.outsideClassName,
);
const _disabledClassName = cn(
"text-muted-foreground opacity-50",
props.disabledClassName,
);
const _hiddenClassName = cn("invisible flex-1", props.hiddenClassName);
const _dropdownOverrideClassName = cn("rounded-md p-2 shadow-xs bg-card");
return (
<DayPicker
className={cn("p-3", className)}
classNames={{
button_next: _buttonNextClassName,
button_previous: _buttonPreviousClassName,
caption: _captionClassName,
caption_label: _captionLabelClassName,
day: _dayClassName,
day_button: _dayButtonClassName,
disabled: _disabledClassName,
hidden: _hiddenClassName,
month: _monthClassName,
month_caption: _monthCaptionClassName,
month_grid: _monthGridClassName,
months: _monthsClassName,
months_dropdown: _dropdownOverrideClassName,
nav: _navClassName,
outside: _outsideClassName,
range_end: _rangeEndClassName,
range_middle: _rangeMiddleClassName,
range_start: _rangeStartClassName,
selected: _selectedClassName,
today: _todayClassName,
week: _weekClassName,
weekday: _weekdayClassName,
weekdays: _weekdaysClassName,
years_dropdown: _dropdownOverrideClassName,
}}
components={{
// Dropdown: (props) => (
// <Dropdown className={_dropdownOverrideClassName} {...props} />
// ),
CaptionLabel: (props) => (
<CaptionLabel
displayYears={displayYears}
navView={navView}
setNavView={setNavView}
showYearSwitcher={showYearSwitcher}
{...props}
/>
),
Chevron: ({ orientation }) => {
const Icon = orientation === "left" ? ChevronLeft : ChevronRight;
return <Icon className="size-4" />;
},
MonthGrid: ({ className, children, ...props }) => (
<MonthGrid
className={className}
displayYears={displayYears}
endMonth={endMonth}
navView={navView}
setNavView={setNavView}
startMonth={startMonth}
{...props}
>
{children}
</MonthGrid>
),
Nav: ({ className }) => (
<Nav
className={className}
displayYears={displayYears}
endMonth={endMonth}
navView={navView}
onPrevClick={onPrevClick}
setDisplayYears={setDisplayYears}
startMonth={startMonth}
/>
),
}}
numberOfMonths={columnsDisplayed}
showOutsideDays={showOutsideDays}
style={{
width: `${248.8 * (columnsDisplayed ?? 1)}px`,
}}
{...props}
/>
);
}
Calendar.displayName = "Calendar";
function Nav({
className,
navView,
startMonth,
endMonth,
displayYears,
setDisplayYears,
onPrevClick,
onNextClick,
}: {
className?: string;
navView: NavView;
startMonth?: Date;
endMonth?: Date;
displayYears: { from: number; to: number };
setDisplayYears: Dispatch<SetStateAction<{ from: number; to: number }>>;
onPrevClick?: (date: Date) => void;
onNextClick?: (date: Date) => void;
}) {
const { nextMonth, previousMonth, goToMonth } = useDayPicker();
const isPreviousDisabled = (() => {
if (navView === "years") {
return (
(startMonth &&
differenceInCalendarDays(
new Date(displayYears.from - 1, 0, 1),
startMonth,
) < 0) ||
(endMonth &&
differenceInCalendarDays(
new Date(displayYears.from - 1, 0, 1),
endMonth,
) > 0)
);
}
return !previousMonth;
})();
const isNextDisabled = (() => {
if (navView === "years") {
return (
(startMonth &&
differenceInCalendarDays(
new Date(displayYears.to + 1, 0, 1),
startMonth,
) < 0) ||
(endMonth &&
differenceInCalendarDays(
new Date(displayYears.to + 1, 0, 1),
endMonth,
) > 0)
);
}
return !nextMonth;
})();
const handlePreviousClick = useCallback(() => {
if (!previousMonth) return;
if (navView === "years") {
setDisplayYears((prev) => ({
from: prev.from - (prev.to - prev.from + 1),
to: prev.to - (prev.to - prev.from + 1),
}));
onPrevClick?.(
new Date(
displayYears.from - (displayYears.to - displayYears.from),
0,
1,
),
);
return;
}
goToMonth(previousMonth);
onPrevClick?.(previousMonth);
}, [previousMonth, goToMonth]);
const handleNextClick = useCallback(() => {
if (!nextMonth) return;
if (navView === "years") {
setDisplayYears((prev) => ({
from: prev.from + (prev.to - prev.from + 1),
to: prev.to + (prev.to - prev.from + 1),
}));
onNextClick?.(
new Date(
displayYears.from + (displayYears.to - displayYears.from),
0,
1,
),
);
return;
}
goToMonth(nextMonth);
onNextClick?.(nextMonth);
}, [goToMonth, nextMonth]);
return (
<nav className={cn("flex items-center", className)}>
<Button
aria-label={
navView === "years"
? `Go to the previous ${
displayYears.to - displayYears.from + 1
} years`
: labelPrevious(previousMonth)
}
className="absolute left-0 size-7 bg-transparent p-0 opacity-80 hover:opacity-100"
disabled={isPreviousDisabled}
onClick={handlePreviousClick}
tabIndex={isPreviousDisabled ? undefined : -1}
type="button"
variant="outline"
>
<ChevronLeft className="size-4" />
</Button>
<Button
aria-label={
navView === "years"
? `Go to the next ${displayYears.to - displayYears.from + 1} years`
: labelNext(nextMonth)
}
className="absolute right-0 size-7 bg-transparent p-0 opacity-80 hover:opacity-100"
disabled={isNextDisabled}
onClick={handleNextClick}
tabIndex={isNextDisabled ? undefined : -1}
type="button"
variant="outline"
>
<ChevronRight className="size-4" />
</Button>
</nav>
);
}
function CaptionLabel({
children,
showYearSwitcher,
navView,
setNavView,
displayYears,
...props
}: {
showYearSwitcher?: boolean;
navView: NavView;
setNavView: Dispatch<SetStateAction<NavView>>;
displayYears: { from: number; to: number };
} & HTMLAttributes<HTMLSpanElement>) {
if (!showYearSwitcher) return <span {...props}>{children}</span>;
return (
<Button
className="h-7 w-full truncate font-medium text-sm"
onClick={() => setNavView((prev) => (prev === "days" ? "years" : "days"))}
size="sm"
variant="ghost"
>
{navView === "days"
? children
: `${displayYears.from} - ${displayYears.to}`}
</Button>
);
}
function MonthGrid({
className,
children,
displayYears,
startMonth,
endMonth,
navView,
setNavView,
...props
}: {
className?: string;
children: ReactNode;
displayYears: { from: number; to: number };
startMonth?: Date;
endMonth?: Date;
navView: NavView;
setNavView: Dispatch<SetStateAction<NavView>>;
} & TableHTMLAttributes<HTMLTableElement>) {
if (navView === "years") {
return (
<YearGrid
className={className}
displayYears={displayYears}
endMonth={endMonth}
navView={navView}
setNavView={setNavView}
startMonth={startMonth}
{...props}
/>
);
}
return (
<table className={className} {...props}>
{children}
</table>
);
}
function YearGrid({
className,
displayYears,
startMonth,
endMonth,
setNavView,
navView,
...props
}: {
className?: string;
displayYears: { from: number; to: number };
startMonth?: Date;
endMonth?: Date;
setNavView: Dispatch<SetStateAction<NavView>>;
navView: NavView;
} & HTMLAttributes<HTMLDivElement>) {
const { goToMonth, selected } = useDayPicker();
return (
<div className={cn("grid grid-cols-4 gap-y-2", className)} {...props}>
{Array.from(
{ length: displayYears.to - displayYears.from + 1 },
(_, i) => {
const isBefore =
differenceInCalendarDays(
new Date(displayYears.from + i, 11, 31),
// biome-ignore lint/style/noNonNullAssertion: <exists>
startMonth!,
) < 0;
const isAfter =
differenceInCalendarDays(
new Date(displayYears.from + i, 0, 0),
// biome-ignore lint/style/noNonNullAssertion: <exists>
endMonth!,
) > 0;
const isDisabled = isBefore || isAfter;
return (
<Button
className={cn(
"h-7 w-full font-normal text-foreground text-sm",
displayYears.from + i === new Date().getFullYear() &&
"bg-accent font-medium text-accent-foreground",
)}
disabled={navView === "years" ? isDisabled : undefined}
// biome-ignore lint/suspicious/noArrayIndexKey: <index is acceptable here>
key={i}
onClick={() => {
setNavView("days");
goToMonth(
new Date(
displayYears.from + i,
(selected as Date | undefined)?.getMonth() ?? 0,
),
);
}}
variant="ghost"
>
{displayYears.from + i}
</Button>
);
},
)}
</div>
);
}
export { Calendar };

View file

@ -1,7 +1,4 @@
import { format } from "date-fns";
import { it } from "date-fns/locale";
import { import {
CalendarIcon,
CodeSquare, CodeSquare,
Eye, Eye,
Printer, Printer,
@ -24,13 +21,13 @@ import {
FormMessage, FormMessage,
} from "~/components/custom_ui/form"; } from "~/components/custom_ui/form";
import { NumberInput } from "~/components/custom_ui/InputNumber"; import { NumberInput } from "~/components/custom_ui/InputNumber";
import { DateInput } from "~/components/custom_ui/inputDate";
import { DualInputLayout } from "~/components/custom_ui/inputLayouts"; import { DualInputLayout } from "~/components/custom_ui/inputLayouts";
import { import {
type ListOption, type ListOption,
MultiSelect, MultiSelect,
} from "~/components/custom_ui/multiselect"; } from "~/components/custom_ui/multiselect";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card"; import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import Input from "~/components/ui/input"; import Input from "~/components/ui/input";
import { PhoneInput } from "~/components/ui/phone-input"; import { PhoneInput } from "~/components/ui/phone-input";
@ -55,7 +52,6 @@ import { FieldResetButton } from "~/forms/comps";
import { filteredCaratteristiche } from "~/hooks/schedaAnnuncioUtils"; import { filteredCaratteristiche } from "~/hooks/schedaAnnuncioUtils";
import { NullableStringOnChange } from "~/lib/form_utils"; import { NullableStringOnChange } from "~/lib/form_utils";
import { getStorageUrl } from "~/lib/storage_utils"; import { getStorageUrl } from "~/lib/storage_utils";
import { cn } from "~/lib/utils";
import { useZodForm } from "~/lib/zodForm"; import { useZodForm } from "~/lib/zodForm";
import { StatusBadge } from "~/pages/area-riservata/admin/edit-annuncio/[id]"; import { StatusBadge } from "~/pages/area-riservata/admin/edit-annuncio/[id]";
import { useTranslation } from "~/providers/I18nProvider"; import { useTranslation } from "~/providers/I18nProvider";
@ -1178,42 +1174,12 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
</Button> </Button>
)} )}
</div> </div>
<Popover> <DateInput
<PopoverTrigger asChild> id="disponibile_da"
<FormControl> onChange={field.onChange}
<Button placeholder="Seleziona data"
className={cn( value={field.value}
"h-10 w-full bg-card pl-3 text-left font-medium", />
!field.value && "text-muted-foreground",
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
)}
id="disponibile_da"
variant={"outline"}
>
{field.value ? (
format(field.value, "PPP", {
locale: it,
})
) : (
<span>Scegli</span>
)}
<CalendarIcon className="ml-auto size-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent align="end" className="w-auto p-0">
<Calendar
autoFocus
captionLayout="dropdown"
defaultMonth={field.value || undefined}
endMonth={new Date(2050, 12)}
locale={it}
mode="single"
onSelect={field.onChange}
selected={field.value || undefined}
/>
</PopoverContent>
</Popover>
</FormItem> </FormItem>
)} )}
/> />

View file

@ -1,6 +1,4 @@
import { format } from "date-fns"; import { Trash2 } from "lucide-react";
import { it } from "date-fns/locale";
import { CalendarIcon, Trash2 } from "lucide-react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { z } from "zod/v4"; import { z } from "zod/v4";
import { Confirm } from "~/components/confirm"; import { Confirm } from "~/components/confirm";
@ -18,14 +16,9 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "~/components/custom_ui/form"; } from "~/components/custom_ui/form";
import { DateInput } from "~/components/custom_ui/inputDate";
import { MultiSelect } from "~/components/custom_ui/multiselect"; import { MultiSelect } from "~/components/custom_ui/multiselect";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { import {
Select, Select,
SelectContent, SelectContent,
@ -35,7 +28,7 @@ import {
} from "~/components/ui/select"; } from "~/components/ui/select";
import { Switch } from "~/components/ui/switch"; import { Switch } from "~/components/ui/switch";
import { PAYMENT_TYPES, type PaymentType } from "~/i18n/stripe"; import { PAYMENT_TYPES, type PaymentType } from "~/i18n/stripe";
import { cn, formatCurrency } from "~/lib/utils"; import { formatCurrency } from "~/lib/utils";
import { useZodForm } from "~/lib/zodForm"; import { useZodForm } from "~/lib/zodForm";
import { orderTypeEnum } from "~/schemas/public/OrderTypeEnum"; import { orderTypeEnum } from "~/schemas/public/OrderTypeEnum";
import type { Ordini } from "~/schemas/public/Ordini"; import type { Ordini } from "~/schemas/public/Ordini";
@ -212,42 +205,12 @@ export const FormEditOrder = ({ prezziario, data, close }: FormProps) => {
<FormLabel htmlFor="created_at">Data Ordine</FormLabel> <FormLabel htmlFor="created_at">Data Ordine</FormLabel>
<FormMessage /> <FormMessage />
</div> </div>
<Popover> <DateInput
<PopoverTrigger asChild> id="created_at"
<FormControl> onChange={field.onChange}
<Button placeholder="Seleziona data"
className={cn( value={field.value}
"h-10 w-full bg-card pl-3 text-left font-medium", />
!field.value && "text-muted-foreground",
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
)}
id="created_at"
variant={"outline"}
>
{field.value ? (
format(field.value, "PPP", {
locale: it,
})
) : (
<span>Scegli data</span>
)}
<CalendarIcon className="ml-auto size-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent align="end" className="w-auto p-0">
<Calendar
autoFocus
captionLayout="dropdown"
defaultMonth={new Date()}
endMonth={new Date(2050, 12)}
locale={it}
mode="single"
onSelect={field.onChange}
selected={field.value || undefined}
/>
</PopoverContent>
</Popover>
</FormItem> </FormItem>
)} )}
/> />

View file

@ -1,6 +1,5 @@
import { format } from "date-fns"; import { format } from "date-fns";
import { it } from "date-fns/locale"; import { it } from "date-fns/locale";
import { ChevronDownIcon } from "lucide-react";
import { z } from "zod"; import { z } from "zod";
import { Confirm } from "~/components/confirm"; import { Confirm } from "~/components/confirm";
import { import {
@ -11,14 +10,9 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "~/components/custom_ui/form"; } from "~/components/custom_ui/form";
import { DateInput } from "~/components/custom_ui/inputDate";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import Input from "~/components/ui/input"; import Input from "~/components/ui/input";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { Textarea } from "~/components/ui/textarea"; import { Textarea } from "~/components/ui/textarea";
import { useZodForm } from "~/lib/zodForm"; import { useZodForm } from "~/lib/zodForm";
import { useTranslation } from "~/providers/I18nProvider"; import { useTranslation } from "~/providers/I18nProvider";
@ -77,34 +71,12 @@ export const FormEditQueueMail = ({
<FormMessage /> <FormMessage />
</div> </div>
<FormControl> <FormControl>
<Popover> <DateInput
<PopoverTrigger asChild> id="date-picker-optional"
<Button onChange={field.onChange}
className="w-full justify-between bg-card font-normal" placeholder="Seleziona data"
id="date-picker-optional" value={field.value}
variant="outline" />
>
{field.value
? format(field.value, "PPP", { locale: it })
: "Seleziona data"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent
align="start"
className="w-auto overflow-hidden p-0"
>
<Calendar
captionLayout="dropdown"
defaultMonth={field.value}
mode="single"
onSelect={(date) => {
field.onChange(date);
}}
selected={field.value}
/>
</PopoverContent>
</Popover>
</FormControl> </FormControl>
</FormItem> </FormItem>
)} )}

View file

@ -1,6 +1,4 @@
import { format } from "date-fns"; import { X } from "lucide-react";
import { enUS, it } from "date-fns/locale";
import { CalendarIcon, X } from "lucide-react";
import { z } from "zod/v4"; import { z } from "zod/v4";
import { Counter } from "~/components/counter"; import { Counter } from "~/components/counter";
import { import {
@ -12,14 +10,9 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "~/components/custom_ui/form"; } from "~/components/custom_ui/form";
import { DateInput } from "~/components/custom_ui/inputDate";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import { Label } from "~/components/ui/label"; import { Label } from "~/components/ui/label";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { Switch } from "~/components/ui/switch"; import { Switch } from "~/components/ui/switch";
import { cn } from "~/lib/utils"; import { cn } from "~/lib/utils";
import { useZodForm } from "~/lib/zodForm"; import { useZodForm } from "~/lib/zodForm";
@ -80,8 +73,6 @@ export const FormEditServizio = ({
defaultValues: defaultValues, defaultValues: defaultValues,
}); });
const DatePickerLocale = locale === "it" ? it : enUS;
return ( return (
<Form {...form}> <Form {...form}>
<form className="space-y-8 px-0.5" onSubmit={form.handleSubmit(onSubmit)}> <form className="space-y-8 px-0.5" onSubmit={form.handleSubmit(onSubmit)}>
@ -168,42 +159,12 @@ export const FormEditServizio = ({
</FormLabel> </FormLabel>
<FormMessage /> <FormMessage />
</div> </div>
<Popover> <DateInput
<PopoverTrigger asChild> id="decorrenza"
<FormControl> onChange={field.onChange}
<Button placeholder={t.anagrafica.scegli_data}
className={cn( value={field.value}
"h-10 w-full bg-card pl-3 text-left font-medium", />
!field.value && "text-muted-foreground",
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
)}
id="decorrenza"
variant={"outline"}
>
{field.value ? (
format(field.value, "PPP", {
locale: DatePickerLocale,
})
) : (
<span>{t.anagrafica.scegli_data}</span>
)}
<CalendarIcon className="ml-auto size-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent align="end" className="w-auto p-0">
<Calendar
autoFocus
captionLayout="dropdown"
defaultMonth={field.value || new Date()}
endMonth={new Date(2050, 12)}
locale={DatePickerLocale}
mode="single"
onSelect={field.onChange}
selected={field.value || undefined}
/>
</PopoverContent>
</Popover>
</FormItem> </FormItem>
)} )}
/> />

View file

@ -1,6 +1,4 @@
import { format, isAfter } from "date-fns"; import { format, isAfter } from "date-fns";
import { it } from "date-fns/locale";
import { ChevronDownIcon } from "lucide-react";
import { useEffect } from "react"; import { useEffect } from "react";
import { useFormContext, useWatch } from "react-hook-form"; import { useFormContext, useWatch } from "react-hook-form";
import { z } from "zod/v4"; import { z } from "zod/v4";
@ -12,15 +10,10 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "~/components/custom_ui/form"; } from "~/components/custom_ui/form";
import { DateInput } from "~/components/custom_ui/inputDate";
import { MultiSelect } from "~/components/custom_ui/multiselect"; import { MultiSelect } from "~/components/custom_ui/multiselect";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import Input from "~/components/ui/input"; import Input from "~/components/ui/input";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { useZodForm } from "~/lib/zodForm"; import { useZodForm } from "~/lib/zodForm";
import { import {
type MailsTemplates, type MailsTemplates,
@ -137,34 +130,12 @@ export const FormAddCodaEmail = ({ submitMutation }: FormProps) => {
<FormMessage /> <FormMessage />
</div> </div>
<FormControl> <FormControl>
<Popover> <DateInput
<PopoverTrigger asChild> id="date-picker-optional"
<Button onChange={field.onChange}
className="w-full justify-between bg-card font-normal" placeholder="Seleziona data"
id="date-picker-optional" value={field.value}
variant="outline" />
>
{field.value
? format(field.value, "PPP", { locale: it })
: "Seleziona data"}
<ChevronDownIcon />
</Button>
</PopoverTrigger>
<PopoverContent
align="start"
className="w-auto overflow-hidden p-0"
>
<Calendar
captionLayout="dropdown"
defaultMonth={field.value}
mode="single"
onSelect={(date) => {
field.onChange(date);
}}
selected={field.value}
/>
</PopoverContent>
</Popover>
</FormControl> </FormControl>
</FormItem> </FormItem>
)} )}

View file

@ -1,6 +1,3 @@
import { format } from "date-fns";
import { it } from "date-fns/locale";
import { CalendarIcon } from "lucide-react";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { z } from "zod/v4"; import { z } from "zod/v4";
import { import {
@ -17,14 +14,9 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "~/components/custom_ui/form"; } from "~/components/custom_ui/form";
import { DateInput } from "~/components/custom_ui/inputDate";
import { MultiSelect } from "~/components/custom_ui/multiselect"; import { MultiSelect } from "~/components/custom_ui/multiselect";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { import {
Select, Select,
SelectContent, SelectContent,
@ -34,7 +26,7 @@ import {
} from "~/components/ui/select"; } from "~/components/ui/select";
import { Switch } from "~/components/ui/switch"; import { Switch } from "~/components/ui/switch";
import { PAYMENT_TYPES } from "~/i18n/stripe"; import { PAYMENT_TYPES } from "~/i18n/stripe";
import { cn, formatCurrency } from "~/lib/utils"; import { formatCurrency } from "~/lib/utils";
import { useZodForm } from "~/lib/zodForm"; import { useZodForm } from "~/lib/zodForm";
import { orderTypeEnum } from "~/schemas/public/OrderTypeEnum"; import { orderTypeEnum } from "~/schemas/public/OrderTypeEnum";
import { paymentStatusEnum } from "~/schemas/public/PaymentStatusEnum"; import { paymentStatusEnum } from "~/schemas/public/PaymentStatusEnum";
@ -195,42 +187,12 @@ export const FormNewOrder = ({
<FormLabel htmlFor="created_at">Data Ordine</FormLabel> <FormLabel htmlFor="created_at">Data Ordine</FormLabel>
<FormMessage /> <FormMessage />
</div> </div>
<Popover> <DateInput
<PopoverTrigger asChild> id="created_at"
<FormControl> onChange={field.onChange}
<Button placeholder="Seleziona data"
className={cn( value={field.value}
"h-10 w-full bg-card pl-3 text-left font-medium", />
!field.value && "text-muted-foreground",
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
)}
id="created_at"
variant={"outline"}
>
{field.value ? (
format(field.value, "PPP", {
locale: it,
})
) : (
<span>Scegli data</span>
)}
<CalendarIcon className="ml-auto size-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent align="end" className="w-auto p-0">
<Calendar
autoFocus
captionLayout="dropdown"
defaultMonth={new Date()}
endMonth={new Date(2050, 12)}
locale={it}
mode="single"
onSelect={field.onChange}
selected={field.value || undefined}
/>
</PopoverContent>
</Popover>
</FormItem> </FormItem>
)} )}
/> />

View file

@ -1,6 +1,4 @@
import { differenceInYears, format } from "date-fns"; import { differenceInYears } from "date-fns";
import { enUS, it } from "date-fns/locale";
import { CalendarIcon } from "lucide-react";
import { type Control, useWatch } from "react-hook-form"; import { type Control, useWatch } from "react-hook-form";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
import { z } from "zod/v4"; import { z } from "zod/v4";
@ -12,15 +10,10 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "~/components/custom_ui/form"; } from "~/components/custom_ui/form";
import { DateInput } from "~/components/custom_ui/inputDate";
import { MultiSelect } from "~/components/custom_ui/multiselect"; import { MultiSelect } from "~/components/custom_ui/multiselect";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import Input from "~/components/ui/input"; import Input from "~/components/ui/input";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { Separator } from "~/components/ui/separator"; import { Separator } from "~/components/ui/separator";
import { Switch } from "~/components/ui/switch"; import { Switch } from "~/components/ui/switch";
import { import {
@ -33,7 +26,6 @@ import {
checkFiscalCodeValidity, checkFiscalCodeValidity,
NullableStringOnChange, NullableStringOnChange,
} from "~/lib/form_utils"; } from "~/lib/form_utils";
import { cn } from "~/lib/utils";
import { useZodForm } from "~/lib/zodForm"; import { useZodForm } from "~/lib/zodForm";
import { useCatasto } from "~/providers/CatastoProvider"; import { useCatasto } from "~/providers/CatastoProvider";
import { useTranslation } from "~/providers/I18nProvider"; import { useTranslation } from "~/providers/I18nProvider";
@ -135,7 +127,6 @@ export const ProfileFormAnagrafica = ({
admin_override: false, admin_override: false,
}; };
const { locale, t } = useTranslation(); const { locale, t } = useTranslation();
const DatePickerLocale = locale === "it" ? it : enUS;
z.config(z.locales[locale]()); z.config(z.locales[locale]());
const form = useZodForm(schema, { const form = useZodForm(schema, {
@ -184,42 +175,12 @@ export const ProfileFormAnagrafica = ({
</FormLabel> </FormLabel>
<FormMessage /> <FormMessage />
</div> </div>
<Popover> <DateInput
<PopoverTrigger asChild> id="data_nascita"
<FormControl> onChange={field.onChange}
<Button placeholder={t.anagrafica.scegli_data}
className={cn( value={field.value}
"h-10 w-full bg-card pl-3 text-left font-medium", />
!field.value && "text-muted-foreground",
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
)}
id="data_nascita"
variant={"outline"}
>
{field.value ? (
format(field.value, "PPP", {
locale: DatePickerLocale,
})
) : (
<span>{t.anagrafica.scegli_data}</span>
)}
<CalendarIcon className="ml-auto size-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent align="end" className="w-auto p-0">
<Calendar
autoFocus
captionLayout="dropdown"
defaultMonth={field.value || undefined}
endMonth={new Date()}
locale={DatePickerLocale}
mode="single"
onSelect={field.onChange}
selected={field.value || undefined}
/>
</PopoverContent>
</Popover>
</FormItem> </FormItem>
)} )}
/> />

View file

@ -1,6 +1,6 @@
import { add, format, formatDuration, intervalToDuration } from "date-fns"; import { add, formatDuration, intervalToDuration } from "date-fns";
import { it } from "date-fns/locale"; import { it } from "date-fns/locale";
import { CalendarIcon, Trash2 } from "lucide-react"; import { Trash2 } from "lucide-react";
import { z } from "zod/v4"; import { z } from "zod/v4";
import { Confirm } from "~/components/confirm"; import { Confirm } from "~/components/confirm";
import { import {
@ -11,15 +11,9 @@ import {
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "~/components/custom_ui/form"; } from "~/components/custom_ui/form";
import { DateInput } from "~/components/custom_ui/inputDate";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import Input from "~/components/ui/input"; import Input from "~/components/ui/input";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { cn } from "~/lib/utils";
import { useZodForm } from "~/lib/zodForm"; import { useZodForm } from "~/lib/zodForm";
import { useTranslation } from "~/providers/I18nProvider"; import { useTranslation } from "~/providers/I18nProvider";
import type { Rinnovi } from "~/schemas/public/Rinnovi"; import type { Rinnovi } from "~/schemas/public/Rinnovi";
@ -91,46 +85,16 @@ export const FormRinnovo = ({
<FormLabel htmlFor="decorrenza">Decorrenza</FormLabel> <FormLabel htmlFor="decorrenza">Decorrenza</FormLabel>
<FormMessage /> <FormMessage />
</div> </div>
<DateInput
<Popover> id="decorrenza"
<PopoverTrigger asChild> onChange={field.onChange}
<FormControl> placeholder={t.anagrafica.scegli_data}
<Button value={field.value}
className={cn( />
"h-10 w-full bg-card pl-3 text-left font-medium",
!field.value && "text-muted-foreground",
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
)}
id="decorrenza"
variant={"outline"}
>
{field.value ? (
format(field.value, "PPP", {
locale: it,
})
) : (
<span>{t.anagrafica.scegli_data}</span>
)}
<CalendarIcon className="ml-auto size-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent align="end" className="w-auto p-0">
<Calendar
autoFocus
captionLayout="dropdown"
defaultMonth={field.value || new Date()}
endMonth={new Date(2050, 12)}
locale={it}
mode="single"
onSelect={field.onChange}
selected={field.value || undefined}
/>
</PopoverContent>
</Popover>
</FormItem> </FormItem>
)} )}
/> />
<FormField <FormField
control={form.control} control={form.control}
name="scadenza" name="scadenza"
@ -140,43 +104,12 @@ export const FormRinnovo = ({
<FormLabel htmlFor="scadenza">Scadenza</FormLabel> <FormLabel htmlFor="scadenza">Scadenza</FormLabel>
<FormMessage /> <FormMessage />
</div> </div>
<DateInput
<Popover> id="scadenza"
<PopoverTrigger asChild> onChange={field.onChange}
<FormControl> placeholder={t.anagrafica.scegli_data}
<Button value={field.value}
className={cn( />
"h-10 w-full bg-card pl-3 text-left font-medium",
!field.value && "text-muted-foreground",
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
)}
id="scadenza"
variant={"outline"}
>
{field.value ? (
format(field.value, "PPP", {
locale: it,
})
) : (
<span>{t.anagrafica.scegli_data}</span>
)}
<CalendarIcon className="ml-auto size-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent align="end" className="w-auto p-0">
<Calendar
autoFocus
captionLayout="dropdown"
defaultMonth={field.value || new Date()}
endMonth={new Date(2050, 12)}
locale={it}
mode="single"
onSelect={field.onChange}
selected={field.value || undefined}
/>
</PopoverContent>
</Popover>
</FormItem> </FormItem>
)} )}
/> />

View file

@ -1,7 +1,5 @@
"use client"; "use client";
import { format } from "date-fns"; import { Check, HelpCircleIcon, Mail } from "lucide-react";
import { enUS, it } from "date-fns/locale";
import { CalendarIcon, Check, HelpCircleIcon, Mail } from "lucide-react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { type Control, useWatch } from "react-hook-form"; import { type Control, useWatch } from "react-hook-form";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
@ -17,10 +15,10 @@ import {
FormMessage, FormMessage,
} from "~/components/custom_ui/form"; } from "~/components/custom_ui/form";
import InputWIcon from "~/components/custom_ui/input-icon"; import InputWIcon from "~/components/custom_ui/input-icon";
import { DateInput } from "~/components/custom_ui/inputDate";
import { MultiSelect, UnpackOptions } from "~/components/custom_ui/multiselect"; import { MultiSelect, UnpackOptions } from "~/components/custom_ui/multiselect";
import { Badge } from "~/components/ui/badge"; import { Badge } from "~/components/ui/badge";
import { Button } from "~/components/ui/button"; import { Button } from "~/components/ui/button";
import { Calendar } from "~/components/ui/calendar";
import { import {
Card, Card,
CardContent, CardContent,
@ -31,11 +29,6 @@ import {
import Input from "~/components/ui/input"; import Input from "~/components/ui/input";
import { Label } from "~/components/ui/label"; import { Label } from "~/components/ui/label";
import { PhoneInput } from "~/components/ui/phone-input"; import { PhoneInput } from "~/components/ui/phone-input";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { Separator } from "~/components/ui/separator"; import { Separator } from "~/components/ui/separator";
import { Slider } from "~/components/ui/slider"; import { Slider } from "~/components/ui/slider";
import { Switch } from "~/components/ui/switch"; import { Switch } from "~/components/ui/switch";
@ -291,7 +284,6 @@ export const FormServizioAcquisto = ({
const form = useZodForm(form_schema, { const form = useZodForm(form_schema, {
defaultValues: defaultValues, defaultValues: defaultValues,
}); });
const DatePickerLocale = locale === "it" ? it : enUS;
const { mutate } = api.servizio.processServizioOnboard.useMutation({ const { mutate } = api.servizio.processServizioOnboard.useMutation({
onError: (error) => { onError: (error) => {
toast.error(`Errore invio dati: ${error.message}`, { toast.error(`Errore invio dati: ${error.message}`, {
@ -734,42 +726,12 @@ export const FormServizioAcquisto = ({
</FormLabel> </FormLabel>
<FormMessage /> <FormMessage />
</div> </div>
<Popover> <DateInput
<PopoverTrigger asChild> id="scadenza_motivazione_transitoria"
<FormControl> onChange={field.onChange}
<Button placeholder={t.anagrafica.scegli_data}
className={cn( value={field.value}
"h-10 w-full bg-card pl-3 text-left font-medium", />
!field.value && "text-muted-foreground",
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
)}
id="scadenza_motivazione_transitoria"
variant={"outline"}
>
{field.value ? (
format(field.value, "PPP", {
locale: it,
})
) : (
<span>{t.anagrafica.scegli_data}</span>
)}
<CalendarIcon className="ml-auto size-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent align="end" className="w-auto p-0">
<Calendar
autoFocus
captionLayout="dropdown"
defaultMonth={field.value || new Date()}
endMonth={new Date(2050, 12)}
locale={it}
mode="single"
onSelect={field.onChange}
selected={field.value || undefined}
/>
</PopoverContent>
</Popover>
</FormItem> </FormItem>
)} )}
/> />
@ -908,42 +870,12 @@ export const FormServizioAcquisto = ({
</FormLabel> </FormLabel>
<FormMessage /> <FormMessage />
</div> </div>
<Popover> <DateInput
<PopoverTrigger asChild> id="dataNascita"
<FormControl> onChange={field.onChange}
<Button placeholder={t.anagrafica.scegli_data}
className={cn( value={field.value}
"h-10 w-full bg-card pl-3 text-left font-medium", />
!field.value && "text-muted-foreground",
"rounded-lg border border-neutral-300 shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm disabled:cursor-not-allowed disabled:opacity-50 dark:focus:border-transparent",
)}
id="dataNascita"
variant={"outline"}
>
{field.value ? (
format(field.value, "PPP", {
locale: DatePickerLocale,
})
) : (
<span>{t.anagrafica.scegli_data}</span>
)}
<CalendarIcon className="ml-auto size-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent align="end" className="w-auto p-0">
<Calendar
autoFocus
captionLayout="dropdown"
defaultMonth={field.value}
endMonth={new Date()}
locale={DatePickerLocale}
mode="single"
onSelect={field.onChange}
selected={field.value}
/>
</PopoverContent>
</Popover>
</FormItem> </FormItem>
)} )}
/> />

View file

@ -6,14 +6,13 @@ import type { ComponentProps, ReactElement, ReactNode } from "react";
import { Toaster } from "react-hot-toast"; import { Toaster } from "react-hot-toast";
import "~/styles/globals.css"; import "~/styles/globals.css";
import { ThemeProvider as NextThemesProvider } from "next-themes"; import { ThemeProvider as NextThemesProvider } from "next-themes";
import NextNProgress from "nextjs-progressbar";
import { NuqsAdapter } from "nuqs/adapters/next/pages";
import { Layout } from "~/components/Layout"; import { Layout } from "~/components/Layout";
import { I18nProvider } from "~/providers/I18nProvider"; import { I18nProvider } from "~/providers/I18nProvider";
import { SessionProvider } from "~/providers/SessionProvider"; import { SessionProvider } from "~/providers/SessionProvider";
import { api } from "~/utils/api"; import { api } from "~/utils/api";
import { inter } from "~/utils/fonts"; import { inter } from "~/utils/fonts";
import "react-day-picker/dist/style.css";
import NextNProgress from "nextjs-progressbar";
import { NuqsAdapter } from "nuqs/adapters/next/pages";
type ThemeProviderProps = ComponentProps<typeof NextThemesProvider>; type ThemeProviderProps = ComponentProps<typeof NextThemesProvider>;
export function ThemeProvider({ children, ...props }: ThemeProviderProps) { export function ThemeProvider({ children, ...props }: ThemeProviderProps) {