"use client"; import { format } from "date-fns"; import { enUS, it } from "date-fns/locale"; import { CalendarIcon, HelpCircleIcon, Mail } from "lucide-react"; import { useRouter } from "next/router"; import { type Control, useWatch } from "react-hook-form"; import toast from "react-hot-toast"; import { z } from "zod/v4"; import { Counter } from "~/components/counter"; import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "~/components/custom_ui/form"; import Input from "~/components/custom_ui/input"; import InputWIcon from "~/components/custom_ui/input-icon"; import { MultiSelect, RepackValues, UnpackOptions, } from "~/components/custom_ui/multiselect"; import { PhoneInput } from "~/components/phone-input"; import { Badge } from "~/components/ui/badge"; import { Button } from "~/components/ui/button"; import { Calendar } from "~/components/ui/calendar"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "~/components/ui/card"; import { Label } from "~/components/ui/label"; import { Popover, PopoverContent, PopoverTrigger, } from "~/components/ui/popover"; import { Separator } from "~/components/ui/separator"; import { Slider } from "~/components/ui/slider"; import { Switch } from "~/components/ui/switch"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "~/components/ui/tooltip"; import { getComuni } from "~/i18n/comuni"; import { GetNazioni } from "~/i18n/nazioni"; import { getProvinciaFromSigla, provincieWithSigla } from "~/i18n/provincie"; import { checkFiscalCodeValidity, getComuneFieldValue } from "~/lib/form_utils"; import { cn } from "~/lib/utils"; import { useZodForm } from "~/lib/zodForm"; import { useTranslation } from "~/providers/I18nProvider"; import type { Servizio } from "~/schemas/public/Servizio"; import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum"; import type { Users, UsersId } from "~/schemas/public/Users"; import type { UsersAnagrafica } from "~/schemas/public/UsersAnagrafica"; import { api } from "~/utils/api"; type InitialData = { servizio: Servizio; userData: Pick; anagrafica: UsersAnagrafica | undefined; }; const FormNewServizioSchema = z.object({ animali: z.boolean(), arredato: z.boolean(), ascensore: z.boolean(), azienda: z.boolean(), budget: z.number().positive(), cap_recapiti: z.string().length(5), citta_recapiti: z.string().nonempty("Inserisci una città"), civico_recapiti: z.string().nonempty("Inserisci un civico"), codice_destinatario: z.string().nullable(), codice_fiscale: z.string(), cognome: z.string().nonempty("Inserisci un cognome valido"), data_nascita: z.date(), email: z.email(), entromese: z.number().nullable(), fatturazione_aziendale: z.boolean(), fumatori: z.boolean(), giardino: z.boolean(), indirizzo_recapiti: z.string().nonempty("Inserisci un indirizzo"), legale_rappresentante: z.string().nullable(), luogo_nascita: z.string(), motivazione_transitorio: z.string().nullable(), n_adulti: z.number().min(1), n_minori: z.number(), nazione_nascita: z.string(), nazione_recapiti: z .string() .refine((v) => v !== "", { params: { type: "nazione" } }), nome: z.string().nonempty("Inserisci un nome valido"), p_iva: z.string().nullable(), parcheggio: z.boolean(), permanenza: z.number().nullable(), pianoterra: z.boolean(), provincia_recapiti: z .string() .refine((v) => v !== "", { params: { type: "provincia" } }), ragione_sociale: z.string().nullable(), reddito: z.string().nullable(), sede_legale: z.string().nullable(), sesso: z.string(), skipOrdine: z.boolean(), telefono: z.string(), terrazzo: z.boolean(), tipologia: z.custom(), }); type FormNewServizioValues = z.infer; export const FormNewServizioAcquisto = ({ initialData, userId, isAdmin = false, }: { initialData: InitialData; userId: UsersId; isAdmin?: boolean; }) => { const router = useRouter(); const schema = FormNewServizioSchema.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", input: "", message: "Inserisci il mese di inizio", path: ["entromese"], }); } if (azienda) { if (!ragione_sociale || ragione_sociale.length < 1) { refinementContext.issues.push({ code: "custom", input: "", message: "Inserisci la ragione sociale", path: ["ragione_sociale"], }); } if (!sede_legale || sede_legale.length < 1) { refinementContext.issues.push({ code: "custom", input: "", message: "Inserisci la sede legale", path: ["sede_legale"], }); } if (!p_iva || p_iva.length < 1) { refinementContext.issues.push({ code: "custom", input: "", message: "Inserisci la partita iva", path: ["p_iva"], }); } if (!legale_rappresentante || legale_rappresentante.length < 1) { refinementContext.issues.push({ code: "custom", input: "", message: "Inserisci il legale rappresentante", path: ["legale_rappresentante"], }); } } if (fatturazione_aziendale) { if (!codice_destinatario || codice_destinatario.length !== 7) { refinementContext.issues.push({ code: "custom", input: "", message: "Inserisci un codice destinatario valido", path: ["codice_destinatario"], }); } } if (!telefono || telefono.length < 10) { refinementContext.issues.push({ code: "custom", input: "", message: "Il numero di telefono deve essere lungo almeno 10 caratteri", }); } checkFiscalCodeValidity({ codiceFiscale: codice_fiscale, cognome, dataNascita: data_nascita, luogoNascita: luogo_nascita, nazioneNascita: nazione_nascita, nome, path: "codice_fiscale", refinementContext, sesso, }); if (n_adulti <= 0) { refinementContext.issues.push({ code: "custom", input: "", message: "Inserisci il numero di persone", path: ["n_adulti"], }); } if ( permanenza === null && tipologia === TipologiaPosizioneEnum.Transitorio ) { refinementContext.issues.push({ code: "custom", input: "", message: "Inserisci permanenza", path: ["permanenza"], }); } if (tipologia === TipologiaPosizioneEnum.Transitorio) { if ( motivazione_transitorio === "" || motivazione_transitorio === null ) { refinementContext.issues.push({ code: "custom", input: "", message: "Inserisci la motivazione", path: ["motivazione_transitorio"], }); } } else { if (reddito === "" || reddito === null) { refinementContext.issues.push({ code: "custom", input: "", message: "Inserisci il reddito", path: ["reddito"], }); } } }, ); // This can come from your database or API. const defaultValues: FormNewServizioValues = { ...initialData.userData, azienda: initialData.anagrafica?.azienda || false, cap_recapiti: initialData.anagrafica?.cap_residenza || "", citta_recapiti: initialData.anagrafica?.comune_residenza || "", civico_recapiti: initialData.anagrafica?.civico_residenza || "", codice_destinatario: initialData.anagrafica?.codice_destinatario || "", codice_fiscale: initialData.anagrafica?.codice_fiscale || "", data_nascita: initialData.anagrafica?.data_nascita ? new Date(initialData.anagrafica.data_nascita) : new Date(), fatturazione_aziendale: initialData.anagrafica?.fatturazione_aziendale || false, indirizzo_recapiti: initialData.anagrafica?.via_residenza || "", legale_rappresentante: initialData.anagrafica?.legale_rappresentante || "", luogo_nascita: initialData.anagrafica?.luogo_nascita || "", nazione_nascita: initialData.anagrafica?.nazione_nascita || "", nazione_recapiti: initialData.anagrafica?.nazione_residenza || "", p_iva: initialData.anagrafica?.p_iva || "", provincia_recapiti: initialData.anagrafica?.provincia_residenza || "", ragione_sociale: initialData.anagrafica?.ragione_sociale || "", sede_legale: initialData.anagrafica?.sede_legale || "", sesso: initialData.anagrafica?.sesso || "M", ...initialData.servizio, skipOrdine: false, }; const { locale, t } = useTranslation(); const nazioni_options = GetNazioni(); const comuni_options = getComuni(); z.config(z.locales[locale]()); const form = useZodForm(schema, { defaultValues: defaultValues, }); const DatePickerLocale = locale === "it" ? it : enUS; const { mutate } = api.servizio.postAcquistoData.useMutation({ onError: (error) => { toast.error(`Errore invio dati: ${error.message}`, { id: "salvataggio", }); }, 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}`); } }, }); function onSubmit(fields: FormNewServizioValues) { mutate({ anagrafica: { azienda: fields.azienda, cap_residenza: fields.cap_recapiti, civico_residenza: fields.civico_recapiti, codice_destinatario: fields.codice_destinatario, codice_fiscale: fields.codice_fiscale, comune_residenza: fields.citta_recapiti, data_nascita: fields.data_nascita, fatturazione_aziendale: fields.fatturazione_aziendale, idanagrafica: initialData.anagrafica?.idanagrafica, legale_rappresentante: fields.legale_rappresentante, luogo_nascita: fields.luogo_nascita, nazione_nascita: fields.nazione_nascita, nazione_residenza: fields.nazione_recapiti, p_iva: fields.p_iva, provincia_residenza: fields.provincia_recapiti, ragione_sociale: fields.ragione_sociale, sede_legale: fields.sede_legale, sesso: fields.sesso, userid: userId, via_residenza: fields.indirizzo_recapiti, }, servizio: { animali: fields.animali, arredato: fields.arredato, ascensore: fields.ascensore, budget: fields.budget, entromese: fields.entromese, fumatori: fields.fumatori, giardino: fields.giardino, motivazione_transitorio: fields.motivazione_transitorio, n_adulti: fields.n_adulti, n_minori: fields.n_minori, parcheggio: fields.parcheggio, permanenza: fields.permanenza, pianoterra: fields.pianoterra, reddito: fields.reddito, terrazzo: fields.terrazzo, tipologia: fields.tipologia, }, servizioId: initialData.servizio.servizio_id, skipOrdine: isAdmin ? fields.skipOrdine : false, user: { cognome: fields.cognome, email: fields.email, nome: fields.nome, telefono: fields.telefono.replace(/\s/g, ""), username: `${fields.nome.trim()} ${fields.cognome.trim()}`, }, userId, }); } type altrePrefMappingType = [ ["animali", string], ["fumatori", string], ["giardino", string], ["parcheggio", string], ["terrazzo", string], ["ascensore", string], ["pianoterra", string], ]; const altrePrefMapping = t.altrePrefMapping as altrePrefMappingType; const [tipologia, nazione_nascita, nazione_recapiti, budget] = form.watch([ "tipologia", "nazione_nascita", "nazione_recapiti", "budget", ]); const texts = locale === "it" ? { dettagli: "Dettagli del servizio", dettagli_desc: "Questi dati rappresentano la tua ricerca", fattura: "Vuoi che la fatturazione sia intestata alla tua azienda?", personali: "Dati personali", personali_desc: "Inserisci i tuoi dati personali", salva: "Salva e procedi al pagamento", sdi: "Codice destinatario SDI", } : { dettagli: "Service Details", dettagli_desc: "These data represent your search", fattura: "Do you want the invoice to be issued to your company?", personali: "Personal Data", personali_desc: "Enter your personal data", salva: "Save and proceed to payment", sdi: "SDI Recipient Code", }; return (
{texts.dettagli} {texts.dettagli_desc} (
{t.preferenze.tipologia}
{ field.onChange(value.value); form.setValue("motivazione_transitorio", null); form.setValue("reddito", null); }} options={[ { label: "Transitorio", value: TipologiaPosizioneEnum.Transitorio, }, { label: "Stabile", value: TipologiaPosizioneEnum.Stabile, }, ]} placeholder={t.seleziona_placeholder} />
)} /> (
{`${t.preferenze.budget_label1} - ${field.value},00 ${ t.preferenze.budget_label2 }`}
{ field.onChange(Number(vals[0])); }} rangeClassName="bg-neutral-700" step={50} thumbClassName="border-neutral-700" value={[budget]} /> {t.preferenze.budget_desc}
)} />
(
{t.preferenze.dalmese_label}...
label: t.preferenze.mesi[field.value]!, value: String(field.value), } : undefined } elementId="select-mesi" elementName="entro_mese" isMulti={false} onValueChange={(value) => { field.onChange( value.value !== "" ? parseInt(value.value) : null, ); }} options={UnpackOptions({ options: t.preferenze.mesi, })} placeholder="Seleziona..." />
)} /> (
{t.preferenze.permanenza_label}
{ field.onChange( value.value !== "" ? parseInt(value.value) : null, ); }} options={UnpackOptions({ options: t.preferenze.permanenza, })} placeholder="Seleziona..." /> {t.preferenze.permanenza_desc}
)} />
(
{t.preferenze.nadulti_label}
field.onChange(Number(v))} value={field.value} />
)} /> (
{t.preferenze.nminori_label}
field.onChange(Number(v))} value={field.value} />
)} />
(
{t.preferenze.arredato_label}
{t.preferenze.arredato_desc}
)} />
{tipologia === TipologiaPosizioneEnum.Transitorio ? ( { const existingValue = t.preferenze.motivazioni_mappings.find( (m) => m.id === field.value, ); return (
{t.preferenze.motivazione_label}
{ field.onChange(value.value); }} options={t.preferenze.motivazioni_mappings.map( (option) => ({ label: option.title, value: option.id, }), )} placeholder={t.seleziona_placeholder} /> {t.preferenze.motivazione_desc}
); }} /> ) : ( (
{t.preferenze.reddito_label}
{ field.onChange(value.value); }} options={UnpackOptions({ options: t.preferenze.reddito_options, })} placeholder={t.seleziona_placeholder} />
)} /> )}
{t.preferenze.altrepref_desc}
{altrePrefMapping.map((pair) => { if (pair) { return ( ( { field.onChange(!field.value); }} > {pair[1]} )} /> ); } })}
{texts.personali} {texts.personali_desc}
(
{t.account.nome}
)} /> (
{t.account.cognome}
)} /> (
{t.account.azienda_o_pf_disclamer} { field.onChange(v); if (!v) { form.setValue("ragione_sociale", null); form.setValue("sede_legale", null); form.setValue("p_iva", null); } }} />
)} />
(
{t.anagrafica.dataNascita}
date > new Date() || date < new Date("1900-01-01") } endMonth={new Date()} locale={DatePickerLocale} mode="single" onSelect={field.onChange} selected={field.value} />
)} /> (
{t.anagrafica.nazioneNascita}
{ field.onChange(value.value); await form.trigger("luogo_nascita"); if (value.value !== "0") { form.setValue("luogo_nascita", ""); } }} options={UnpackOptions({ options: nazioni_options })} placeholder="Seleziona..." />
)} /> { if (nazione_nascita === "0") { const options = comuni_options.map((c) => c.nome); return (
{t.anagrafica.luogoNascita}
{ field.onChange(value.value); await form.trigger("luogo_nascita"); }} options={UnpackOptions({ options })} placeholder="Seleziona..." />
); } return (
{t.anagrafica.luogoNascita}
{ field.onChange(v.target.value); await form.trigger("luogo_nascita"); }} type="text" />
); }} /> (
{t.anagrafica.sesso}{" "} {t.anagrafica.sesso_disclamer}
v.value === field.value, )} elementId="select-sesso" elementName="sesso" isMulti={false} onValueChange={(value) => { field.onChange(value.value); }} options={t.anagrafica.sesso_options} placeholder="" />
)} />
(
{t.anagrafica.codiceFiscale}
{ field.onChange(v.target.value.toUpperCase()); await form.trigger("codice_fiscale"); }} type="text" />
)} /> (
{t.account.email}
)} /> (
{t.account.telefono}
)} />
(
{t.recapiti.nazione}
{ field.onChange(value.value); form.setValue("provincia_recapiti", ""); if (value.value !== "0") { form.setValue("citta_recapiti", ""); } }} options={UnpackOptions({ options: nazioni_options })} placeholder="Seleziona..." />
)} /> { const provinciaName = field.value && getProvinciaFromSigla(field.value); return (
{t.recapiti.provincia}
{nazione_recapiti === "0" ? ( { field.onChange(value.value); }} options={provincieWithSigla.map((prov) => ({ label: prov.nome, value: prov.sigla, }))} placeholder="Seleziona" /> ) : ( )}
); }} />
{ if (nazione_recapiti === "0") { const provincia = form.watch("provincia_recapiti"); const options = comuni_options .filter((comune) => provincia ? comune.provincia === provincia : true, ) .map((comune) => comune.nome); return (
{t.recapiti.comune}
{ field.onChange(value.value); await form.trigger("citta_recapiti"); }} options={UnpackOptions({ options })} placeholder="Seleziona..." />
); } return (
{t.recapiti.comune}
{ field.onChange(v.target.value); await form.trigger("citta_recapiti"); }} type="text" />
); }} /> (
{t.recapiti.cap}
)} />
(
{t.recapiti.indirizzo}
)} /> (
{t.recapiti.civico}
)} />
{isAdmin && ( (
Vuoi saltare la creazione dell'ordine e impostare il servizio come attivo? { field.onChange(v); }} />
)} /> )}
); }; const AziendaSection = ({ control, setValue, }: { control: Control; setValue: ( name: keyof FormNewServizioValues, // biome-ignore lint/suspicious/noExplicitAny: value: any, ) => void; }) => { const { t, locale } = useTranslation(); const azienda = useWatch({ control, name: "azienda", }); return ( <>
(
{t.anagrafica.ragioneSociale}
)} /> (
{t.anagrafica.sedeLegale}
)} />
(
{t.anagrafica.p_iva}
)} /> (
{t.anagrafica.legale_rappresentante}
)} />
(
{locale === "it" ? "Vuoi che la fatturazione sia intestata alla tua azienda?" : "Do you want the invoice to be issued to your company?"} { field.onChange(v); if (!v) { setValue("codice_destinatario", null); } }} />
)} /> ); }; const FatturazioneSection = ({ control, }: { control: Control; }) => { const { locale } = useTranslation(); const fatturazione_aziendale = useWatch({ control, name: "fatturazione_aziendale", }); return ( (
{locale === "it" ? "Codice destinatario SDI" : "SDI Recipient Code"}
)} /> ); };