834 lines
31 KiB
TypeScript
834 lines
31 KiB
TypeScript
|
|
import { z } from "zod";
|
||
|
|
import { useZodForm } from "~/lib/zodForm";
|
||
|
|
import {
|
||
|
|
Form,
|
||
|
|
FormControl,
|
||
|
|
FormField,
|
||
|
|
FormItem,
|
||
|
|
FormLabel,
|
||
|
|
FormMessage,
|
||
|
|
} from "~/components/custom_ui/form";
|
||
|
|
import Input from "~/components/custom_ui/input";
|
||
|
|
import { Button } from "~/components/ui/button";
|
||
|
|
import toast from "react-hot-toast";
|
||
|
|
import { customErrorMapWrapper } from "~/hooks/locale";
|
||
|
|
import { api } from "~/utils/api";
|
||
|
|
import { useTranslation } from "~/providers/I18nProvider";
|
||
|
|
import { differenceInYears, format } from "date-fns";
|
||
|
|
import {
|
||
|
|
Popover,
|
||
|
|
PopoverContent,
|
||
|
|
PopoverTrigger,
|
||
|
|
} from "~/components/ui/popover";
|
||
|
|
import { cn } from "~/lib/utils";
|
||
|
|
import { CalendarIcon } from "lucide-react";
|
||
|
|
import { Calendar } from "~/components/ui/calendar";
|
||
|
|
import {
|
||
|
|
MultiSelect,
|
||
|
|
RepackValues,
|
||
|
|
UnpackOptions,
|
||
|
|
} from "~/components/custom_ui/multiselect";
|
||
|
|
import { it, enUS } from "date-fns/locale";
|
||
|
|
import { Separator } from "~/components/ui/separator";
|
||
|
|
import { GetNazioni } from "~/i18n/nazioni";
|
||
|
|
import { provincie } from "~/i18n/provincie";
|
||
|
|
import { checkFiscalCodeValidity, getComuneFieldValue } from "~/lib/form_utils";
|
||
|
|
import { getComuniNames } from "~/i18n/comuni";
|
||
|
|
import type { UserWithAnagrafica } from "~/server/services/user.service";
|
||
|
|
import { Switch } from "~/components/ui/switch";
|
||
|
|
|
||
|
|
export const ProfileFormAnagrafica = ({
|
||
|
|
userData,
|
||
|
|
}: {
|
||
|
|
userData: UserWithAnagrafica;
|
||
|
|
}) => {
|
||
|
|
const profileFormSchema = z
|
||
|
|
.object({
|
||
|
|
data_nascita: z.coerce.date().optional(),
|
||
|
|
luogo_nascita: z.string().optional(),
|
||
|
|
sesso: z.string().optional(),
|
||
|
|
nazione_nascita: z.string().optional(),
|
||
|
|
codice_fiscale: z.string().optional(),
|
||
|
|
via_residenza: z.string().optional(),
|
||
|
|
civico_residenza: z.string().optional(),
|
||
|
|
cap_residenza: z.string().optional(),
|
||
|
|
comune_residenza: z.string().optional(),
|
||
|
|
provincia_residenza: z.string().optional(),
|
||
|
|
nazione_residenza: z.string().optional(),
|
||
|
|
azienda: z.boolean(),
|
||
|
|
fatturazione_aziendale: z.boolean(),
|
||
|
|
codice_destinatario: z.string().length(7).nullable(),
|
||
|
|
ragione_sociale: z.string().nullable(),
|
||
|
|
sede_legale: z.string().nullable(),
|
||
|
|
legale_rappresentante: z.string().nullable(),
|
||
|
|
p_iva: z.string().nullable(),
|
||
|
|
})
|
||
|
|
.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.addIssue({
|
||
|
|
code: z.ZodIssueCode.custom,
|
||
|
|
message: "Inserisci la ragione sociale",
|
||
|
|
path: ["ragione_sociale"],
|
||
|
|
});
|
||
|
|
}
|
||
|
|
if (!sede_legale || sede_legale.length < 1) {
|
||
|
|
refinementContext.addIssue({
|
||
|
|
code: z.ZodIssueCode.custom,
|
||
|
|
message: "Inserisci la sede legale",
|
||
|
|
path: ["sede_legale"],
|
||
|
|
});
|
||
|
|
}
|
||
|
|
if (!p_iva || p_iva.length < 1) {
|
||
|
|
refinementContext.addIssue({
|
||
|
|
code: z.ZodIssueCode.custom,
|
||
|
|
message: "Inserisci la partita iva",
|
||
|
|
path: ["p_iva"],
|
||
|
|
});
|
||
|
|
}
|
||
|
|
if (!legale_rappresentante || legale_rappresentante.length < 1) {
|
||
|
|
refinementContext.addIssue({
|
||
|
|
code: z.ZodIssueCode.custom,
|
||
|
|
message: "Inserisci il legale rappresentante",
|
||
|
|
path: ["legale_rappresentante"],
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (fatturazione_aziendale) {
|
||
|
|
if (!codice_destinatario || codice_destinatario.length != 7) {
|
||
|
|
refinementContext.addIssue({
|
||
|
|
code: z.ZodIssueCode.custom,
|
||
|
|
message: "Inserisci il codice destinatario",
|
||
|
|
path: ["codice_destinatario"],
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (cap_residenza) {
|
||
|
|
if (cap_residenza.length !== 5) {
|
||
|
|
refinementContext.addIssue({
|
||
|
|
code: z.ZodIssueCode.custom,
|
||
|
|
message: "Inserisci un CAP valido",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (data_nascita) {
|
||
|
|
const diff = differenceInYears(data_nascita, new Date());
|
||
|
|
if (diff === 0) {
|
||
|
|
refinementContext.addIssue({
|
||
|
|
code: z.ZodIssueCode.custom,
|
||
|
|
message: "Inserisci una data valida",
|
||
|
|
path: ["data_nascita"],
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (
|
||
|
|
codice_fiscale &&
|
||
|
|
data_nascita &&
|
||
|
|
sesso &&
|
||
|
|
luogo_nascita &&
|
||
|
|
nazione_nascita
|
||
|
|
) {
|
||
|
|
{
|
||
|
|
checkFiscalCodeValidity({
|
||
|
|
path: "codice_fiscale",
|
||
|
|
codiceFiscale: codice_fiscale,
|
||
|
|
cognome: userData.cognome?.toUpperCase() || "",
|
||
|
|
nome: userData.nome?.toUpperCase() || "",
|
||
|
|
dataNascita: data_nascita,
|
||
|
|
sesso,
|
||
|
|
refinementContext,
|
||
|
|
luogoNascita: luogo_nascita,
|
||
|
|
nazioneNascita: nazione_nascita,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
);
|
||
|
|
|
||
|
|
type ProfileFormValues = z.infer<typeof profileFormSchema>;
|
||
|
|
|
||
|
|
const defaultValues: ProfileFormValues = {
|
||
|
|
data_nascita: userData.data_nascita || new Date(),
|
||
|
|
luogo_nascita: userData.luogo_nascita || "",
|
||
|
|
nazione_nascita: userData.nazione_nascita || "",
|
||
|
|
codice_fiscale: userData.codice_fiscale || "",
|
||
|
|
via_residenza: userData.via_residenza || "",
|
||
|
|
civico_residenza: userData.civico_residenza || "",
|
||
|
|
cap_residenza: userData.cap_residenza || "",
|
||
|
|
comune_residenza: userData.comune_residenza || "",
|
||
|
|
provincia_residenza: userData.provincia_residenza || "",
|
||
|
|
nazione_residenza: userData.nazione_residenza || "",
|
||
|
|
sesso: userData.sesso || "",
|
||
|
|
azienda: userData.azienda || false,
|
||
|
|
ragione_sociale: userData.ragione_sociale || null,
|
||
|
|
sede_legale: userData.sede_legale || null,
|
||
|
|
legale_rappresentante: userData.legale_rappresentante || null,
|
||
|
|
p_iva: userData.p_iva || null,
|
||
|
|
fatturazione_aziendale: userData.fatturazione_aziendale || false,
|
||
|
|
codice_destinatario: userData.codice_destinatario || null,
|
||
|
|
};
|
||
|
|
const { locale, t } = useTranslation();
|
||
|
|
z.setErrorMap(customErrorMapWrapper(locale));
|
||
|
|
|
||
|
|
const form = useZodForm({
|
||
|
|
schema: profileFormSchema,
|
||
|
|
defaultValues: defaultValues,
|
||
|
|
});
|
||
|
|
|
||
|
|
const utils = api.useUtils();
|
||
|
|
|
||
|
|
const { mutate } = api.users.editUserAnagrafica.useMutation({
|
||
|
|
onSuccess: async () => {
|
||
|
|
toast.success(t.profile.aggiornato);
|
||
|
|
await utils.auth.getSession.invalidate();
|
||
|
|
await utils.users.getUser.invalidate();
|
||
|
|
await utils.users.getClientProfilo.invalidate();
|
||
|
|
},
|
||
|
|
onError: (error) => {
|
||
|
|
toast.error(error.message);
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
function onSubmit(fields: ProfileFormValues) {
|
||
|
|
mutate({
|
||
|
|
...fields,
|
||
|
|
userid: userData.id,
|
||
|
|
idanagrafica: userData.idanagrafica || undefined,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
const nazioni_options = GetNazioni();
|
||
|
|
const comuni_options = getComuniNames();
|
||
|
|
const azienda = form.watch("azienda");
|
||
|
|
const nazione_nascita = form.watch("nazione_nascita");
|
||
|
|
const nazione_residenza = form.watch("nazione_residenza");
|
||
|
|
const fatturazione_aziendale = form.watch("fatturazione_aziendale");
|
||
|
|
const DatePickerLocale = locale === "it" ? it : enUS;
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<Form {...form}>
|
||
|
|
<form
|
||
|
|
onSubmit={form.handleSubmit(onSubmit)}
|
||
|
|
className="h-full space-y-8 px-0.5"
|
||
|
|
>
|
||
|
|
<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
|
||
|
|
variant={"outline"}
|
||
|
|
id="data_nascita"
|
||
|
|
className={cn(
|
||
|
|
"h-[42px] w-full pl-3 text-left font-medium",
|
||
|
|
!field.value && "text-muted-foreground",
|
||
|
|
`text-primary dark:bg-primary rounded-lg border border-neutral-300 bg-white shadow-xs outline-hidden file:border-0 file:bg-transparent file:text-sm file:font-medium 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:text-white dark:placeholder:text-neutral-400 dark:hover:border-neutral-400 dark:focus:border-transparent dark:aria-expanded:border-neutral-400`,
|
||
|
|
)}
|
||
|
|
>
|
||
|
|
{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 className="w-auto p-0" align="start">
|
||
|
|
<Calendar
|
||
|
|
locale={DatePickerLocale}
|
||
|
|
endMonth={new Date()}
|
||
|
|
mode="single"
|
||
|
|
defaultMonth={field.value}
|
||
|
|
captionLayout="dropdown"
|
||
|
|
selected={field.value}
|
||
|
|
onSelect={field.onChange}
|
||
|
|
disabled={(date) =>
|
||
|
|
date > new Date() || date < new Date("1900-01-01")
|
||
|
|
}
|
||
|
|
// eslint-disable-next-line jsx-a11y/no-autofocus
|
||
|
|
autoFocus
|
||
|
|
/>
|
||
|
|
</PopoverContent>
|
||
|
|
</Popover>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
|
||
|
|
<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>
|
||
|
|
|
||
|
|
<FormControl>
|
||
|
|
<MultiSelect
|
||
|
|
elementId="select-naz"
|
||
|
|
elementName="nazione_nascita"
|
||
|
|
options={UnpackOptions({ options: nazioni_options })}
|
||
|
|
defaultValue={
|
||
|
|
field.value
|
||
|
|
? RepackValues({
|
||
|
|
options: nazioni_options,
|
||
|
|
values: field.value,
|
||
|
|
})
|
||
|
|
: undefined
|
||
|
|
}
|
||
|
|
onValueChange={async (value) => {
|
||
|
|
field.onChange(value.value);
|
||
|
|
await form.trigger("luogo_nascita");
|
||
|
|
}}
|
||
|
|
placeholder="Seleziona..."
|
||
|
|
isMulti={false}
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
|
||
|
|
<FormField
|
||
|
|
control={form.control}
|
||
|
|
name="luogo_nascita"
|
||
|
|
render={({ field }) => {
|
||
|
|
if (nazione_nascita === "0") {
|
||
|
|
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>
|
||
|
|
|
||
|
|
<FormControl>
|
||
|
|
<MultiSelect
|
||
|
|
elementId="select-comune"
|
||
|
|
elementName="luogo_nascita"
|
||
|
|
options={UnpackOptions({ options: comuni_options })}
|
||
|
|
defaultValue={
|
||
|
|
field.value
|
||
|
|
? getComuneFieldValue(field.value, comuni_options)
|
||
|
|
: undefined
|
||
|
|
}
|
||
|
|
onValueChange={async (value) => {
|
||
|
|
field.onChange(value.value);
|
||
|
|
await form.trigger("luogo_nascita");
|
||
|
|
await form.trigger("codice_fiscale");
|
||
|
|
}}
|
||
|
|
placeholder="Seleziona..."
|
||
|
|
isMulti={false}
|
||
|
|
/>
|
||
|
|
</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}
|
||
|
|
type="text"
|
||
|
|
id="luogoNascita"
|
||
|
|
onChange={async (v) => {
|
||
|
|
field.onChange(v.target.value);
|
||
|
|
await form.trigger("luogo_nascita");
|
||
|
|
await form.trigger("codice_fiscale");
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
</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
|
||
|
|
elementId="select-sesso"
|
||
|
|
elementName="sesso"
|
||
|
|
isMulti={false}
|
||
|
|
placeholder=""
|
||
|
|
defaultValue={t.anagrafica.sesso_options.filter(
|
||
|
|
(v) => v.value == field.value,
|
||
|
|
)}
|
||
|
|
options={t.anagrafica.sesso_options}
|
||
|
|
onValueChange={(value) => {
|
||
|
|
field.onChange(value.value);
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
|
||
|
|
<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}
|
||
|
|
onChange={async (v) => {
|
||
|
|
field.onChange(v.target.value.toUpperCase());
|
||
|
|
await form.trigger("codice_fiscale");
|
||
|
|
}}
|
||
|
|
type="text"
|
||
|
|
className="uppercase"
|
||
|
|
id="codice_fiscale"
|
||
|
|
/>
|
||
|
|
</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}
|
||
|
|
onCheckedChange={(v) => {
|
||
|
|
field.onChange(v);
|
||
|
|
if (!v) {
|
||
|
|
form.setValue("ragione_sociale", null);
|
||
|
|
form.setValue("sede_legale", null);
|
||
|
|
form.setValue("p_iva", null);
|
||
|
|
}
|
||
|
|
}}
|
||
|
|
id="azienda"
|
||
|
|
className="data-[state=checked]:bg-neutral-700"
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
<FormMessage />
|
||
|
|
</div>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
{azienda && (
|
||
|
|
<>
|
||
|
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
||
|
|
<FormField
|
||
|
|
control={form.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}
|
||
|
|
type="text"
|
||
|
|
id="ragione_sociale"
|
||
|
|
value={field.value || undefined}
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
<FormField
|
||
|
|
control={form.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 />
|
||
|
|
</div>
|
||
|
|
<FormControl>
|
||
|
|
<Input
|
||
|
|
{...field}
|
||
|
|
type="text"
|
||
|
|
id="sede_legale"
|
||
|
|
value={field.value || undefined}
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
||
|
|
<FormField
|
||
|
|
control={form.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}
|
||
|
|
type="text"
|
||
|
|
id="p_iva"
|
||
|
|
value={field.value || undefined}
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
<FormField
|
||
|
|
control={form.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 />
|
||
|
|
</div>
|
||
|
|
<FormControl>
|
||
|
|
<Input
|
||
|
|
{...field}
|
||
|
|
type="text"
|
||
|
|
id="legale_rappresentante"
|
||
|
|
value={field.value || undefined}
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<FormField
|
||
|
|
control={form.control}
|
||
|
|
name="fatturazione_aziendale"
|
||
|
|
render={({ field }) => (
|
||
|
|
<FormItem className="py-2">
|
||
|
|
<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}
|
||
|
|
onCheckedChange={(v) => {
|
||
|
|
field.onChange(v);
|
||
|
|
if (!v) {
|
||
|
|
form.setValue("codice_destinatario", null);
|
||
|
|
}
|
||
|
|
}}
|
||
|
|
id="fatturazione_aziendale"
|
||
|
|
className="data-[state=checked]:bg-neutral-700"
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
<FormMessage />
|
||
|
|
</div>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
{fatturazione_aziendale && (
|
||
|
|
<FormField
|
||
|
|
control={form.control}
|
||
|
|
name="codice_destinatario"
|
||
|
|
render={({ field }) => (
|
||
|
|
<FormItem className="w-full">
|
||
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
||
|
|
<FormLabel htmlFor="codice_destinatario">
|
||
|
|
Codice destinatario (SDI)
|
||
|
|
</FormLabel>
|
||
|
|
<FormMessage />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<FormControl>
|
||
|
|
<Input
|
||
|
|
{...field}
|
||
|
|
type="text"
|
||
|
|
id="codice_destinatario"
|
||
|
|
value={field.value || undefined}
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
)}
|
||
|
|
</>
|
||
|
|
)}
|
||
|
|
<Separator />
|
||
|
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
||
|
|
<FormField
|
||
|
|
control={form.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
|
||
|
|
elementId="nazione_residenza"
|
||
|
|
options={UnpackOptions({ options: nazioni_options })}
|
||
|
|
onValueChange={async (value) => {
|
||
|
|
form.setValue("provincia_residenza", "");
|
||
|
|
field.onChange(value.value);
|
||
|
|
await form.trigger("comune_residenza");
|
||
|
|
}}
|
||
|
|
defaultValue={
|
||
|
|
field.value
|
||
|
|
? RepackValues({
|
||
|
|
options: nazioni_options,
|
||
|
|
values: field.value,
|
||
|
|
})
|
||
|
|
: undefined
|
||
|
|
}
|
||
|
|
elementName="nazione"
|
||
|
|
isMulti={false}
|
||
|
|
placeholder="Seleziona"
|
||
|
|
/>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
|
||
|
|
<FormField
|
||
|
|
control={form.control}
|
||
|
|
name="provincia_residenza"
|
||
|
|
render={({ field }) => (
|
||
|
|
<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" ? (
|
||
|
|
<MultiSelect
|
||
|
|
elementId="provincia_residenza"
|
||
|
|
options={UnpackOptions({ options: provincie })}
|
||
|
|
onValueChange={(value) => {
|
||
|
|
field.onChange(value.value);
|
||
|
|
}}
|
||
|
|
defaultValue={
|
||
|
|
field.value
|
||
|
|
? RepackValues({
|
||
|
|
options: provincie,
|
||
|
|
values: field.value,
|
||
|
|
})
|
||
|
|
: undefined
|
||
|
|
}
|
||
|
|
elementName="provincia"
|
||
|
|
isMulti={false}
|
||
|
|
placeholder="Seleziona"
|
||
|
|
/>
|
||
|
|
) : (
|
||
|
|
<FormControl>
|
||
|
|
<Input {...field} type="text" id="provincia_residenza" />
|
||
|
|
</FormControl>
|
||
|
|
)}
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
||
|
|
<FormField
|
||
|
|
control={form.control}
|
||
|
|
name="comune_residenza"
|
||
|
|
render={({ field }) => {
|
||
|
|
if (nazione_residenza === "0") {
|
||
|
|
return (
|
||
|
|
<FormItem className="w-full">
|
||
|
|
<div className="flex flex-wrap items-center gap-x-2">
|
||
|
|
<FormLabel htmlFor="select-comune">
|
||
|
|
{t.recapiti.comune}
|
||
|
|
</FormLabel>
|
||
|
|
<FormMessage />
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<FormControl>
|
||
|
|
<MultiSelect
|
||
|
|
elementId="select-comune"
|
||
|
|
elementName="comune_residenza"
|
||
|
|
options={UnpackOptions({ options: comuni_options })}
|
||
|
|
defaultValue={
|
||
|
|
field.value
|
||
|
|
? getComuneFieldValue(field.value, comuni_options)
|
||
|
|
: undefined
|
||
|
|
}
|
||
|
|
onValueChange={async (value) => {
|
||
|
|
field.onChange(value.value);
|
||
|
|
await form.trigger("comune_residenza");
|
||
|
|
}}
|
||
|
|
placeholder="Seleziona..."
|
||
|
|
isMulti={false}
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
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}
|
||
|
|
type="text"
|
||
|
|
id="comune_residenza"
|
||
|
|
className="w-full"
|
||
|
|
onChange={async (v) => {
|
||
|
|
field.onChange(v.target.value);
|
||
|
|
await form.trigger("comune_residenza");
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
);
|
||
|
|
}}
|
||
|
|
/>
|
||
|
|
<FormField
|
||
|
|
control={form.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>
|
||
|
|
|
||
|
|
<FormMessage />
|
||
|
|
</div>
|
||
|
|
<FormControl>
|
||
|
|
<Input
|
||
|
|
{...field}
|
||
|
|
type="text"
|
||
|
|
id="cap_residenza"
|
||
|
|
placeholder="00100"
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
||
|
|
<FormField
|
||
|
|
control={form.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}
|
||
|
|
type="text"
|
||
|
|
id="via_residenza"
|
||
|
|
placeholder="Via Roma"
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
|
||
|
|
<FormField
|
||
|
|
control={form.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>
|
||
|
|
|
||
|
|
<FormMessage />
|
||
|
|
</div>
|
||
|
|
<FormControl>
|
||
|
|
<Input
|
||
|
|
{...field}
|
||
|
|
type="text"
|
||
|
|
id="civico_residenza"
|
||
|
|
placeholder="50"
|
||
|
|
/>
|
||
|
|
</FormControl>
|
||
|
|
</FormItem>
|
||
|
|
)}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<Button type="submit">{t.profile.aggiorna}</Button>
|
||
|
|
</form>
|
||
|
|
</Form>
|
||
|
|
</>
|
||
|
|
);
|
||
|
|
};
|