infoalloggi-monorepo/apps/infoalloggi/src/forms/FormNewServizioAcquisto.tsx

1494 lines
56 KiB
TypeScript

"use client";
import { z } from "zod/v4";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "~/components/custom_ui/form";
import { useZodForm } from "~/lib/zodForm";
import { api } from "~/utils/api";
import { Button } from "~/components/ui/button";
import { useTranslation } from "~/providers/I18nProvider";
import { cn } from "~/lib/utils";
import type { Users, UsersId } from "~/schemas/public/Users";
import {
MultiSelect,
RepackValues,
UnpackOptions,
} from "~/components/custom_ui/multiselect";
import { Switch } from "~/components/ui/switch";
import type { UsersAnagrafica } from "~/schemas/public/UsersAnagrafica";
import Input from "~/components/custom_ui/input";
import { checkFiscalCodeValidity, getComuneFieldValue } from "~/lib/form_utils";
import InputWIcon from "~/components/custom_ui/input-icon";
import { CalendarIcon, HelpCircleIcon, Mail } from "lucide-react";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "~/components/ui/popover";
import { format } from "date-fns";
import { Calendar } from "~/components/ui/calendar";
import { enUS, it } from "date-fns/locale";
import { GetNazioni } from "~/i18n/nazioni";
import { getComuniNames } from "~/i18n/comuni";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "~/components/ui/tooltip";
import { provincie } from "~/i18n/provincie";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import type { Servizio } from "~/schemas/public/Servizio";
import toast from "react-hot-toast";
import { Counter } from "~/components/counter";
import { Slider } from "~/components/ui/slider";
import { Label } from "~/components/ui/label";
import { Badge } from "~/components/ui/badge";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import { useRouter } from "next/router";
import { Separator } from "~/components/ui/separator";
import { PhoneInput } from "~/components/phone-input";
type InitialData = {
servizio: Servizio;
userData: Pick<Users, "id" | "nome" | "cognome" | "email" | "telefono">;
anagrafica: UsersAnagrafica | undefined;
};
export const FormNewServizioAcquisto = ({
initialData,
userId,
isAdmin = false,
}: {
initialData: InitialData;
userId: UsersId;
isAdmin?: boolean;
}) => {
const router = useRouter();
const Schema = z
.object({
nome: z.string().nonempty("Inserisci un nome valido"),
cognome: z.string().nonempty("Inserisci un cognome valido"),
azienda: z.boolean(),
fatturazione_aziendale: z.boolean(),
codice_destinatario: z.string().nullable(),
ragione_sociale: z.string().nullable(),
sede_legale: z.string().nullable(),
legale_rappresentante: z.string().nullable(),
p_iva: z.string().nullable(),
email: z.email(),
telefono: z.string(),
sesso: z.string(),
data_nascita: z.date(),
luogo_nascita: z.string(),
nazione_nascita: z.string(),
codice_fiscale: z.string(),
indirizzo_recapiti: z.string().nonempty("Inserisci un indirizzo"),
civico_recapiti: z.string().nonempty("Inserisci un civico"),
cap_recapiti: z.string().length(5),
citta_recapiti: z.string().nonempty("Inserisci una città"),
provincia_recapiti: z
.string()
.refine((v) => v !== "", { params: { type: "provincia" } }),
nazione_recapiti: z
.string()
.refine((v) => v !== "", { params: { type: "nazione" } }),
tipologia: z.custom<TipologiaPosizioneEnum>(),
budget: z.number().positive(),
entromese: z.number().nullable(),
n_adulti: z.number().min(1),
n_minori: z.number(),
permanenza: z.number().nullable(),
motivazione_transitorio: z.string().nullable(),
reddito: z.string().nullable(),
arredato: z.boolean(),
animali: z.boolean(),
fumatori: z.boolean(),
giardino: z.boolean(),
parcheggio: z.boolean(),
terrazzo: z.boolean(),
ascensore: z.boolean(),
pianoterra: z.boolean(),
skipOrdine: z.boolean(),
})
.superRefine(
(
{
telefono,
codice_fiscale,
sesso,
cognome,
nome,
data_nascita,
luogo_nascita,
nazione_nascita,
n_adulti,
permanenza,
entromese,
motivazione_transitorio,
reddito,
azienda,
p_iva,
sede_legale,
legale_rappresentante,
ragione_sociale,
fatturazione_aziendale,
codice_destinatario,
},
refinementContext,
) => {
if (entromese === null) {
refinementContext.issues.push({
code: "custom",
message: "Inserisci il mese di inizio",
path: ["entromese"],
input: "",
});
}
if (azienda) {
if (!ragione_sociale || ragione_sociale.length < 1) {
refinementContext.issues.push({
code: "custom",
message: "Inserisci la ragione sociale",
path: ["ragione_sociale"],
input: "",
});
}
if (!sede_legale || sede_legale.length < 1) {
refinementContext.issues.push({
code: "custom",
message: "Inserisci la sede legale",
path: ["sede_legale"],
input: "",
});
}
if (!p_iva || p_iva.length < 1) {
refinementContext.issues.push({
code: "custom",
message: "Inserisci la partita iva",
path: ["p_iva"],
input: "",
});
}
if (!legale_rappresentante || legale_rappresentante.length < 1) {
refinementContext.issues.push({
code: "custom",
message: "Inserisci il legale rappresentante",
path: ["legale_rappresentante"],
input: "",
});
}
}
if (fatturazione_aziendale) {
if (!codice_destinatario || codice_destinatario.length != 7) {
refinementContext.issues.push({
code: "custom",
message: "Inserisci un codice destinatario valido",
path: ["codice_destinatario"],
input: "",
});
}
}
if (!telefono || telefono.length < 10) {
refinementContext.issues.push({
code: "custom",
message:
"Il numero di telefono deve essere lungo almeno 10 caratteri",
input: "",
});
}
checkFiscalCodeValidity({
path: "codice_fiscale",
codiceFiscale: codice_fiscale,
cognome,
nome,
dataNascita: data_nascita,
sesso,
refinementContext,
luogoNascita: luogo_nascita,
nazioneNascita: nazione_nascita,
});
if (n_adulti <= 0) {
refinementContext.issues.push({
code: "custom",
message: "Inserisci il numero di persone",
path: ["n_adulti"],
input: "",
});
}
if (
permanenza === null &&
tipologia === TipologiaPosizioneEnum.Transitorio
) {
refinementContext.issues.push({
code: "custom",
message: "Inserisci permanenza",
path: ["permanenza"],
input: "",
});
}
if (tipologia === TipologiaPosizioneEnum.Transitorio) {
if (
motivazione_transitorio === "" ||
motivazione_transitorio === null
) {
refinementContext.issues.push({
code: "custom",
message: "Inserisci la motivazione",
path: ["motivazione_transitorio"],
input: "",
});
}
} else {
if (reddito === "" || reddito === null) {
refinementContext.issues.push({
code: "custom",
message: "Inserisci il reddito",
path: ["reddito"],
input: "",
});
}
}
},
);
type FormValues = z.infer<typeof Schema>;
// This can come from your database or API.
const defaultValues: FormValues = {
...initialData.userData,
azienda: initialData.anagrafica?.azienda || false,
ragione_sociale: initialData.anagrafica?.ragione_sociale || "",
sede_legale: initialData.anagrafica?.sede_legale || "",
legale_rappresentante: initialData.anagrafica?.legale_rappresentante || "",
p_iva: initialData.anagrafica?.p_iva || "",
luogo_nascita: initialData.anagrafica?.luogo_nascita || "",
nazione_nascita: initialData.anagrafica?.nazione_nascita || "",
codice_fiscale: initialData.anagrafica?.codice_fiscale || "",
sesso: initialData.anagrafica?.sesso || "M",
data_nascita: initialData.anagrafica?.data_nascita
? new Date(initialData.anagrafica.data_nascita)
: new Date(),
nazione_recapiti: initialData.anagrafica?.nazione_residenza || "",
provincia_recapiti: initialData.anagrafica?.provincia_residenza || "",
citta_recapiti: initialData.anagrafica?.comune_residenza || "",
indirizzo_recapiti: initialData.anagrafica?.via_residenza || "",
civico_recapiti: initialData.anagrafica?.civico_residenza || "",
cap_recapiti: initialData.anagrafica?.cap_residenza || "",
fatturazione_aziendale:
initialData.anagrafica?.fatturazione_aziendale || false,
codice_destinatario: initialData.anagrafica?.codice_destinatario || "",
...initialData.servizio,
skipOrdine: false,
};
const { locale, t } = useTranslation();
const nazioni_options = GetNazioni();
const comuni_options = getComuniNames();
z.config(z.locales[locale]());
const form = useZodForm(Schema, {
defaultValues: defaultValues,
});
const DatePickerLocale = locale === "it" ? it : enUS;
const { mutate } = api.servizio.postAcquistoData.useMutation({
onMutate: () => {
toast.loading("Invio dati in corso", {
id: "salvataggio",
});
},
onSuccess: async (data) => {
toast.success("Servizio impostato con successo", {
id: "salvataggio",
});
if (isAdmin) {
if (data) {
await router.push(`/area-riservata/admin/user-view/ordini/${userId}`);
} else {
await router.push(
`/area-riservata/admin/user-view/ricerca/${userId}`,
);
}
} else {
await router.push(`/servizio/pagamento/${data}`);
}
},
onError: (error) => {
toast.error("Errore invio dati: " + error.message, {
id: "salvataggio",
});
},
});
function onSubmit(fields: FormValues) {
mutate({
servizioId: initialData.servizio.servizio_id,
userId,
user: {
username: `${fields.nome.trim()} ${fields.cognome.trim()}`,
nome: fields.nome,
cognome: fields.cognome,
email: fields.email,
telefono: fields.telefono.replace(/\s/g, ""),
},
anagrafica: {
idanagrafica: initialData.anagrafica?.idanagrafica,
azienda: fields.azienda,
ragione_sociale: fields.ragione_sociale,
sede_legale: fields.sede_legale,
legale_rappresentante: fields.legale_rappresentante,
p_iva: fields.p_iva,
sesso: fields.sesso,
data_nascita: fields.data_nascita,
luogo_nascita: fields.luogo_nascita,
nazione_nascita: fields.nazione_nascita,
codice_fiscale: fields.codice_fiscale,
nazione_residenza: fields.nazione_recapiti,
provincia_residenza: fields.provincia_recapiti,
comune_residenza: fields.citta_recapiti,
via_residenza: fields.indirizzo_recapiti,
civico_residenza: fields.civico_recapiti,
cap_residenza: fields.cap_recapiti,
userid: userId,
fatturazione_aziendale: fields.fatturazione_aziendale,
codice_destinatario: fields.codice_destinatario,
},
servizio: {
tipologia: fields.tipologia,
budget: fields.budget,
entromese: fields.entromese,
n_adulti: fields.n_adulti,
n_minori: fields.n_minori,
permanenza: fields.permanenza,
motivazione_transitorio: fields.motivazione_transitorio,
arredato: fields.arredato,
animali: fields.animali,
fumatori: fields.fumatori,
giardino: fields.giardino,
parcheggio: fields.parcheggio,
terrazzo: fields.terrazzo,
ascensore: fields.ascensore,
pianoterra: fields.pianoterra,
reddito: fields.reddito,
},
skipOrdine: fields.skipOrdine,
});
}
type altrePrefMappingType = [
["animali", string],
["fumatori", string],
["giardino", string],
["parcheggio", string],
["terrazzo", string],
["ascensore", string],
["pianoterra", string],
];
const altrePrefMapping = t.altrePrefMapping as altrePrefMappingType;
const [
tipologia,
azienda,
fatturazione_aziendale,
nazione_nascita,
nazione_recapiti,
budget,
] = form.watch([
"tipologia",
"azienda",
"fatturazione_aziendale",
"nazione_nascita",
"nazione_recapiti",
"budget",
]);
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8 px-0.5">
<Card>
<CardHeader>
<CardTitle>Dettagli del servizio</CardTitle>
<CardDescription>
Questi dati rappresentano la tua ricerca
</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<FormField
control={form.control}
name="tipologia"
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="select-tipologia">Tipologia</FormLabel>
<FormMessage />
</div>
<MultiSelect
elementId="select-tipologia"
elementName="tipologia"
isMulti={false}
placeholder={t.seleziona_placeholder}
defaultValue={{
value: TipologiaPosizioneEnum.Transitorio,
label: "Transitorio",
}}
options={[
{
value: TipologiaPosizioneEnum.Transitorio,
label: "Transitorio",
},
{
value: TipologiaPosizioneEnum.Stabile,
label: "Stabile",
},
]}
onValueChange={(value) => {
field.onChange(value.value);
form.setValue("motivazione_transitorio", null);
form.setValue("reddito", null);
}}
/>
</FormItem>
)}
/>
<FormField
control={form.control}
name="budget"
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2 pb-1">
<FormLabel htmlFor="budgetslider">
{`${t.preferenze.budget_label1} - ${field.value},00 ${
t.preferenze.budget_label2
}`}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<Slider
min={0}
max={2000}
step={50}
defaultValue={[field.value]}
onValueChange={(vals) => {
field.onChange(Number(vals[0]));
}}
rangeClassName="bg-neutral-700"
thumbClassName="border-neutral-700"
value={[budget]}
id="budgetslider"
/>
</FormControl>
<FormDescription>{t.preferenze.budget_desc}</FormDescription>
</FormItem>
)}
/>
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
<FormField
control={form.control}
name="entromese"
render={({ field }) => (
<FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="select-mesi">
{t.preferenze.dalmese_label}...
</FormLabel>
<FormMessage />
</div>
<FormControl>
<MultiSelect
elementId="select-mesi"
elementName="entro_mese"
options={UnpackOptions({
options: t.preferenze.mesi,
})}
defaultValue={
field.value !== null
? {
value: String(field.value),
label: t.preferenze.mesi[field.value]!,
}
: undefined
}
onValueChange={(value) => {
field.onChange(
value.value !== "" ? parseInt(value.value) : null,
);
}}
placeholder="Seleziona..."
isMulti={false}
/>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="permanenza"
disabled={tipologia !== TipologiaPosizioneEnum.Transitorio}
render={({ field }) => (
<FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="permanenza">
{t.preferenze.permanenza_label}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<MultiSelect
elementId="permanenza"
elementName="permanenza"
options={UnpackOptions({
options: t.preferenze.permanenza,
})}
defaultValue={
field.value
? {
value: field.value.toString(),
label:
t.preferenze.permanenza[field.value] || "",
}
: undefined
}
onValueChange={(value) => {
field.onChange(
value.value !== "" ? parseInt(value.value) : null,
);
}}
placeholder="Seleziona..."
isMulti={false}
disabled={
tipologia !== TipologiaPosizioneEnum.Transitorio
}
/>
</FormControl>
<FormDescription>
{t.preferenze.permanenza_desc}
</FormDescription>
</FormItem>
)}
/>
</div>
<div className="flex w-full flex-col items-center justify-between gap-4 sm:flex-row">
<div className="flex w-full items-center justify-between gap-4">
<FormField
control={form.control}
name="n_adulti"
render={({ field }) => (
<FormItem className={cn("w-full")}>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel className={cn("")} htmlFor="n_adulti">
{t.preferenze.nadulti_label}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<Counter
value={field.value}
setValue={(v) => field.onChange(Number(v))}
name="n_adulti"
onlyPositive
/>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="n_minori"
render={({ field }) => (
<FormItem className={cn("w-full")}>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel className={cn("")} htmlFor="n_minori">
{t.preferenze.nminori_label}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<Counter
value={field.value}
setValue={(v) => field.onChange(Number(v))}
name="n_minori"
onlyPositive
/>
</FormControl>
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name="arredato"
render={({ field }) => (
<FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="arredato">
{t.preferenze.arredato_label}
</FormLabel>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={field.onChange}
id="arredato"
className="data-[state=checked]:bg-neutral-700"
/>
</FormControl>
<FormMessage />
</div>
<FormDescription>
{t.preferenze.arredato_desc}
</FormDescription>
</FormItem>
)}
/>
</div>
{tipologia === TipologiaPosizioneEnum.Transitorio ? (
<FormField
key={tipologia}
control={form.control}
name="motivazione_transitorio"
render={({ field }) => {
const existingValue = t.preferenze.motivazioni_mappings.find(
(m) => m.id == field.value,
);
return (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="motivazione_transitorio">
{t.preferenze.motivazione_label}
</FormLabel>
<FormMessage />
</div>
<MultiSelect
elementId="select-motivazione_transitorio"
elementName="motivazione_transitorio"
isMulti={false}
placeholder={t.seleziona_placeholder}
defaultValue={
existingValue
? {
value: existingValue.id,
label: existingValue.title,
}
: undefined
}
options={t.preferenze.motivazioni_mappings.map(
(option) => ({
value: option.id,
label: option.title,
}),
)}
onValueChange={(value) => {
field.onChange(value.value);
}}
/>
<FormDescription>
{t.preferenze.motivazione_desc}
</FormDescription>
</FormItem>
);
}}
/>
) : (
<FormField
key={tipologia}
control={form.control}
name="reddito"
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="select-reddito">
{t.preferenze.reddito_label}
</FormLabel>
<FormMessage />
</div>
<MultiSelect
elementId="select-reddito"
elementName="reddito"
isMulti={false}
placeholder={t.seleziona_placeholder}
defaultValue={undefined}
options={UnpackOptions({
options: t.preferenze.reddito_options,
})}
onValueChange={(value) => {
field.onChange(value.value);
}}
/>
</FormItem>
)}
/>
)}
<div className="flex flex-col space-y-2">
<Label htmlFor="altrePrefDialogButton">
{t.preferenze.altrepref_label}
</Label>
<FormDescription>{t.preferenze.altrepref_desc}</FormDescription>
<div className="mt-2 flex flex-wrap gap-2">
{altrePrefMapping.map((pair, index) => {
if (pair) {
return (
<FormField
control={form.control}
key={index}
name={pair[0]}
render={({ field }) => (
<FormItem>
<FormControl>
<Badge
onClick={() => {
field.onChange(!field.value);
}}
className={cn(
"cursor-pointer text-sm",
field.value
? "bg-neutral-800 hover:bg-neutral-800 sm:hover:bg-neutral-900/80"
: "bg-neutral-200 text-neutral-700 hover:bg-neutral-200 sm:hover:bg-neutral-900/80 sm:hover:text-neutral-50",
)}
>
{pair[1]}
</Badge>
</FormControl>
</FormItem>
)}
/>
);
}
})}
</div>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Dati personali</CardTitle>
<CardDescription>
Questi dati sono necessari per la fatturazione
</CardDescription>
</CardHeader>
<CardContent className="space-y-6">
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
<FormField
control={form.control}
name="nome"
render={({ field }) => (
<FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="nome">{t.account.nome}</FormLabel>
<FormMessage />
</div>
<FormControl>
<Input {...field} type="text" id="nome" />
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="cognome"
render={({ field }) => (
<FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="cognome">
{t.account.cognome}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<Input {...field} type="text" id="cognome" />
</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">
{t.account.azienda_o_pf_disclamer}
</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="data_nascita"
render={({ field }) => (
<FormItem className="flex w-full flex-col">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="dataNascita">
{t.anagrafica.dataNascita}
</FormLabel>
<FormMessage />
</div>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={"outline"}
id="dataNascita"
className={cn(
"h-[42px] w-full pl-3 text-left font-medium",
!field.value && "text-muted-foreground",
`text-primary dark:bg-primary mt-2 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="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-nascita">
{t.anagrafica.luogoNascita}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<MultiSelect
elementId="select-comune-nascita"
elementName="luogoNascita"
options={UnpackOptions({ options: comuni_options })}
defaultValue={getComuneFieldValue(
field.value,
comuni_options,
)}
onValueChange={async (value) => {
field.onChange(value.value);
await form.trigger("luogo_nascita");
}}
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");
}}
/>
</FormControl>
</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-nascita">
{t.anagrafica.nazioneNascita}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<MultiSelect
elementId="select-naz-nascita"
elementName="nazioneNascita"
options={UnpackOptions({ options: nazioni_options })}
defaultValue={RepackValues({
options: nazioni_options,
values: field.value,
})}
onValueChange={async (value) => {
field.onChange(value.value);
await form.trigger("luogo_nascita");
}}
placeholder="Seleziona..."
isMulti={false}
/>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="sesso"
render={({ field }) => (
<FormItem className="w-full">
<div className="flex items-center gap-x-2">
<FormLabel htmlFor="select-sesso">
<TooltipProvider>
<Tooltip delayDuration={0}>
<TooltipTrigger className="flex items-center gap-x-2">
{t.anagrafica.sesso}{" "}
<HelpCircleIcon className="size-5" />
</TooltipTrigger>
<TooltipContent>
{t.anagrafica.sesso_disclamer}
</TooltipContent>
</Tooltip>
</TooltipProvider>
</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>
)}
/>
</div>
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
<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="email"
render={({ field }) => (
<FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="email">{t.account.email}</FormLabel>
<FormMessage />
</div>
<FormControl>
<InputWIcon
{...field}
id="email"
type="email"
iconPosition="start"
>
<Mail size={16} strokeWidth={2} aria-hidden="true" />
</InputWIcon>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="telefono"
render={({ field }) => (
<FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="numero">
{t.account.telefono}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<PhoneInput {...field} id="telefono" />
</FormControl>
</FormItem>
)}
/>
</div>
<Separator />
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
<FormField
control={form.control}
name="nazione_recapiti"
render={({ field }) => (
<FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="select-naz">
{t.recapiti.nazione}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<MultiSelect
elementId="select-naz"
elementName="nazioneRecapiti"
options={UnpackOptions({ options: nazioni_options })}
defaultValue={RepackValues({
options: nazioni_options,
values: field.value,
})}
onValueChange={async (value) => {
field.onChange(value.value);
form.setValue("provincia_recapiti", "");
await form.trigger("citta_recapiti");
}}
placeholder="Seleziona..."
isMulti={false}
/>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="provincia_recapiti"
render={({ field }) => (
<FormItem className="w-full">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="provinciaRecapiti">
{t.recapiti.provincia}
</FormLabel>
<FormMessage />
</div>
{nazione_recapiti === "0" ? (
<MultiSelect
elementId="provinciaRecapiti"
options={UnpackOptions({ options: provincie })}
onValueChange={(value) => {
field.onChange(value.value);
}}
defaultValue={RepackValues({
options: provincie,
values: field.value,
})}
elementName="provincia"
isMulti={false}
placeholder="Seleziona"
/>
) : (
<FormControl>
<Input {...field} type="text" id="provinciaRecapiti" />
</FormControl>
)}
</FormItem>
)}
/>
</div>
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
<FormField
control={form.control}
name="citta_recapiti"
render={({ field }) => {
if (nazione_recapiti === "0") {
return (
<FormItem className="w-full sm:w-4/6">
<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="citta_recapiti"
options={UnpackOptions({ options: comuni_options })}
defaultValue={getComuneFieldValue(
field.value,
comuni_options,
)}
onValueChange={async (value) => {
field.onChange(value.value);
await form.trigger("citta_recapiti");
}}
placeholder="Seleziona..."
isMulti={false}
/>
</FormControl>
</FormItem>
);
}
return (
<FormItem className="w-full sm:w-4/6">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="citta_recapiti">
{t.recapiti.comune}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<Input
{...field}
type="text"
id="citta_recapiti"
onChange={async (v) => {
field.onChange(v.target.value);
await form.trigger("citta_recapiti");
}}
/>
</FormControl>
</FormItem>
);
}}
/>
<FormField
control={form.control}
name="cap_recapiti"
render={({ field }) => (
<FormItem className="w-full sm:w-2/6">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="cap">{t.recapiti.cap}</FormLabel>
<FormMessage />
</div>
<FormControl>
<Input
{...field}
type="text"
id="cap"
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="indirizzo_recapiti"
render={({ field }) => (
<FormItem className="w-full sm:w-4/6">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="indirizzo">
{t.recapiti.indirizzo}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<Input
{...field}
type="text"
id="indirizzo"
placeholder="Via Roma"
/>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="civico_recapiti"
render={({ field }) => (
<FormItem className="w-full sm:w-2/6">
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="civico">
{t.recapiti.civico}
</FormLabel>
<FormMessage />
</div>
<FormControl>
<Input
{...field}
type="text"
id="civico"
placeholder="50"
/>
</FormControl>
</FormItem>
)}
/>
</div>
</CardContent>
</Card>
<div className="flex w-full items-center justify-center gap-2 pb-8 sm:justify-end">
<FormField
control={form.control}
name="skipOrdine"
render={({ field }) => (
<FormItem className="py-2">
<div className="flex items-center justify-start gap-x-4">
<FormLabel htmlFor="skipOrdine">
Vuoi saltare la creazione dell&apos;ordine e impostare il
servizio come attivo?
</FormLabel>
<FormControl>
<Switch
checked={field.value}
onCheckedChange={(v) => {
field.onChange(v);
}}
id="skipOrdine"
className="data-[state=checked]:bg-neutral-700"
/>
</FormControl>
<FormMessage />
</div>
</FormItem>
)}
/>
<Button type="submit" className="w-full sm:w-auto">
Salva e Procedi
</Button>
</div>
</form>
</Form>
);
};