2025-08-28 18:27:07 +02:00
|
|
|
import { differenceInYears, format } from "date-fns";
|
|
|
|
|
import { enUS, it } from "date-fns/locale";
|
|
|
|
|
import { CalendarIcon } from "lucide-react";
|
2025-10-30 18:13:50 +01:00
|
|
|
import { type Control, useWatch } from "react-hook-form";
|
2025-08-28 18:27:07 +02:00
|
|
|
import toast from "react-hot-toast";
|
2025-08-07 14:50:40 +02:00
|
|
|
import { z } from "zod/v4";
|
2025-08-04 17:45:44 +02:00
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
Form,
|
|
|
|
|
FormControl,
|
|
|
|
|
FormField,
|
|
|
|
|
FormItem,
|
|
|
|
|
FormLabel,
|
|
|
|
|
FormMessage,
|
2025-08-04 17:45:44 +02:00
|
|
|
} from "~/components/custom_ui/form";
|
|
|
|
|
import Input from "~/components/custom_ui/input";
|
|
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
MultiSelect,
|
|
|
|
|
RepackValues,
|
|
|
|
|
UnpackOptions,
|
|
|
|
|
} from "~/components/custom_ui/multiselect";
|
|
|
|
|
import { Button } from "~/components/ui/button";
|
2025-08-04 17:45:44 +02:00
|
|
|
import { Calendar } from "~/components/ui/calendar";
|
|
|
|
|
import {
|
2025-08-28 18:27:07 +02:00
|
|
|
Popover,
|
|
|
|
|
PopoverContent,
|
|
|
|
|
PopoverTrigger,
|
|
|
|
|
} from "~/components/ui/popover";
|
2025-08-04 17:45:44 +02:00
|
|
|
import { Separator } from "~/components/ui/separator";
|
2025-08-28 18:27:07 +02:00
|
|
|
import { Switch } from "~/components/ui/switch";
|
2025-10-30 18:13:50 +01:00
|
|
|
import { getComuni } from "~/i18n/comuni";
|
2025-08-04 17:45:44 +02:00
|
|
|
import { GetNazioni } from "~/i18n/nazioni";
|
2025-10-30 18:13:50 +01:00
|
|
|
import { getProvinciaFromSigla, provincieWithSigla } from "~/i18n/provincie";
|
2025-08-04 17:45:44 +02:00
|
|
|
import { checkFiscalCodeValidity, getComuneFieldValue } from "~/lib/form_utils";
|
2025-08-28 18:27:07 +02:00
|
|
|
import { cn } from "~/lib/utils";
|
|
|
|
|
import { useZodForm } from "~/lib/zodForm";
|
|
|
|
|
import { useTranslation } from "~/providers/I18nProvider";
|
2025-08-04 17:45:44 +02:00
|
|
|
import type { UserWithAnagrafica } from "~/server/services/user.service";
|
2025-08-28 18:27:07 +02:00
|
|
|
import { api } from "~/utils/api";
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-10-30 18:13:50 +01:00
|
|
|
const profileFormSchema = z.object({
|
|
|
|
|
azienda: z.boolean(),
|
|
|
|
|
cap_residenza: z.string().optional(),
|
|
|
|
|
civico_residenza: z.string().optional(),
|
|
|
|
|
codice_destinatario: z.string().length(7).nullable(),
|
|
|
|
|
codice_fiscale: z.string().optional(),
|
|
|
|
|
comune_residenza: z.string().optional(),
|
|
|
|
|
data_nascita: z.date().optional(),
|
|
|
|
|
fatturazione_aziendale: z.boolean(),
|
|
|
|
|
legale_rappresentante: z.string().nullable(),
|
|
|
|
|
luogo_nascita: z.string().optional(),
|
|
|
|
|
nazione_nascita: z.string().optional(),
|
|
|
|
|
nazione_residenza: z.string().optional(),
|
|
|
|
|
p_iva: z.string().nullable(),
|
|
|
|
|
provincia_residenza: z.string().optional(),
|
|
|
|
|
ragione_sociale: z.string().nullable(),
|
|
|
|
|
sede_legale: z.string().nullable(),
|
|
|
|
|
sesso: z.string().optional(),
|
|
|
|
|
via_residenza: z.string().optional(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
type ProfileFormValues = z.infer<typeof profileFormSchema>;
|
2025-08-04 17:45:44 +02:00
|
|
|
export const ProfileFormAnagrafica = ({
|
2025-08-28 18:27:07 +02:00
|
|
|
userData,
|
2025-08-04 17:45:44 +02:00
|
|
|
}: {
|
2025-08-28 18:27:07 +02:00
|
|
|
userData: UserWithAnagrafica;
|
2025-08-04 17:45:44 +02:00
|
|
|
}) => {
|
2025-10-30 18:13:50 +01:00
|
|
|
const schema = profileFormSchema.superRefine(
|
|
|
|
|
(
|
|
|
|
|
{
|
|
|
|
|
data_nascita,
|
|
|
|
|
codice_fiscale,
|
|
|
|
|
sesso,
|
|
|
|
|
luogo_nascita,
|
|
|
|
|
nazione_nascita,
|
|
|
|
|
cap_residenza,
|
|
|
|
|
azienda,
|
|
|
|
|
p_iva,
|
|
|
|
|
ragione_sociale,
|
|
|
|
|
sede_legale,
|
|
|
|
|
legale_rappresentante,
|
|
|
|
|
fatturazione_aziendale,
|
|
|
|
|
codice_destinatario,
|
|
|
|
|
},
|
|
|
|
|
refinementContext,
|
|
|
|
|
) => {
|
|
|
|
|
if (azienda) {
|
|
|
|
|
if (!ragione_sociale || ragione_sociale.length < 1) {
|
|
|
|
|
refinementContext.issues.push({
|
|
|
|
|
code: "custom",
|
|
|
|
|
input: "",
|
|
|
|
|
message: "Inserisci la ragione sociale",
|
|
|
|
|
path: ["ragione_sociale"],
|
|
|
|
|
});
|
2025-08-28 18:27:07 +02:00
|
|
|
}
|
2025-10-30 18:13:50 +01:00
|
|
|
if (!sede_legale || sede_legale.length < 1) {
|
|
|
|
|
refinementContext.issues.push({
|
|
|
|
|
code: "custom",
|
|
|
|
|
input: "",
|
|
|
|
|
message: "Inserisci la sede legale",
|
|
|
|
|
path: ["sede_legale"],
|
|
|
|
|
});
|
2025-08-28 18:27:07 +02:00
|
|
|
}
|
2025-10-30 18:13:50 +01:00
|
|
|
if (!p_iva || p_iva.length < 1) {
|
|
|
|
|
refinementContext.issues.push({
|
|
|
|
|
code: "custom",
|
|
|
|
|
input: "",
|
|
|
|
|
message: "Inserisci la partita iva",
|
|
|
|
|
path: ["p_iva"],
|
|
|
|
|
});
|
2025-08-28 18:27:07 +02:00
|
|
|
}
|
2025-10-30 18:13:50 +01:00
|
|
|
if (!legale_rappresentante || legale_rappresentante.length < 1) {
|
|
|
|
|
refinementContext.issues.push({
|
|
|
|
|
code: "custom",
|
|
|
|
|
input: "",
|
|
|
|
|
message: "Inserisci il legale rappresentante",
|
|
|
|
|
path: ["legale_rappresentante"],
|
|
|
|
|
});
|
2025-08-28 18:27:07 +02:00
|
|
|
}
|
2025-10-30 18:13:50 +01:00
|
|
|
}
|
|
|
|
|
if (fatturazione_aziendale) {
|
|
|
|
|
if (!codice_destinatario || codice_destinatario.length !== 7) {
|
|
|
|
|
refinementContext.issues.push({
|
|
|
|
|
code: "custom",
|
|
|
|
|
input: "",
|
|
|
|
|
message: "Inserisci il codice destinatario",
|
|
|
|
|
path: ["codice_destinatario"],
|
2025-08-28 18:27:07 +02:00
|
|
|
});
|
|
|
|
|
}
|
2025-10-30 18:13:50 +01:00
|
|
|
}
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-10-30 18:13:50 +01:00
|
|
|
if (cap_residenza) {
|
|
|
|
|
if (cap_residenza.length !== 5) {
|
|
|
|
|
refinementContext.issues.push({
|
|
|
|
|
code: "custom",
|
|
|
|
|
input: "",
|
|
|
|
|
message: "Inserisci un CAP valido",
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data_nascita) {
|
|
|
|
|
const diff = differenceInYears(data_nascita, new Date());
|
|
|
|
|
if (diff === 0) {
|
|
|
|
|
refinementContext.issues.push({
|
|
|
|
|
code: "custom",
|
|
|
|
|
input: "",
|
|
|
|
|
message: "Inserisci una data valida",
|
|
|
|
|
path: ["data_nascita"],
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
codice_fiscale &&
|
|
|
|
|
codice_fiscale.length > 0 &&
|
|
|
|
|
data_nascita &&
|
|
|
|
|
sesso &&
|
|
|
|
|
luogo_nascita &&
|
|
|
|
|
nazione_nascita
|
|
|
|
|
) {
|
|
|
|
|
checkFiscalCodeValidity({
|
|
|
|
|
codiceFiscale: codice_fiscale,
|
|
|
|
|
cognome: userData.cognome?.toUpperCase() || "",
|
|
|
|
|
dataNascita: data_nascita,
|
|
|
|
|
luogoNascita: luogo_nascita,
|
|
|
|
|
nazioneNascita: nazione_nascita,
|
|
|
|
|
nome: userData.nome?.toUpperCase() || "",
|
|
|
|
|
path: "codice_fiscale",
|
|
|
|
|
refinementContext,
|
|
|
|
|
sesso,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
);
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
const defaultValues: ProfileFormValues = {
|
2025-08-29 16:18:32 +02:00
|
|
|
azienda: userData.azienda || false,
|
|
|
|
|
cap_residenza: userData.cap_residenza || "",
|
|
|
|
|
civico_residenza: userData.civico_residenza || "",
|
|
|
|
|
codice_destinatario: userData.codice_destinatario || null,
|
|
|
|
|
codice_fiscale: userData.codice_fiscale || "",
|
|
|
|
|
comune_residenza: userData.comune_residenza || "",
|
2025-08-28 18:27:07 +02:00
|
|
|
data_nascita: userData.data_nascita || new Date(),
|
2025-08-29 16:18:32 +02:00
|
|
|
fatturazione_aziendale: userData.fatturazione_aziendale || false,
|
|
|
|
|
legale_rappresentante: userData.legale_rappresentante || null,
|
2025-08-28 18:27:07 +02:00
|
|
|
luogo_nascita: userData.luogo_nascita || "",
|
|
|
|
|
nazione_nascita: userData.nazione_nascita || "",
|
|
|
|
|
nazione_residenza: userData.nazione_residenza || "",
|
2025-08-29 16:18:32 +02:00
|
|
|
p_iva: userData.p_iva || null,
|
|
|
|
|
provincia_residenza: userData.provincia_residenza || "",
|
2025-08-28 18:27:07 +02:00
|
|
|
ragione_sociale: userData.ragione_sociale || null,
|
|
|
|
|
sede_legale: userData.sede_legale || null,
|
2025-08-29 16:18:32 +02:00
|
|
|
sesso: userData.sesso || "",
|
|
|
|
|
via_residenza: userData.via_residenza || "",
|
2025-08-28 18:27:07 +02:00
|
|
|
};
|
|
|
|
|
const { locale, t } = useTranslation();
|
2025-10-30 18:13:50 +01:00
|
|
|
const DatePickerLocale = locale === "it" ? it : enUS;
|
2025-08-28 18:27:07 +02:00
|
|
|
z.config(z.locales[locale]());
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-10-30 18:13:50 +01:00
|
|
|
const form = useZodForm(schema, {
|
2025-08-28 18:27:07 +02:00
|
|
|
defaultValues: defaultValues,
|
|
|
|
|
});
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
const utils = api.useUtils();
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
const { mutate } = api.users.editUserAnagrafica.useMutation({
|
2025-08-29 16:18:32 +02:00
|
|
|
onError: (error) => {
|
|
|
|
|
toast.error(error.message);
|
|
|
|
|
},
|
2025-08-28 18:27:07 +02:00
|
|
|
onSuccess: async () => {
|
|
|
|
|
toast.success(t.profile.aggiornato);
|
|
|
|
|
await utils.auth.getSession.invalidate();
|
|
|
|
|
await utils.users.getUser.invalidate();
|
2025-11-10 16:27:15 +01:00
|
|
|
await utils.users.getClientProfilo.invalidate({
|
|
|
|
|
userId: userData.id,
|
|
|
|
|
});
|
2025-08-28 18:27:07 +02:00
|
|
|
},
|
|
|
|
|
});
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
function onSubmit(fields: ProfileFormValues) {
|
|
|
|
|
mutate({
|
2025-11-10 16:27:15 +01:00
|
|
|
userId: userData.id,
|
|
|
|
|
data: { ...fields },
|
2025-08-28 18:27:07 +02:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
const nazioni_options = GetNazioni();
|
2025-10-30 18:13:50 +01:00
|
|
|
const comuni_options = getComuni();
|
|
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<Form {...form}>
|
2025-10-30 18:13:50 +01:00
|
|
|
{/* <FormDebug control={form.control} /> */}
|
2025-08-28 18:27:07 +02:00
|
|
|
<form
|
|
|
|
|
className="h-full space-y-8 px-0.5"
|
2025-08-29 16:18:32 +02:00
|
|
|
onSubmit={form.handleSubmit(onSubmit)}
|
2025-08-28 18:27:07 +02:00
|
|
|
>
|
|
|
|
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
|
|
|
|
<FormField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name="data_nascita"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="flex w-full flex-col">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="data_nascita">
|
|
|
|
|
{t.anagrafica.dataNascita}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<Popover>
|
|
|
|
|
<PopoverTrigger asChild>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Button
|
|
|
|
|
className={cn(
|
|
|
|
|
"h-[42px] w-full pl-3 text-left font-medium",
|
|
|
|
|
!field.value && "text-muted-foreground",
|
2025-10-10 16:18:43 +02:00
|
|
|
`rounded-lg border border-neutral-300 bg-white text-primary shadow-xs outline-hidden file:border-0 file:bg-transparent file:font-medium file:text-sm hover:border-neutral-400 focus:border-neutral-400 disabled:cursor-not-allowed disabled:opacity-50 aria-expanded:border-neutral-400 dark:border-neutral-500 dark:bg-primary dark:text-white dark:aria-expanded:border-neutral-400 dark:focus:border-transparent dark:hover:border-neutral-400 dark:placeholder:text-neutral-400`,
|
2025-08-28 18:27:07 +02:00
|
|
|
)}
|
2025-08-29 16:18:32 +02:00
|
|
|
id="data_nascita"
|
|
|
|
|
variant={"outline"}
|
2025-08-28 18:27:07 +02:00
|
|
|
>
|
|
|
|
|
{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>
|
2025-08-29 16:18:32 +02:00
|
|
|
<PopoverContent align="start" className="w-auto p-0">
|
2025-08-28 18:27:07 +02:00
|
|
|
<Calendar
|
2025-08-29 16:18:32 +02:00
|
|
|
autoFocus
|
2025-08-28 18:27:07 +02:00
|
|
|
captionLayout="dropdown"
|
2025-08-29 16:18:32 +02:00
|
|
|
defaultMonth={field.value}
|
|
|
|
|
endMonth={new Date()}
|
|
|
|
|
locale={DatePickerLocale}
|
|
|
|
|
mode="single"
|
|
|
|
|
onSelect={field.onChange}
|
|
|
|
|
selected={field.value}
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
|
|
|
|
</PopoverContent>
|
|
|
|
|
</Popover>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
<FormField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name="nazione_nascita"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="select-naz">
|
|
|
|
|
{t.anagrafica.nazioneNascita}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
<FormControl>
|
|
|
|
|
<MultiSelect
|
|
|
|
|
defaultValue={
|
|
|
|
|
field.value
|
|
|
|
|
? RepackValues({
|
|
|
|
|
options: nazioni_options,
|
|
|
|
|
values: field.value,
|
|
|
|
|
})
|
|
|
|
|
: undefined
|
|
|
|
|
}
|
2025-08-29 16:18:32 +02:00
|
|
|
elementId="select-naz"
|
|
|
|
|
elementName="nazione_nascita"
|
|
|
|
|
isMulti={false}
|
2025-08-28 18:27:07 +02:00
|
|
|
onValueChange={async (value) => {
|
|
|
|
|
field.onChange(value.value);
|
|
|
|
|
await form.trigger("luogo_nascita");
|
|
|
|
|
}}
|
2025-08-29 16:18:32 +02:00
|
|
|
options={UnpackOptions({ options: nazioni_options })}
|
2025-08-28 18:27:07 +02:00
|
|
|
placeholder="Seleziona..."
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
<FormField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name="luogo_nascita"
|
|
|
|
|
render={({ field }) => {
|
2025-10-30 18:13:50 +01:00
|
|
|
if (form.watch("nazione_nascita") === "0") {
|
|
|
|
|
const options = comuni_options.map((c) => c.nome);
|
2025-08-28 18:27:07 +02:00
|
|
|
return (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="select-comune">
|
|
|
|
|
{t.anagrafica.luogoNascita}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
<FormControl>
|
|
|
|
|
<MultiSelect
|
|
|
|
|
defaultValue={
|
|
|
|
|
field.value
|
2025-10-30 18:13:50 +01:00
|
|
|
? getComuneFieldValue(field.value, options)
|
2025-08-28 18:27:07 +02:00
|
|
|
: undefined
|
|
|
|
|
}
|
2025-08-29 16:18:32 +02:00
|
|
|
elementId="select-comune"
|
|
|
|
|
elementName="luogo_nascita"
|
|
|
|
|
isMulti={false}
|
2025-08-28 18:27:07 +02:00
|
|
|
onValueChange={async (value) => {
|
|
|
|
|
field.onChange(value.value);
|
|
|
|
|
await form.trigger("luogo_nascita");
|
|
|
|
|
await form.trigger("codice_fiscale");
|
|
|
|
|
}}
|
2025-10-30 18:13:50 +01:00
|
|
|
options={UnpackOptions({ options })}
|
2025-08-28 18:27:07 +02:00
|
|
|
placeholder="Seleziona..."
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="luogoNascita">
|
|
|
|
|
{t.anagrafica.luogoNascita}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
id="luogoNascita"
|
|
|
|
|
onChange={async (v) => {
|
|
|
|
|
field.onChange(v.target.value);
|
|
|
|
|
await form.trigger("luogo_nascita");
|
|
|
|
|
await form.trigger("codice_fiscale");
|
|
|
|
|
}}
|
2025-08-29 16:18:32 +02:00
|
|
|
type="text"
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
|
|
|
|
<FormField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name="sesso"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="select-sesso">
|
|
|
|
|
{t.anagrafica.sesso}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<MultiSelect
|
|
|
|
|
defaultValue={t.anagrafica.sesso_options.filter(
|
|
|
|
|
(v) => v.value === field.value,
|
|
|
|
|
)}
|
2025-08-29 16:18:32 +02:00
|
|
|
elementId="select-sesso"
|
|
|
|
|
elementName="sesso"
|
|
|
|
|
isMulti={false}
|
2025-10-30 18:13:50 +01:00
|
|
|
onValueChange={async (value) => {
|
2025-08-28 18:27:07 +02:00
|
|
|
field.onChange(value.value);
|
2025-10-30 18:13:50 +01:00
|
|
|
await form.trigger("codice_fiscale");
|
2025-08-28 18:27:07 +02:00
|
|
|
}}
|
2025-08-29 16:18:32 +02:00
|
|
|
options={t.anagrafica.sesso_options}
|
|
|
|
|
placeholder=""
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-08-28 18:27:07 +02:00
|
|
|
<FormField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name="codice_fiscale"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="codice_fiscale">
|
|
|
|
|
{t.anagrafica.codiceFiscale}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
2025-08-29 16:18:32 +02:00
|
|
|
className="uppercase"
|
|
|
|
|
id="codice_fiscale"
|
2025-08-28 18:27:07 +02:00
|
|
|
onChange={async (v) => {
|
|
|
|
|
field.onChange(v.target.value.toUpperCase());
|
|
|
|
|
await form.trigger("codice_fiscale");
|
|
|
|
|
}}
|
|
|
|
|
type="text"
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
<FormField
|
|
|
|
|
control={form.control}
|
|
|
|
|
name="azienda"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="mt-6 w-full">
|
|
|
|
|
<div className="flex items-center justify-center gap-x-4">
|
|
|
|
|
<FormLabel htmlFor="azienda">Azienda?</FormLabel>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Switch
|
|
|
|
|
checked={field.value}
|
2025-08-29 16:18:32 +02:00
|
|
|
className="data-[state=checked]:bg-neutral-700"
|
|
|
|
|
id="azienda"
|
2025-08-28 18:27:07 +02:00
|
|
|
onCheckedChange={(v) => {
|
|
|
|
|
field.onChange(v);
|
|
|
|
|
if (!v) {
|
|
|
|
|
form.setValue("ragione_sociale", null);
|
|
|
|
|
form.setValue("sede_legale", null);
|
|
|
|
|
form.setValue("p_iva", null);
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2025-10-30 18:13:50 +01:00
|
|
|
|
|
|
|
|
<AziendaSection control={form.control} setValue={form.setValue} />
|
|
|
|
|
<FatturazioneSection control={form.control} />
|
|
|
|
|
|
|
|
|
|
<Separator />
|
|
|
|
|
|
|
|
|
|
<ResidenzaSection
|
|
|
|
|
control={form.control}
|
|
|
|
|
setValue={form.setValue}
|
|
|
|
|
trigger={form.trigger}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<Button type="submit">{t.profile.aggiorna}</Button>
|
|
|
|
|
</form>
|
|
|
|
|
</Form>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const AziendaSection = ({
|
|
|
|
|
control,
|
|
|
|
|
setValue,
|
|
|
|
|
}: {
|
|
|
|
|
control: Control<ProfileFormValues>;
|
|
|
|
|
// biome-ignore lint/suspicious/noExplicitAny: <fine here>
|
|
|
|
|
setValue: (field: keyof ProfileFormValues, value: any) => void;
|
|
|
|
|
}) => {
|
|
|
|
|
const { t } = useTranslation();
|
|
|
|
|
const azienda = useWatch({ control, name: "azienda" });
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div
|
|
|
|
|
className={cn(
|
|
|
|
|
"flex w-full flex-col items-start justify-between gap-4 sm:flex-row",
|
|
|
|
|
!azienda && "hidden",
|
|
|
|
|
)}
|
|
|
|
|
>
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="ragione_sociale"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="ragione_sociale">
|
|
|
|
|
{t.anagrafica.ragioneSociale}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
id="ragione_sociale"
|
|
|
|
|
type="text"
|
|
|
|
|
value={field.value || undefined}
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
2025-10-30 18:13:50 +01:00
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="sede_legale"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="sede_legale">
|
|
|
|
|
{t.anagrafica.sedeLegale}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
2025-08-28 18:27:07 +02:00
|
|
|
</div>
|
2025-10-30 18:13:50 +01:00
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
id="sede_legale"
|
|
|
|
|
type="text"
|
|
|
|
|
value={field.value || undefined}
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
2025-10-30 18:13:50 +01:00
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
className={cn(
|
|
|
|
|
"flex w-full flex-col items-start justify-between gap-4 sm:flex-row",
|
|
|
|
|
!azienda && "hidden",
|
|
|
|
|
)}
|
|
|
|
|
>
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="p_iva"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="p_iva">{t.anagrafica.p_iva}</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
id="p_iva"
|
|
|
|
|
type="text"
|
|
|
|
|
value={field.value || undefined}
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
2025-10-30 18:13:50 +01:00
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="legale_rappresentante"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="legale_rappresentante">
|
|
|
|
|
{t.anagrafica.legale_rappresentante}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
2025-08-28 18:27:07 +02:00
|
|
|
</div>
|
2025-10-30 18:13:50 +01:00
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
id="legale_rappresentante"
|
|
|
|
|
type="text"
|
|
|
|
|
value={field.value || undefined}
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="fatturazione_aziendale"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className={cn("py-2", !azienda && "hidden")}>
|
|
|
|
|
<div className="flex items-center justify-start gap-x-4">
|
|
|
|
|
<FormLabel htmlFor="fatturazione_aziendale">
|
|
|
|
|
Vuoi che la fatturazione sia intestata alla tua azienda?
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Switch
|
|
|
|
|
checked={field.value}
|
|
|
|
|
className="data-[state=checked]:bg-neutral-700"
|
|
|
|
|
id="fatturazione_aziendale"
|
|
|
|
|
onCheckedChange={(v) => {
|
|
|
|
|
field.onChange(v);
|
|
|
|
|
if (!v) {
|
|
|
|
|
setValue("codice_destinatario", null);
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const FatturazioneSection = ({
|
|
|
|
|
control,
|
|
|
|
|
}: {
|
|
|
|
|
control: Control<ProfileFormValues>;
|
|
|
|
|
}) => {
|
|
|
|
|
const fatturazione_aziendale = useWatch({
|
|
|
|
|
control,
|
|
|
|
|
name: "fatturazione_aziendale",
|
|
|
|
|
});
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="codice_destinatario"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem
|
|
|
|
|
className={cn("w-full", !fatturazione_aziendale && "hidden")}
|
|
|
|
|
>
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="codice_destinatario">
|
|
|
|
|
Codice destinatario (SDI)
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
id="codice_destinatario"
|
|
|
|
|
type="text"
|
|
|
|
|
value={field.value || undefined}
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
2025-10-30 18:13:50 +01:00
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-10-30 18:13:50 +01:00
|
|
|
const ResidenzaSection = ({
|
|
|
|
|
control,
|
|
|
|
|
setValue,
|
|
|
|
|
trigger,
|
|
|
|
|
}: {
|
|
|
|
|
control: Control<ProfileFormValues>;
|
|
|
|
|
// biome-ignore lint/suspicious/noExplicitAny: <fine here>
|
|
|
|
|
setValue: (field: keyof ProfileFormValues, value: any) => void;
|
|
|
|
|
trigger: (name?: keyof ProfileFormValues) => Promise<boolean>;
|
|
|
|
|
}) => {
|
|
|
|
|
const { t } = useTranslation();
|
|
|
|
|
const nazioni_options = GetNazioni();
|
|
|
|
|
const comuni_options = getComuni();
|
|
|
|
|
const nazione_residenza = useWatch({
|
|
|
|
|
control: control,
|
|
|
|
|
name: "nazione_residenza",
|
|
|
|
|
});
|
|
|
|
|
const provincia_residenza = useWatch({
|
|
|
|
|
control: control,
|
|
|
|
|
name: "provincia_residenza",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="nazione_residenza"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="nazione_residenza">
|
|
|
|
|
{t.recapiti.nazione}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<MultiSelect
|
|
|
|
|
defaultValue={
|
|
|
|
|
field.value
|
|
|
|
|
? RepackValues({
|
|
|
|
|
options: nazioni_options,
|
|
|
|
|
values: field.value,
|
|
|
|
|
})
|
|
|
|
|
: undefined
|
|
|
|
|
}
|
|
|
|
|
elementId="nazione_residenza"
|
|
|
|
|
elementName="nazione"
|
|
|
|
|
isMulti={false}
|
|
|
|
|
onValueChange={async (value) => {
|
|
|
|
|
setValue("provincia_residenza", "");
|
|
|
|
|
field.onChange(value.value);
|
|
|
|
|
await trigger("comune_residenza");
|
|
|
|
|
}}
|
|
|
|
|
options={UnpackOptions({ options: nazioni_options })}
|
|
|
|
|
placeholder="Seleziona"
|
|
|
|
|
/>
|
|
|
|
|
</FormItem>
|
2025-08-28 18:27:07 +02:00
|
|
|
)}
|
2025-10-30 18:13:50 +01:00
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="provincia_residenza"
|
|
|
|
|
render={({ field }) => {
|
|
|
|
|
const provinciaName =
|
|
|
|
|
field.value && getProvinciaFromSigla(field.value);
|
|
|
|
|
return (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="provincia_residenza">
|
|
|
|
|
{t.recapiti.provincia}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{nazione_residenza === "0" ? (
|
2025-08-28 18:27:07 +02:00
|
|
|
<MultiSelect
|
|
|
|
|
defaultValue={
|
2025-10-30 18:13:50 +01:00
|
|
|
field.value && provinciaName
|
|
|
|
|
? {
|
|
|
|
|
label: provinciaName,
|
|
|
|
|
value: field.value,
|
|
|
|
|
}
|
2025-08-28 18:27:07 +02:00
|
|
|
: undefined
|
|
|
|
|
}
|
2025-10-30 18:13:50 +01:00
|
|
|
elementId="provincia_residenza"
|
|
|
|
|
elementName="provincia"
|
2025-08-28 18:27:07 +02:00
|
|
|
isMulti={false}
|
2025-10-30 18:13:50 +01:00
|
|
|
onValueChange={(value) => {
|
2025-08-29 16:18:32 +02:00
|
|
|
field.onChange(value.value);
|
|
|
|
|
}}
|
2025-10-30 18:13:50 +01:00
|
|
|
options={provincieWithSigla.map((prov) => ({
|
|
|
|
|
label: prov.nome,
|
|
|
|
|
value: prov.sigla,
|
|
|
|
|
}))}
|
2025-08-28 18:27:07 +02:00
|
|
|
placeholder="Seleziona"
|
|
|
|
|
/>
|
2025-10-30 18:13:50 +01:00
|
|
|
) : (
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input {...field} id="provincia_residenza" type="text" />
|
|
|
|
|
</FormControl>
|
|
|
|
|
)}
|
|
|
|
|
</FormItem>
|
|
|
|
|
);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="comune_residenza"
|
|
|
|
|
render={({ field }) => {
|
|
|
|
|
if (nazione_residenza === "0") {
|
|
|
|
|
const options = comuni_options
|
|
|
|
|
.filter((comune) =>
|
|
|
|
|
provincia_residenza
|
|
|
|
|
? comune.provincia === provincia_residenza
|
|
|
|
|
: true,
|
|
|
|
|
)
|
|
|
|
|
.map((comune) => comune.nome);
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-10-30 18:13:50 +01:00
|
|
|
return (
|
2025-08-28 18:27:07 +02:00
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
2025-10-30 18:13:50 +01:00
|
|
|
<FormLabel htmlFor="select-comune">
|
|
|
|
|
{t.recapiti.comune}
|
2025-08-28 18:27:07 +02:00
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-10-30 18:13:50 +01:00
|
|
|
<FormControl>
|
2025-08-28 18:27:07 +02:00
|
|
|
<MultiSelect
|
|
|
|
|
defaultValue={
|
|
|
|
|
field.value
|
2025-10-30 18:13:50 +01:00
|
|
|
? getComuneFieldValue(field.value, options)
|
2025-08-28 18:27:07 +02:00
|
|
|
: undefined
|
|
|
|
|
}
|
2025-10-30 18:13:50 +01:00
|
|
|
elementId="select-comune"
|
|
|
|
|
elementName="comune_residenza"
|
2025-08-28 18:27:07 +02:00
|
|
|
isMulti={false}
|
2025-10-30 18:13:50 +01:00
|
|
|
onValueChange={async (value) => {
|
2025-08-29 16:18:32 +02:00
|
|
|
field.onChange(value.value);
|
2025-10-30 18:13:50 +01:00
|
|
|
await trigger("comune_residenza");
|
2025-08-29 16:18:32 +02:00
|
|
|
}}
|
2025-10-30 18:13:50 +01:00
|
|
|
options={UnpackOptions({
|
|
|
|
|
options: options,
|
|
|
|
|
})}
|
|
|
|
|
placeholder="Seleziona..."
|
2025-08-28 18:27:07 +02:00
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
2025-10-30 18:13:50 +01:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex w-full flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="comune_residenza">
|
|
|
|
|
{t.recapiti.comune}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
className="w-full"
|
|
|
|
|
id="comune_residenza"
|
|
|
|
|
onChange={async (v) => {
|
|
|
|
|
field.onChange(v.target.value);
|
|
|
|
|
await trigger("comune_residenza");
|
|
|
|
|
}}
|
|
|
|
|
type="text"
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="cap_residenza"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="cap_residenza">{t.recapiti.cap}</FormLabel>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-10-30 18:13:50 +01:00
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
id="cap_residenza"
|
|
|
|
|
placeholder="00100"
|
|
|
|
|
type="text"
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
|
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="via_residenza"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="via_residenza">
|
|
|
|
|
{t.recapiti.indirizzo}
|
|
|
|
|
</FormLabel>
|
|
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
id="via_residenza"
|
|
|
|
|
placeholder="Via Roma"
|
|
|
|
|
type="text"
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-10-30 18:13:50 +01:00
|
|
|
<FormField
|
|
|
|
|
control={control}
|
|
|
|
|
name="civico_residenza"
|
|
|
|
|
render={({ field }) => (
|
|
|
|
|
<FormItem className="w-full">
|
|
|
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
|
|
|
|
<FormLabel htmlFor="civico_residenza">
|
|
|
|
|
{t.recapiti.civico}
|
|
|
|
|
</FormLabel>
|
2025-08-04 17:45:44 +02:00
|
|
|
|
2025-10-30 18:13:50 +01:00
|
|
|
<FormMessage />
|
|
|
|
|
</div>
|
|
|
|
|
<FormControl>
|
|
|
|
|
<Input
|
|
|
|
|
{...field}
|
|
|
|
|
id="civico_residenza"
|
|
|
|
|
placeholder="50"
|
|
|
|
|
type="text"
|
|
|
|
|
/>
|
|
|
|
|
</FormControl>
|
|
|
|
|
</FormItem>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2025-08-28 18:27:07 +02:00
|
|
|
</>
|
|
|
|
|
);
|
2025-08-04 17:45:44 +02:00
|
|
|
};
|