From 967935f0a83ac4e661f0c4c7109a5811ce705e47 Mon Sep 17 00:00:00 2001 From: Marco Pedone Date: Thu, 30 Oct 2025 18:13:50 +0100 Subject: [PATCH] Refactor comuni and provincie data structures; add dynamic FormDebug component - Updated `initializeComuniNames` to accept an optional `provincia` parameter for filtering comuni by province. - Renamed `getComuniNames` to `getComuni` and modified it to return an array of objects containing both comune names and their respective province siglas. - Introduced `provincieWithSigla` array to map province names to their siglas, along with a new function `getProvinciaFromSigla` for retrieving province names based on sigla. - Added a dynamic import for the `FormDebug` component to facilitate debugging in development mode while preventing it from rendering in production. - Commented out console logs in `checkFiscalCodeValidity` for cleaner production output. --- .../src/components/custom_ui/form.tsx | 19 - .../src/components/custom_ui/formDevTool.tsx | 7 - .../src/forms/FormNewServizioAcquisto.tsx | 817 +++++++------ .../src/forms/FormProfilo_Anagrafica.tsx | 1075 +++++++++-------- apps/infoalloggi/src/i18n/comuni.ts | 10 +- apps/infoalloggi/src/i18n/provincie.ts | 230 ++-- apps/infoalloggi/src/lib/form_utils.ts | 13 +- 7 files changed, 1159 insertions(+), 1012 deletions(-) delete mode 100644 apps/infoalloggi/src/components/custom_ui/formDevTool.tsx diff --git a/apps/infoalloggi/src/components/custom_ui/form.tsx b/apps/infoalloggi/src/components/custom_ui/form.tsx index 3a474fa..ce574c8 100644 --- a/apps/infoalloggi/src/components/custom_ui/form.tsx +++ b/apps/infoalloggi/src/components/custom_ui/form.tsx @@ -11,7 +11,6 @@ import { } from "react-hook-form"; import { Label } from "src/components/ui/label"; import { cn } from "src/lib/utils"; -import { env } from "~/env"; const Form = FormProvider; @@ -171,23 +170,6 @@ const FormMessage = React.forwardRef< }); FormMessage.displayName = "FormMessage"; -const FormDebug = React.forwardRef< - React.ElementType, - React.HTMLAttributes ->(async () => { - if (env.NODE_ENV !== "development") { - return null; - } - const { control, formState } = useFormContext(); - const devtools = await import(/* webpackIgnore: true */ "@hookform/devtools"); - - if (Object.keys(formState.errors).length > 0) { - console.error("errors", formState.errors); - } - return ; -}); -FormDebug.displayName = "FormDebug"; - export { useFormField, Form, @@ -197,5 +179,4 @@ export { FormDescription, FormMessage, FormField, - FormDebug, }; diff --git a/apps/infoalloggi/src/components/custom_ui/formDevTool.tsx b/apps/infoalloggi/src/components/custom_ui/formDevTool.tsx deleted file mode 100644 index a45da28..0000000 --- a/apps/infoalloggi/src/components/custom_ui/formDevTool.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import dynamic from "next/dynamic"; -import type React from "react"; - -export const DevT: React.ElementType = dynamic( - () => import("@hookform/devtools").then((mod) => mod.DevTool), - { ssr: false }, -); diff --git a/apps/infoalloggi/src/forms/FormNewServizioAcquisto.tsx b/apps/infoalloggi/src/forms/FormNewServizioAcquisto.tsx index e08011d..d63345d 100644 --- a/apps/infoalloggi/src/forms/FormNewServizioAcquisto.tsx +++ b/apps/infoalloggi/src/forms/FormNewServizioAcquisto.tsx @@ -3,6 +3,7 @@ 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"; @@ -48,9 +49,9 @@ import { TooltipProvider, TooltipTrigger, } from "~/components/ui/tooltip"; -import { getComuniNames } from "~/i18n/comuni"; +import { getComuni } from "~/i18n/comuni"; import { GetNazioni } from "~/i18n/nazioni"; -import { provincie } from "~/i18n/provincie"; +import { getProvinciaFromSigla, provincieWithSigla } from "~/i18n/provincie"; import { checkFiscalCodeValidity, getComuneFieldValue } from "~/lib/form_utils"; import { cn } from "~/lib/utils"; import { useZodForm } from "~/lib/zodForm"; @@ -67,6 +68,53 @@ type InitialData = { 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, @@ -77,198 +125,150 @@ export const FormNewServizioAcquisto = ({ isAdmin?: boolean; }) => { const router = useRouter(); - const Schema = 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(), - }) - .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, + 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 (n_adulti <= 0) { + } + if (azienda) { + if (!ragione_sociale || ragione_sociale.length < 1) { refinementContext.issues.push({ code: "custom", input: "", - message: "Inserisci il numero di persone", - path: ["n_adulti"], + 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 ( - permanenza === null && - tipologia === TipologiaPosizioneEnum.Transitorio + motivazione_transitorio === "" || + motivazione_transitorio === null ) { refinementContext.issues.push({ code: "custom", input: "", - message: "Inserisci permanenza", - path: ["permanenza"], + message: "Inserisci la motivazione", + path: ["motivazione_transitorio"], }); } - 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"], - }); - } + } else { + if (reddito === "" || reddito === null) { + refinementContext.issues.push({ + code: "custom", + input: "", + message: "Inserisci il reddito", + path: ["reddito"], + }); } - }, - ); - - type FormValues = z.infer; + } + }, + ); // This can come from your database or API. - const defaultValues: FormValues = { + const defaultValues: FormNewServizioValues = { ...initialData.userData, azienda: initialData.anagrafica?.azienda || false, cap_recapiti: initialData.anagrafica?.cap_residenza || "", @@ -298,10 +298,10 @@ export const FormNewServizioAcquisto = ({ const { locale, t } = useTranslation(); const nazioni_options = GetNazioni(); - const comuni_options = getComuniNames(); + const comuni_options = getComuni(); z.config(z.locales[locale]()); - const form = useZodForm(Schema, { + const form = useZodForm(schema, { defaultValues: defaultValues, }); const DatePickerLocale = locale === "it" ? it : enUS; @@ -335,7 +335,7 @@ export const FormNewServizioAcquisto = ({ }, }); - function onSubmit(fields: FormValues) { + function onSubmit(fields: FormNewServizioValues) { mutate({ anagrafica: { azienda: fields.azienda, @@ -399,17 +399,8 @@ export const FormNewServizioAcquisto = ({ ["pianoterra", string], ]; const altrePrefMapping = t.altrePrefMapping as altrePrefMappingType; - const [ - tipologia, - azienda, - fatturazione_aziendale, - nazione_nascita, - nazione_recapiti, - budget, - ] = form.watch([ + const [tipologia, nazione_nascita, nazione_recapiti, budget] = form.watch([ "tipologia", - "azienda", - "fatturazione_aziendale", "nazione_nascita", "nazione_recapiti", "budget", @@ -438,7 +429,10 @@ export const FormNewServizioAcquisto = ({ return (
- + {texts.dettagli} @@ -882,154 +876,9 @@ export const FormNewServizioAcquisto = ({ /> - {azienda && ( - <> -
- ( - -
- - {t.anagrafica.ragioneSociale} - - -
- - - -
- )} - /> - ( - -
- - {t.anagrafica.sedeLegale} - - -
- - - -
- )} - /> -
-
- ( - -
- - {t.anagrafica.p_iva} - - -
- - - -
- )} - /> - ( - -
- - {t.anagrafica.legale_rappresentante} - - -
- - - -
- )} - /> -
- ( - -
- - {texts.fattura} - - - { - field.onChange(v); - if (!v) { - form.setValue("codice_destinatario", null); - } - }} - /> - - -
-
- )} - /> - {fatturazione_aziendale && ( - ( - -
- - {texts.sdi} - - -
+ + - - - -
- )} - /> - )} - - )}
{ field.onChange(value.value); await form.trigger("luogo_nascita"); + if (value.value !== "0") { + form.setValue("luogo_nascita", ""); + } }} options={UnpackOptions({ options: nazioni_options })} placeholder="Seleziona..." @@ -1124,6 +976,7 @@ export const FormNewServizioAcquisto = ({ name="luogo_nascita" render={({ field }) => { if (nazione_nascita === "0") { + const options = comuni_options.map((c) => c.nome); return (
@@ -1137,7 +990,7 @@ export const FormNewServizioAcquisto = ({ @@ -1310,7 +1163,9 @@ export const FormNewServizioAcquisto = ({ onValueChange={async (value) => { field.onChange(value.value); form.setValue("provincia_recapiti", ""); - await form.trigger("citta_recapiti"); + if (value.value !== "0") { + form.setValue("citta_recapiti", ""); + } }} options={UnpackOptions({ options: nazioni_options })} placeholder="Seleziona..." @@ -1322,37 +1177,52 @@ export const FormNewServizioAcquisto = ({ ( - -
- - {t.recapiti.provincia} - - -
+ render={({ field }) => { + const provinciaName = + field.value && getProvinciaFromSigla(field.value); + return ( + +
+ + {t.recapiti.provincia} + + +
- {nazione_recapiti === "0" ? ( - { - field.onChange(value.value); - }} - options={UnpackOptions({ options: provincie })} - placeholder="Seleziona" - /> - ) : ( - - - - )} -
- )} + {nazione_recapiti === "0" ? ( + { + field.onChange(value.value); + }} + options={provincieWithSigla.map((prov) => ({ + label: prov.nome, + value: prov.sigla, + }))} + placeholder="Seleziona" + /> + ) : ( + + + + )} +
+ ); + }} />
@@ -1361,6 +1231,12 @@ export const FormNewServizioAcquisto = ({ name="citta_recapiti" render={({ field }) => { 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 (
@@ -1374,7 +1250,7 @@ export const FormNewServizioAcquisto = ({ @@ -1484,7 +1360,7 @@ export const FormNewServizioAcquisto = ({
-
+
{isAdmin && ( ); }; + +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"} + + +
+ + + + +
+ )} + /> + ); +}; diff --git a/apps/infoalloggi/src/forms/FormProfilo_Anagrafica.tsx b/apps/infoalloggi/src/forms/FormProfilo_Anagrafica.tsx index fe27e37..76369c9 100644 --- a/apps/infoalloggi/src/forms/FormProfilo_Anagrafica.tsx +++ b/apps/infoalloggi/src/forms/FormProfilo_Anagrafica.tsx @@ -1,6 +1,7 @@ import { differenceInYears, format } from "date-fns"; import { enUS, it } from "date-fns/locale"; import { CalendarIcon } from "lucide-react"; +import { type Control, useWatch } from "react-hook-form"; import toast from "react-hot-toast"; import { z } from "zod/v4"; import { @@ -26,9 +27,9 @@ import { } from "~/components/ui/popover"; import { Separator } from "~/components/ui/separator"; import { Switch } from "~/components/ui/switch"; -import { getComuniNames } from "~/i18n/comuni"; +import { getComuni } from "~/i18n/comuni"; import { GetNazioni } from "~/i18n/nazioni"; -import { provincie } from "~/i18n/provincie"; +import { getProvinciaFromSigla, provincieWithSigla } from "~/i18n/provincie"; import { checkFiscalCodeValidity, getComuneFieldValue } from "~/lib/form_utils"; import { cn } from "~/lib/utils"; import { useZodForm } from "~/lib/zodForm"; @@ -36,140 +37,140 @@ import { useTranslation } from "~/providers/I18nProvider"; import type { UserWithAnagrafica } from "~/server/services/user.service"; import { api } from "~/utils/api"; +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; export const ProfileFormAnagrafica = ({ userData, }: { userData: UserWithAnagrafica; }) => { - 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(), - }) - .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"], - }); - } - 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 il codice destinatario", - path: ["codice_destinatario"], - }); - } - } - - 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 && - 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, + 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"], }); } - }, - ); + 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 il codice destinatario", + path: ["codice_destinatario"], + }); + } + } - type ProfileFormValues = z.infer; + 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, + }); + } + }, + ); const defaultValues: ProfileFormValues = { azienda: userData.azienda || false, @@ -192,9 +193,10 @@ export const ProfileFormAnagrafica = ({ via_residenza: userData.via_residenza || "", }; const { locale, t } = useTranslation(); + const DatePickerLocale = locale === "it" ? it : enUS; z.config(z.locales[locale]()); - const form = useZodForm(profileFormSchema, { + const form = useZodForm(schema, { defaultValues: defaultValues, }); @@ -220,15 +222,12 @@ export const ProfileFormAnagrafica = ({ }); } 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; + const comuni_options = getComuni(); + return ( <> + {/* */} { - if (nazione_nascita === "0") { + if (form.watch("nazione_nascita") === "0") { + const options = comuni_options.map((c) => c.nome); return (
@@ -343,7 +343,7 @@ export const ProfileFormAnagrafica = ({ @@ -405,8 +405,9 @@ export const ProfileFormAnagrafica = ({ elementId="select-sesso" elementName="sesso" isMulti={false} - onValueChange={(value) => { + onValueChange={async (value) => { field.onChange(value.value); + await form.trigger("codice_fiscale"); }} options={t.anagrafica.sesso_options} placeholder="" @@ -469,363 +470,17 @@ export const ProfileFormAnagrafica = ({ )} />
- {azienda && ( - <> -
- ( - -
- - {t.anagrafica.ragioneSociale} - - -
- - - -
- )} - /> - ( - -
- - {t.anagrafica.sedeLegale} - - -
- - - -
- )} - /> -
-
- ( - -
- - {t.anagrafica.p_iva} - - -
- - - -
- )} - /> - ( - -
- - {t.anagrafica.legale_rappresentante} - - -
- - - -
- )} - /> -
- ( - -
- - Vuoi che la fatturazione sia intestata alla tua azienda? - - - { - field.onChange(v); - if (!v) { - form.setValue("codice_destinatario", null); - } - }} - /> - - -
-
- )} - /> - {fatturazione_aziendale && ( - ( - -
- - Codice destinatario (SDI) - - -
- - - -
- )} - /> - )} - - )} + + + -
- ( - -
- - {t.recapiti.nazione} - - -
- { - form.setValue("provincia_residenza", ""); - field.onChange(value.value); - await form.trigger("comune_residenza"); - }} - options={UnpackOptions({ options: nazioni_options })} - placeholder="Seleziona" - /> -
- )} - /> - ( - -
- - {t.recapiti.provincia} - - -
- - {nazione_residenza === "0" ? ( - { - field.onChange(value.value); - }} - options={UnpackOptions({ options: provincie })} - placeholder="Seleziona" - /> - ) : ( - - - - )} -
- )} - /> -
-
- { - if (nazione_residenza === "0") { - return ( - -
- - {t.recapiti.comune} - - -
- - - { - field.onChange(value.value); - await form.trigger("comune_residenza"); - }} - options={UnpackOptions({ options: comuni_options })} - placeholder="Seleziona..." - /> - -
- ); - } - return ( - -
- - {t.recapiti.comune} - - -
- - { - field.onChange(v.target.value); - await form.trigger("comune_residenza"); - }} - type="text" - /> - -
- ); - }} - /> - ( - -
- - {t.recapiti.cap} - - - -
- - - -
- )} - /> -
-
- ( - -
- - {t.recapiti.indirizzo} - - -
- - - -
- )} - /> - - ( - -
- - {t.recapiti.civico} - - - -
- - - -
- )} - /> -
+ @@ -833,3 +488,437 @@ export const ProfileFormAnagrafica = ({ ); }; + +const AziendaSection = ({ + control, + setValue, +}: { + control: Control; + // biome-ignore lint/suspicious/noExplicitAny: + setValue: (field: keyof ProfileFormValues, value: any) => void; +}) => { + const { t } = useTranslation(); + const azienda = useWatch({ control, name: "azienda" }); + return ( + <> +
+ ( + +
+ + {t.anagrafica.ragioneSociale} + + +
+ + + +
+ )} + /> + ( + +
+ + {t.anagrafica.sedeLegale} + + +
+ + + +
+ )} + /> +
+
+ ( + +
+ {t.anagrafica.p_iva} + +
+ + + +
+ )} + /> + ( + +
+ + {t.anagrafica.legale_rappresentante} + + +
+ + + +
+ )} + /> +
+ ( + +
+ + Vuoi che la fatturazione sia intestata alla tua azienda? + + + { + field.onChange(v); + if (!v) { + setValue("codice_destinatario", null); + } + }} + /> + + +
+
+ )} + /> + + ); +}; + +const FatturazioneSection = ({ + control, +}: { + control: Control; +}) => { + const fatturazione_aziendale = useWatch({ + control, + name: "fatturazione_aziendale", + }); + return ( + <> + ( + +
+ + Codice destinatario (SDI) + + +
+ + + + +
+ )} + /> + + ); +}; + +const ResidenzaSection = ({ + control, + setValue, + trigger, +}: { + control: Control; + // biome-ignore lint/suspicious/noExplicitAny: + setValue: (field: keyof ProfileFormValues, value: any) => void; + trigger: (name?: keyof ProfileFormValues) => Promise; +}) => { + 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 ( + <> +
+ ( + +
+ + {t.recapiti.nazione} + + +
+ { + setValue("provincia_residenza", ""); + field.onChange(value.value); + await trigger("comune_residenza"); + }} + options={UnpackOptions({ options: nazioni_options })} + placeholder="Seleziona" + /> +
+ )} + /> + + { + const provinciaName = + field.value && getProvinciaFromSigla(field.value); + return ( + +
+ + {t.recapiti.provincia} + + +
+ + {nazione_residenza === "0" ? ( + { + field.onChange(value.value); + }} + options={provincieWithSigla.map((prov) => ({ + label: prov.nome, + value: prov.sigla, + }))} + placeholder="Seleziona" + /> + ) : ( + + + + )} +
+ ); + }} + /> +
+
+ { + if (nazione_residenza === "0") { + const options = comuni_options + .filter((comune) => + provincia_residenza + ? comune.provincia === provincia_residenza + : true, + ) + .map((comune) => comune.nome); + + return ( + +
+ + {t.recapiti.comune} + + +
+ + + { + field.onChange(value.value); + await trigger("comune_residenza"); + }} + options={UnpackOptions({ + options: options, + })} + placeholder="Seleziona..." + /> + +
+ ); + } + return ( + +
+ + {t.recapiti.comune} + + +
+ + { + field.onChange(v.target.value); + await trigger("comune_residenza"); + }} + type="text" + /> + +
+ ); + }} + /> + ( + +
+ {t.recapiti.cap} + + +
+ + + +
+ )} + /> +
+
+ ( + +
+ + {t.recapiti.indirizzo} + + +
+ + + +
+ )} + /> + + ( + +
+ + {t.recapiti.civico} + + + +
+ + + +
+ )} + /> +
+ + ); +}; diff --git a/apps/infoalloggi/src/i18n/comuni.ts b/apps/infoalloggi/src/i18n/comuni.ts index 9b6e562..96da3d2 100644 --- a/apps/infoalloggi/src/i18n/comuni.ts +++ b/apps/infoalloggi/src/i18n/comuni.ts @@ -24,14 +24,14 @@ const searchComune = (comune: string): Comune | null => { return result; }; let comuniNames: string[] | null = null; -const initializeComuniNames = () => { +const initializeComuniNames = (provincia?: string) => { if (!comuniNames) { - comuniNames = comuniArray.map((comune) => comune.NOME); + comuniNames = comuniArray.filter((c)=> provincia ? c.SIGLA==provincia:true).map((comune) => comune.NOME); } }; -export const getComuniNames = () => { - initializeComuniNames(); - return comuniNames!; +export const getComuni = () => { + + return comuniArray.map((comune) => ({nome:comune.NOME, provincia:comune.SIGLA})); }; export const getComuneFromIndex = (index: number): Comune | null => { initializeComuniNames(); diff --git a/apps/infoalloggi/src/i18n/provincie.ts b/apps/infoalloggi/src/i18n/provincie.ts index 4938278..3860336 100644 --- a/apps/infoalloggi/src/i18n/provincie.ts +++ b/apps/infoalloggi/src/i18n/provincie.ts @@ -1,112 +1,120 @@ -export const provincie = [ - "AGRIGENTO", - "ALESSANDRIA", - "ANCONA", - "AOSTA", - "AREZZO", - "ASCOLI PICENO", - "ASTI", - "AVELLINO", - "BARI", - "BARLETTA-ANDRIA-TRANI", - "BELLUNO", - "BENEVENTO", - "BERGAMO", - "BIELLA", - "BOLOGNA", - "BOLZANO", - "BRESCIA", - "BRINDISI", - "CAGLIARI", - "CALTANISSETTA", - "CAMPOBASSO", - "CARBONIA-IGLESIAS", - "CASERTA", - "CATANIA", - "CATANZARO", - "CHIETI", - "COMO", - "COSENZA", - "CREMONA", - "CROTONE", - "CUNEO", - "ENNA", - "FERMO", - "FERRARA", - "FIRENZE", - "FOGGIA", - "FORLÌ-CESENA", - "FROSINONE", - "GENOVA", - "GORIZIA", - "GROSSETO", - "IMPERIA", - "ISERNIA", - "LA SPEZIA", - "L'AQUILA", - "LATINA", - "LECCE", - "LECCO", - "LIVORNO", - "LODI", - "LUCCA", - "MACERATA", - "MANTOVA", - "MASSA-CARRARA", - "MATERA", - "MESSINA", - "MILANO", - "MODENA", - "MONZA E DELLA BRIANZA", - "NAPOLI", - "NOVARA", - "NUORO", - "OLBIA-TEMPIO", - "ORISTANO", - "PADOVA", - "PALERMO", - "PARMA", - "PAVIA", - "PERUGIA", - "PESARO E URBINO", - "PESCARA", - "PIACENZA", - "PISA", - "PISTOIA", - "PORDENONE", - "POTENZA", - "PRATO", - "RAGUSA", - "RAVENNA", - "REGGIO CALABRIA", - "REGGIO EMILIA", - "RIETI", - "RIMINI", - "ROMA", - "ROVIGO", - "SALERNO", - "MEDIO CAMPIDANO", - "SASSARI", - "SAVONA", - "SIENA", - "SIRACUSA", - "SONDRIO", - "TARANTO", - "TERAMO", - "TERNI", - "TORINO", - "OGLIASTRA", - "TRAPANI", - "TRENTO", - "TREVISO", - "TRIESTE", - "UDINE", - "VARESE", - "VENEZIA", - "VERBANO-CUSIO-OSSOLA", - "VERCELLI", - "VERONA", - "VIBO VALENTIA", - "VICENZA", - "VITERBO", + +export const getProvinciaFromSigla = (sigla: string): string | undefined => { + const provincia = provincieWithSigla.find((prov) => prov.sigla === sigla); + return provincia ? provincia.nome : undefined; +} +export const provincieWithSigla: { + nome: string; + sigla: string; +}[] = [ + {nome: "AGRIGENTO",sigla: "AG"}, + {nome: "ALESSANDRIA",sigla: "AL"}, + {nome: "ANCONA",sigla: "AN"}, + {nome: "AOSTA",sigla: "AO"}, + {nome: "AREZZO",sigla: "AR"}, + {nome: "ASCOLI PICENO",sigla: "AP"}, + {nome: "ASTI",sigla: "AT"}, + {nome: "AVELLINO",sigla: "AV"}, + {nome: "BARI",sigla: "BA"}, + {nome: "BARLETTA-ANDRIA-TRANI",sigla: "BT"}, + {nome: "BELLUNO",sigla: "BL"}, + {nome: "BENEVENTO",sigla: "BN"}, + {nome: "BERGAMO",sigla: "BG"}, + {nome: "BIELLA",sigla: "BI"}, + {nome: "BOLOGNA",sigla: "BO"}, + {nome: "BOLZANO",sigla: "BZ"}, + {nome: "BRESCIA",sigla: "BS"}, + {nome: "BRINDISI",sigla: "BR"}, + {nome: "CAGLIARI",sigla: "CA"}, + {nome: "CALTANISSETTA",sigla: "CL"}, + {nome: "CAMPOBASSO",sigla: "CB"}, + {nome: "CARBONIA-IGLESIAS",sigla: "CI"}, + {nome: "CASERTA",sigla: "CE"}, + {nome: "CATANIA",sigla: "CT"}, + {nome: "CATANZARO",sigla: "CZ"}, + {nome: "CHIETI",sigla: "CH"}, + {nome: "COMO",sigla: "CO"}, + {nome: "COSENZA",sigla: "CS"}, + {nome: "CREMONA",sigla: "CR"}, + {nome: "CROTONE",sigla: "KR"}, + {nome: "CUNEO",sigla: "CN"}, + {nome: "ENNA",sigla: "EN"}, + {nome: "FERMO",sigla: "FM"}, + {nome: "FERRARA",sigla: "FE"}, + {nome: "FIRENZE",sigla: "FI"}, + {nome: "FOGGIA",sigla: "FG"}, + {nome: "FORLÌ-CESENA",sigla: "FC"}, + {nome: "FROSINONE",sigla: "FR"}, + {nome: "GENOVA",sigla: "GE"}, + {nome: "GORIZIA",sigla: "GO"}, + {nome: "GROSSETO",sigla: "GR"}, + {nome: "IMPERIA",sigla: "IM"}, + {nome: "ISERNIA",sigla: "IS"}, + {nome: "LA SPEZIA",sigla: "SP"}, + {nome: "L'AQUILA",sigla: "AQ"}, + {nome: "LATINA",sigla: "LT"}, + {nome: "LECCE",sigla: "LE"}, + {nome: "LECCO",sigla: "LC"}, + {nome: "LIVORNO",sigla: "LI"}, + {nome: "LODI",sigla: "LO"}, + {nome: "LUCCA",sigla: "LU"}, + {nome: "MACERATA",sigla: "MC"}, + {nome: "MANTOVA",sigla: "MN"}, + {nome: "MASSA-CARRARA",sigla: "MS"}, + {nome: "MATERA",sigla: "MT"}, + {nome: "MESSINA",sigla: "ME"}, + {nome: "MILANO",sigla: "MI"}, + {nome: "MODENA",sigla: "MO"}, + {nome: "MONZA E DELLA BRIANZA",sigla: "MB"}, + {nome: "NAPOLI",sigla: "NA"}, + {nome: "NOVARA",sigla: "NO"}, + {nome: "NUORO",sigla: "NU"}, + {nome: "OLBIA-TEMPIO",sigla: "OT"}, + {nome: "ORISTANO",sigla: "OR"}, + {nome: "PADOVA",sigla: "PD"}, + {nome: "PALERMO",sigla: "PA"}, + {nome: "PARMA",sigla: "PR"}, + {nome: "PAVIA",sigla: "PV"}, + {nome: "PERUGIA",sigla: "PG"}, + {nome: "PESARO E URBINO",sigla: "PU"}, + {nome: "PESCARA",sigla: "PE"}, + {nome: "PIACENZA",sigla: "PC"}, + {nome: "PISA",sigla: "PI"}, + {nome: "PISTOIA",sigla: "PT"}, + {nome: "PORDENONE",sigla: "PN"}, + {nome: "POTENZA",sigla: "PZ"}, + {nome: "PRATO",sigla: "PO"}, + {nome: "RAGUSA",sigla: "RG"}, + {nome: "RAVENNA",sigla: "RA"}, + {nome: "REGGIO CALABRIA",sigla: "RC"}, + {nome: "REGGIO EMILIA",sigla: "RE"}, + {nome: "RIETI",sigla: "RI"}, + {nome: "RIMINI",sigla: "RN"}, + {nome: "ROMA",sigla: "RM"}, + {nome: "ROVIGO",sigla: "RO"}, + {nome: "SALERNO",sigla: "SA"}, + {nome: "MEDIO CAMPIDANO",sigla: "VS"}, + {nome: "SASSARI",sigla: "SS"}, + {nome: "SAVONA",sigla: "SV"}, + {nome: "SIENA",sigla: "SI"}, + {nome: "SIRACUSA",sigla: "SR"}, + {nome: "SONDRIO",sigla: "SO"}, + {nome: "TARANTO",sigla: "TA"}, + {nome: "TERAMO",sigla: "TE"}, + {nome: "TERNI",sigla: "TR"}, + {nome: "TORINO",sigla: "TO"}, + {nome: "OGLIASTRA",sigla: "OG"}, + {nome: "TRAPANI",sigla: "TP"}, + {nome: "TRENTO",sigla: "TN"}, + {nome: "TREVISO",sigla: "TV"}, + {nome: "TRIESTE",sigla: "TS"}, + {nome: "UDINE",sigla: "UD"}, + {nome: "VARESE",sigla: "VA"}, + {nome: "VENEZIA",sigla: "VE"}, + {nome: "VERBANO-CUSIO-OSSOLA",sigla: "VB"}, + {nome: "VERCELLI",sigla: "VC"}, + {nome: "VERONA",sigla: "VR"}, + {nome: "VIBO VALENTIA",sigla: "VV"}, + {nome: "VICENZA",sigla: "VI"}, + {nome: "VITERBO",sigla: "VT"} ]; \ No newline at end of file diff --git a/apps/infoalloggi/src/lib/form_utils.ts b/apps/infoalloggi/src/lib/form_utils.ts index 80fb89a..193a7eb 100644 --- a/apps/infoalloggi/src/lib/form_utils.ts +++ b/apps/infoalloggi/src/lib/form_utils.ts @@ -1,8 +1,17 @@ +import dynamic from "next/dynamic"; import type { z } from "zod/v4"; import type { ListOption } from "~/components/custom_ui/multiselect"; import { getComuneFromIndex } from "~/i18n/comuni"; import { searchNazioneByIndex } from "~/i18n/nazioni"; +export const FormDebug: React.ElementType = + process.env.NODE_ENV === "development" + ? dynamic( + () => import("@hookform/devtools").then((module) => module.DevTool), + { ssr: false }, + ) + : () => null; // Return null component in production + export const getComuneFieldValue = ( fieldValue: string, comuni_options: string[], @@ -183,8 +192,8 @@ export const checkFiscalCodeValidity = ({ gen !== codiceFiscale.slice(0, 15) && !(codiceFiscale in getAlternativeCF(gen)) ) { - console.log("gen", gen); - console.log("codiceFiscale", codiceFiscale); + //console.log("gen", gen); + //console.log("codiceFiscale", codiceFiscale); console.log("alternative", getAlternativeCF(gen)); refinementContext.issues.push({ code: "custom",