catasto
This commit is contained in:
parent
306be40555
commit
219f76dd10
16 changed files with 827 additions and 41077 deletions
|
|
@ -18,11 +18,7 @@ import {
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import InputWIcon from "~/components/custom_ui/input-icon";
|
import InputWIcon from "~/components/custom_ui/input-icon";
|
||||||
import {
|
import { MultiSelect, UnpackOptions } from "~/components/custom_ui/multiselect";
|
||||||
MultiSelect,
|
|
||||||
RepackValues,
|
|
||||||
UnpackOptions,
|
|
||||||
} from "~/components/custom_ui/multiselect";
|
|
||||||
import { PhoneInput } from "~/components/phone-input";
|
import { PhoneInput } from "~/components/phone-input";
|
||||||
import { Badge } from "~/components/ui/badge";
|
import { Badge } from "~/components/ui/badge";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
|
|
@ -49,12 +45,16 @@ import {
|
||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "~/components/ui/tooltip";
|
} from "~/components/ui/tooltip";
|
||||||
import { getComuni } from "~/i18n/comuni";
|
import {
|
||||||
import { GetNazioni } from "~/i18n/nazioni";
|
getProvinciaFromSigla,
|
||||||
import { getProvinciaFromSigla, provincieWithSigla } from "~/i18n/provincie";
|
ITALY_CATASTO_CODE,
|
||||||
import { checkFiscalCodeValidity, getComuneFieldValue } from "~/lib/form_utils";
|
parseDBComune,
|
||||||
|
parseDBNazione,
|
||||||
|
} from "~/lib/catasto";
|
||||||
|
import { checkFiscalCodeValidity } from "~/lib/form_utils";
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
|
import { useCatasto } from "~/providers/CatastoProvider";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import type { Servizio } from "~/schemas/public/Servizio";
|
import type { Servizio } from "~/schemas/public/Servizio";
|
||||||
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
|
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
|
||||||
|
|
@ -75,8 +75,8 @@ const FormNewServizioSchema = z.object({
|
||||||
azienda: z.boolean(),
|
azienda: z.boolean(),
|
||||||
budget: z.number().positive(),
|
budget: z.number().positive(),
|
||||||
cap_recapiti: z.string().length(5),
|
cap_recapiti: z.string().length(5),
|
||||||
citta_recapiti: z.string().nonempty("Inserisci una città"),
|
citta_recapiti: z.string().nullable(),
|
||||||
civico_recapiti: z.string().nonempty("Inserisci un civico"),
|
civico_recapiti: z.string(),
|
||||||
codice_destinatario: z.string().nullable(),
|
codice_destinatario: z.string().nullable(),
|
||||||
codice_fiscale: z.string(),
|
codice_fiscale: z.string(),
|
||||||
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
cognome: z.string().nonempty("Inserisci un cognome valido"),
|
||||||
|
|
@ -88,22 +88,18 @@ const FormNewServizioSchema = z.object({
|
||||||
giardino: z.boolean(),
|
giardino: z.boolean(),
|
||||||
indirizzo_recapiti: z.string().nonempty("Inserisci un indirizzo"),
|
indirizzo_recapiti: z.string().nonempty("Inserisci un indirizzo"),
|
||||||
legale_rappresentante: z.string().nullable(),
|
legale_rappresentante: z.string().nullable(),
|
||||||
luogo_nascita: z.string(),
|
luogo_nascita: z.string().nullable(),
|
||||||
motivazione_transitorio: z.string().nullable(),
|
motivazione_transitorio: z.string().nullable(),
|
||||||
n_adulti: z.number().min(1),
|
n_adulti: z.number().min(1),
|
||||||
n_minori: z.number(),
|
n_minori: z.number(),
|
||||||
nazione_nascita: z.string(),
|
nazione_nascita: z.string().nullable(),
|
||||||
nazione_recapiti: z
|
nazione_recapiti: z.string().nullable(),
|
||||||
.string()
|
|
||||||
.refine((v) => v !== "", { params: { type: "nazione" } }),
|
|
||||||
nome: z.string().nonempty("Inserisci un nome valido"),
|
nome: z.string().nonempty("Inserisci un nome valido"),
|
||||||
p_iva: z.string().nullable(),
|
p_iva: z.string().nullable(),
|
||||||
parcheggio: z.boolean(),
|
parcheggio: z.boolean(),
|
||||||
permanenza: z.number().nullable(),
|
permanenza: z.number().nullable(),
|
||||||
pianoterra: z.boolean(),
|
pianoterra: z.boolean(),
|
||||||
provincia_recapiti: z
|
provincia_recapiti: z.string().nullable(),
|
||||||
.string()
|
|
||||||
.refine((v) => v !== "", { params: { type: "provincia" } }),
|
|
||||||
ragione_sociale: z.string().nullable(),
|
ragione_sociale: z.string().nullable(),
|
||||||
reddito: z.string().nullable(),
|
reddito: z.string().nullable(),
|
||||||
sede_legale: z.string().nullable(),
|
sede_legale: z.string().nullable(),
|
||||||
|
|
@ -126,6 +122,7 @@ export const FormNewServizioAcquisto = ({
|
||||||
isAdmin?: boolean;
|
isAdmin?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { comuni, nazioni } = useCatasto();
|
||||||
const schema = FormNewServizioSchema.superRefine(
|
const schema = FormNewServizioSchema.superRefine(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
|
|
@ -150,6 +147,9 @@ export const FormNewServizioAcquisto = ({
|
||||||
ragione_sociale,
|
ragione_sociale,
|
||||||
fatturazione_aziendale,
|
fatturazione_aziendale,
|
||||||
codice_destinatario,
|
codice_destinatario,
|
||||||
|
citta_recapiti,
|
||||||
|
nazione_recapiti,
|
||||||
|
provincia_recapiti,
|
||||||
},
|
},
|
||||||
refinementContext,
|
refinementContext,
|
||||||
) => {
|
) => {
|
||||||
|
|
@ -212,19 +212,64 @@ export const FormNewServizioAcquisto = ({
|
||||||
input: "",
|
input: "",
|
||||||
message:
|
message:
|
||||||
"Il numero di telefono deve essere lungo almeno 10 caratteri",
|
"Il numero di telefono deve essere lungo almeno 10 caratteri",
|
||||||
|
path: ["telefono"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!luogo_nascita || luogo_nascita.length < 1) {
|
||||||
|
refinementContext.issues.push({
|
||||||
|
code: "custom",
|
||||||
|
input: "",
|
||||||
|
message: "Inserisci il luogo di nascita",
|
||||||
|
path: ["luogo_nascita"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!nazione_nascita || nazione_nascita.length < 1) {
|
||||||
|
refinementContext.issues.push({
|
||||||
|
code: "custom",
|
||||||
|
input: "",
|
||||||
|
message: "Inserisci la nazione di nascita",
|
||||||
|
path: ["nazione_nascita"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!citta_recapiti || citta_recapiti.length < 1) {
|
||||||
|
refinementContext.issues.push({
|
||||||
|
code: "custom",
|
||||||
|
input: "",
|
||||||
|
message: "Inserisci la città di recapiti",
|
||||||
|
path: ["citta_recapiti"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!nazione_recapiti || nazione_recapiti.length < 1) {
|
||||||
|
refinementContext.issues.push({
|
||||||
|
code: "custom",
|
||||||
|
input: "",
|
||||||
|
message: "Inserisci la nazione di recapiti",
|
||||||
|
path: ["nazione_recapiti"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!provincia_recapiti || provincia_recapiti.length < 1) {
|
||||||
|
refinementContext.issues.push({
|
||||||
|
code: "custom",
|
||||||
|
input: "",
|
||||||
|
message: "Inserisci la provincia di recapiti",
|
||||||
|
path: ["provincia_recapiti"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (luogo_nascita && nazione_nascita) {
|
||||||
|
checkFiscalCodeValidity({
|
||||||
|
codiceFiscale: codice_fiscale,
|
||||||
|
cognome,
|
||||||
|
dataNascita: data_nascita,
|
||||||
|
luogoNascita: luogo_nascita,
|
||||||
|
nazioneNascita: nazione_nascita,
|
||||||
|
nome,
|
||||||
|
path: "codice_fiscale",
|
||||||
|
refinementContext,
|
||||||
|
sesso,
|
||||||
|
comuneCatasto: comuni.find((c) => c.catasto === luogo_nascita),
|
||||||
|
nazioneCatasto: nazioni.find((c) => c.catasto === nazione_nascita),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
checkFiscalCodeValidity({
|
|
||||||
codiceFiscale: codice_fiscale,
|
|
||||||
cognome,
|
|
||||||
dataNascita: data_nascita,
|
|
||||||
luogoNascita: luogo_nascita,
|
|
||||||
nazioneNascita: nazione_nascita,
|
|
||||||
nome,
|
|
||||||
path: "codice_fiscale",
|
|
||||||
refinementContext,
|
|
||||||
sesso,
|
|
||||||
});
|
|
||||||
if (n_adulti <= 0) {
|
if (n_adulti <= 0) {
|
||||||
refinementContext.issues.push({
|
refinementContext.issues.push({
|
||||||
code: "custom",
|
code: "custom",
|
||||||
|
|
@ -287,7 +332,7 @@ export const FormNewServizioAcquisto = ({
|
||||||
...initialData.userData,
|
...initialData.userData,
|
||||||
azienda: initialData.anagrafica?.azienda || false,
|
azienda: initialData.anagrafica?.azienda || false,
|
||||||
cap_recapiti: initialData.anagrafica?.cap_residenza || "",
|
cap_recapiti: initialData.anagrafica?.cap_residenza || "",
|
||||||
citta_recapiti: initialData.anagrafica?.comune_residenza || "",
|
citta_recapiti: initialData.anagrafica?.comune_residenza || null,
|
||||||
civico_recapiti: initialData.anagrafica?.civico_residenza || "",
|
civico_recapiti: initialData.anagrafica?.civico_residenza || "",
|
||||||
codice_destinatario: initialData.anagrafica?.codice_destinatario || "",
|
codice_destinatario: initialData.anagrafica?.codice_destinatario || "",
|
||||||
codice_fiscale: initialData.anagrafica?.codice_fiscale || "",
|
codice_fiscale: initialData.anagrafica?.codice_fiscale || "",
|
||||||
|
|
@ -298,12 +343,12 @@ export const FormNewServizioAcquisto = ({
|
||||||
initialData.anagrafica?.fatturazione_aziendale || false,
|
initialData.anagrafica?.fatturazione_aziendale || false,
|
||||||
indirizzo_recapiti: initialData.anagrafica?.via_residenza || "",
|
indirizzo_recapiti: initialData.anagrafica?.via_residenza || "",
|
||||||
legale_rappresentante: initialData.anagrafica?.legale_rappresentante || "",
|
legale_rappresentante: initialData.anagrafica?.legale_rappresentante || "",
|
||||||
luogo_nascita: initialData.anagrafica?.luogo_nascita || "",
|
luogo_nascita: initialData.anagrafica?.luogo_nascita || null,
|
||||||
nazione_nascita: initialData.anagrafica?.nazione_nascita || "",
|
nazione_nascita: initialData.anagrafica?.nazione_nascita || null,
|
||||||
nazione_recapiti: initialData.anagrafica?.nazione_residenza || "",
|
nazione_recapiti: initialData.anagrafica?.nazione_residenza || null,
|
||||||
|
|
||||||
p_iva: initialData.anagrafica?.p_iva || "",
|
p_iva: initialData.anagrafica?.p_iva || "",
|
||||||
provincia_recapiti: initialData.anagrafica?.provincia_residenza || "",
|
provincia_recapiti: initialData.anagrafica?.provincia_residenza || null,
|
||||||
ragione_sociale: initialData.anagrafica?.ragione_sociale || "",
|
ragione_sociale: initialData.anagrafica?.ragione_sociale || "",
|
||||||
sede_legale: initialData.anagrafica?.sede_legale || "",
|
sede_legale: initialData.anagrafica?.sede_legale || "",
|
||||||
sesso: initialData.anagrafica?.sesso || "M",
|
sesso: initialData.anagrafica?.sesso || "M",
|
||||||
|
|
@ -311,8 +356,6 @@ export const FormNewServizioAcquisto = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const { locale, t } = useTranslation();
|
const { locale, t } = useTranslation();
|
||||||
const nazioni_options = GetNazioni();
|
|
||||||
const comuni_options = getComuni();
|
|
||||||
z.config(z.locales[locale]());
|
z.config(z.locales[locale]());
|
||||||
|
|
||||||
const form = useZodForm(schema, {
|
const form = useZodForm(schema, {
|
||||||
|
|
@ -417,10 +460,9 @@ export const FormNewServizioAcquisto = ({
|
||||||
["pianoterra", string],
|
["pianoterra", string],
|
||||||
];
|
];
|
||||||
const altrePrefMapping = t.altrePrefMapping as altrePrefMappingType;
|
const altrePrefMapping = t.altrePrefMapping as altrePrefMappingType;
|
||||||
const [tipologia, nazione_nascita, nazione_recapiti, budget] = form.watch([
|
const [tipologia, nazione_nascita, budget] = form.watch([
|
||||||
"tipologia",
|
"tipologia",
|
||||||
"nazione_nascita",
|
"nazione_nascita",
|
||||||
"nazione_recapiti",
|
|
||||||
"budget",
|
"budget",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
@ -1004,45 +1046,66 @@ export const FormNewServizioAcquisto = ({
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="nazione_nascita"
|
name="nazione_nascita"
|
||||||
render={({ field }) => (
|
render={({ field }) => {
|
||||||
<FormItem className="w-full">
|
const parsedNazioneNascita = parseDBNazione(
|
||||||
<div className="flex flex-wrap items-center gap-x-2">
|
field.value,
|
||||||
<FormLabel htmlFor="select-naz-nascita">
|
nazioni,
|
||||||
{t.anagrafica.nazioneNascita}
|
);
|
||||||
</FormLabel>
|
return (
|
||||||
<FormMessage />
|
<FormItem className="w-full">
|
||||||
</div>
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
|
<FormLabel htmlFor="select-naz-nascita">
|
||||||
|
{t.anagrafica.nazioneNascita}
|
||||||
|
</FormLabel>
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
defaultValue={RepackValues({
|
defaultValue={
|
||||||
options: nazioni_options,
|
field.value
|
||||||
values: field.value,
|
? parsedNazioneNascita
|
||||||
})}
|
? {
|
||||||
elementId="select-naz-nascita"
|
label: parsedNazioneNascita.nome,
|
||||||
elementName="nazioneNascita"
|
value: parsedNazioneNascita.catasto,
|
||||||
isMulti={false}
|
}
|
||||||
onValueChange={async (value) => {
|
: {
|
||||||
field.onChange(value.value);
|
label: field.value,
|
||||||
await form.trigger("luogo_nascita");
|
value: field.value,
|
||||||
if (value.value !== "0") {
|
}
|
||||||
form.setValue("luogo_nascita", "");
|
: undefined
|
||||||
}
|
}
|
||||||
}}
|
elementId="select-naz-nascita"
|
||||||
options={UnpackOptions({ options: nazioni_options })}
|
elementName="nazioneNascita"
|
||||||
placeholder="Seleziona..."
|
isMulti={false}
|
||||||
/>
|
onValueChange={async (value) => {
|
||||||
</FormControl>
|
field.onChange(value.value);
|
||||||
</FormItem>
|
await form.trigger("luogo_nascita");
|
||||||
)}
|
|
||||||
|
form.setValue("luogo_nascita", null);
|
||||||
|
}}
|
||||||
|
options={nazioni.map((n) => ({
|
||||||
|
label: n.nome,
|
||||||
|
value: n.catasto,
|
||||||
|
}))}
|
||||||
|
placeholder="Seleziona..."
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="luogo_nascita"
|
name="luogo_nascita"
|
||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
if (nazione_nascita === "0") {
|
if (nazione_nascita === ITALY_CATASTO_CODE) {
|
||||||
const options = comuni_options.map((c) => c.nome);
|
const parsedComuneNascita = parseDBComune(
|
||||||
|
field.value,
|
||||||
|
comuni,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormItem className="w-full">
|
<FormItem className="w-full">
|
||||||
<div className="flex flex-wrap items-center gap-x-2">
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
|
|
@ -1054,18 +1117,32 @@ export const FormNewServizioAcquisto = ({
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
defaultValue={getComuneFieldValue(
|
defaultValue={
|
||||||
field.value,
|
field.value
|
||||||
options,
|
? parsedComuneNascita
|
||||||
)}
|
? {
|
||||||
|
label: `${parsedComuneNascita.nome} (${parsedComuneNascita.sigla})`,
|
||||||
|
value: parsedComuneNascita.catasto,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
label: field.value,
|
||||||
|
value: field.value,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
elementId="select-comune-nascita"
|
elementId="select-comune-nascita"
|
||||||
elementName="luogoNascita"
|
elementName="luogoNascita"
|
||||||
isMulti={false}
|
isMulti={false}
|
||||||
onValueChange={async (value) => {
|
onValueChange={async (value) => {
|
||||||
field.onChange(value.value);
|
field.onChange(value.value);
|
||||||
await form.trigger("luogo_nascita");
|
await form.trigger("luogo_nascita");
|
||||||
|
|
||||||
|
await form.trigger("codice_fiscale");
|
||||||
}}
|
}}
|
||||||
options={UnpackOptions({ options })}
|
options={comuni.map((c) => ({
|
||||||
|
label: `${c.nome} (${c.sigla})`,
|
||||||
|
value: c.catasto,
|
||||||
|
}))}
|
||||||
placeholder="Seleziona..."
|
placeholder="Seleziona..."
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
@ -1087,8 +1164,10 @@ export const FormNewServizioAcquisto = ({
|
||||||
onChange={async (v) => {
|
onChange={async (v) => {
|
||||||
field.onChange(v.target.value);
|
field.onChange(v.target.value);
|
||||||
await form.trigger("luogo_nascita");
|
await form.trigger("luogo_nascita");
|
||||||
|
await form.trigger("codice_fiscale");
|
||||||
}}
|
}}
|
||||||
type="text"
|
type="text"
|
||||||
|
value={field.value || undefined}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
@ -1204,179 +1283,11 @@ export const FormNewServizioAcquisto = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Separator />
|
<Separator />
|
||||||
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
<ResidenzaSection
|
||||||
<FormField
|
control={form.control}
|
||||||
control={form.control}
|
setValue={form.setValue}
|
||||||
name="nazione_recapiti"
|
trigger={form.trigger}
|
||||||
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
|
|
||||||
defaultValue={RepackValues({
|
|
||||||
options: nazioni_options,
|
|
||||||
values: field.value,
|
|
||||||
})}
|
|
||||||
elementId="select-naz"
|
|
||||||
elementName="nazioneRecapiti"
|
|
||||||
isMulti={false}
|
|
||||||
onValueChange={async (value) => {
|
|
||||||
field.onChange(value.value);
|
|
||||||
form.setValue("provincia_recapiti", "");
|
|
||||||
if (value.value !== "0") {
|
|
||||||
form.setValue("citta_recapiti", "");
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
options={UnpackOptions({ options: nazioni_options })}
|
|
||||||
placeholder="Seleziona..."
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="provincia_recapiti"
|
|
||||||
render={({ field }) => {
|
|
||||||
const provinciaName =
|
|
||||||
field.value && getProvinciaFromSigla(field.value);
|
|
||||||
return (
|
|
||||||
<FormItem className="w-full">
|
|
||||||
<div className="flex flex-wrap items-center gap-x-2">
|
|
||||||
<FormLabel htmlFor="provinciaRecapiti">
|
|
||||||
{t.recapiti.provincia}
|
|
||||||
</FormLabel>
|
|
||||||
<FormMessage />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{nazione_recapiti === "0" ? (
|
|
||||||
<MultiSelect
|
|
||||||
defaultValue={
|
|
||||||
field.value && provinciaName
|
|
||||||
? {
|
|
||||||
label: provinciaName,
|
|
||||||
value: field.value,
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
elementId="provinciaRecapiti"
|
|
||||||
elementName="provincia"
|
|
||||||
isMulti={false}
|
|
||||||
onValueChange={(value) => {
|
|
||||||
field.onChange(value.value);
|
|
||||||
}}
|
|
||||||
options={provincieWithSigla.map((prov) => ({
|
|
||||||
label: prov.nome,
|
|
||||||
value: prov.sigla,
|
|
||||||
}))}
|
|
||||||
placeholder="Seleziona"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
id="provinciaRecapiti"
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
</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") {
|
|
||||||
const provincia = form.watch("provincia_recapiti");
|
|
||||||
const options = comuni_options
|
|
||||||
.filter((comune) =>
|
|
||||||
provincia ? comune.provincia === provincia : true,
|
|
||||||
)
|
|
||||||
.map((comune) => comune.nome);
|
|
||||||
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
|
|
||||||
defaultValue={getComuneFieldValue(
|
|
||||||
field.value,
|
|
||||||
options,
|
|
||||||
)}
|
|
||||||
elementId="select-comune"
|
|
||||||
elementName="citta_recapiti"
|
|
||||||
isMulti={false}
|
|
||||||
onValueChange={async (value) => {
|
|
||||||
field.onChange(value.value);
|
|
||||||
await form.trigger("citta_recapiti");
|
|
||||||
}}
|
|
||||||
options={UnpackOptions({ options })}
|
|
||||||
placeholder="Seleziona..."
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<FormItem className="w-full">
|
|
||||||
<div className="flex flex-wrap items-center gap-x-2">
|
|
||||||
<FormLabel htmlFor="citta_recapiti">
|
|
||||||
{t.recapiti.comune}
|
|
||||||
</FormLabel>
|
|
||||||
<FormMessage />
|
|
||||||
</div>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
id="citta_recapiti"
|
|
||||||
onChange={async (v) => {
|
|
||||||
field.onChange(v.target.value);
|
|
||||||
await form.trigger("citta_recapiti");
|
|
||||||
}}
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="cap_recapiti"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem className="w-full">
|
|
||||||
<div className="flex flex-wrap items-center gap-x-2">
|
|
||||||
<FormLabel htmlFor="cap">{t.recapiti.cap}</FormLabel>
|
|
||||||
|
|
||||||
<FormMessage />
|
|
||||||
</div>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
{...field}
|
|
||||||
id="cap"
|
|
||||||
placeholder="00100"
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
|
|
@ -1653,3 +1564,229 @@ const FatturazioneSection = ({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ResidenzaSection = ({
|
||||||
|
control,
|
||||||
|
trigger,
|
||||||
|
setValue,
|
||||||
|
}: {
|
||||||
|
control: Control<FormNewServizioValues>;
|
||||||
|
trigger: (name?: keyof FormNewServizioValues) => Promise<boolean>;
|
||||||
|
// biome-ignore lint/suspicious/noExplicitAny: <fine here>
|
||||||
|
setValue: (field: keyof FormNewServizioValues, value: any) => void;
|
||||||
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { comuni, nazioni, provincie } = useCatasto();
|
||||||
|
|
||||||
|
const nazione_recapiti = useWatch({
|
||||||
|
control,
|
||||||
|
name: "nazione_recapiti",
|
||||||
|
});
|
||||||
|
const provincia_recapiti = useWatch({
|
||||||
|
control,
|
||||||
|
name: "provincia_recapiti",
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex w-full flex-col items-start justify-between gap-4 sm:flex-row">
|
||||||
|
<FormField
|
||||||
|
control={control}
|
||||||
|
name="nazione_recapiti"
|
||||||
|
render={({ field }) => {
|
||||||
|
const parsedNazioneResidenza = parseDBNazione(field.value, nazioni);
|
||||||
|
return (
|
||||||
|
<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
|
||||||
|
defaultValue={
|
||||||
|
field.value
|
||||||
|
? parsedNazioneResidenza
|
||||||
|
? {
|
||||||
|
label: parsedNazioneResidenza.nome,
|
||||||
|
value: parsedNazioneResidenza.catasto,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
label: field.value,
|
||||||
|
value: field.value,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
elementId="select-naz"
|
||||||
|
elementName="nazioneRecapiti"
|
||||||
|
isMulti={false}
|
||||||
|
onValueChange={async (value) => {
|
||||||
|
setValue("provincia_recapiti", null);
|
||||||
|
setValue("citta_recapiti", null);
|
||||||
|
field.onChange(value.value);
|
||||||
|
await trigger("citta_recapiti");
|
||||||
|
}}
|
||||||
|
options={nazioni.map((n) => ({
|
||||||
|
label: n.nome,
|
||||||
|
value: n.catasto,
|
||||||
|
}))}
|
||||||
|
placeholder="Seleziona..."
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={control}
|
||||||
|
name="provincia_recapiti"
|
||||||
|
render={({ field }) => {
|
||||||
|
const parseProvincia = getProvinciaFromSigla(
|
||||||
|
field.value,
|
||||||
|
provincie,
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<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 === ITALY_CATASTO_CODE ? (
|
||||||
|
<MultiSelect
|
||||||
|
defaultValue={
|
||||||
|
field.value && parseProvincia
|
||||||
|
? {
|
||||||
|
label: parseProvincia.nome,
|
||||||
|
value: parseProvincia.sigla,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
elementId="provinciaRecapiti"
|
||||||
|
elementName="provincia"
|
||||||
|
isMulti={false}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
field.onChange(value.value);
|
||||||
|
setValue("citta_recapiti", null);
|
||||||
|
}}
|
||||||
|
options={provincie.map((prov) => ({
|
||||||
|
label: prov.nome,
|
||||||
|
value: prov.sigla,
|
||||||
|
}))}
|
||||||
|
placeholder="Seleziona"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
id="provinciaRecapiti"
|
||||||
|
type="text"
|
||||||
|
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={control}
|
||||||
|
name="citta_recapiti"
|
||||||
|
render={({ field }) => {
|
||||||
|
if (nazione_recapiti === ITALY_CATASTO_CODE) {
|
||||||
|
const parsedComuneResidenza = parseDBComune(field.value, comuni);
|
||||||
|
|
||||||
|
const options = comuni
|
||||||
|
.filter((comune) =>
|
||||||
|
provincia_recapiti
|
||||||
|
? comune.sigla === provincia_recapiti
|
||||||
|
: true,
|
||||||
|
)
|
||||||
|
.map((comune) => ({
|
||||||
|
label: comune.nome,
|
||||||
|
value: comune.catasto,
|
||||||
|
}));
|
||||||
|
|
||||||
|
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
|
||||||
|
defaultValue={
|
||||||
|
field.value && parsedComuneResidenza
|
||||||
|
? {
|
||||||
|
label: parsedComuneResidenza.nome,
|
||||||
|
value: parsedComuneResidenza.catasto,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
elementId="select-comune"
|
||||||
|
elementName="citta_recapiti"
|
||||||
|
isMulti={false}
|
||||||
|
onValueChange={async (value) => {
|
||||||
|
field.onChange(value.value);
|
||||||
|
await trigger("citta_recapiti");
|
||||||
|
}}
|
||||||
|
options={options}
|
||||||
|
placeholder="Seleziona..."
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<FormItem className="w-full">
|
||||||
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
|
<FormLabel htmlFor="citta_recapiti">
|
||||||
|
{t.recapiti.comune}
|
||||||
|
</FormLabel>
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
{...field}
|
||||||
|
id="citta_recapiti"
|
||||||
|
onChange={async (v) => {
|
||||||
|
field.onChange(v.target.value);
|
||||||
|
await trigger("citta_recapiti");
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
value={field.value || undefined}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={control}
|
||||||
|
name="cap_recapiti"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className="w-full">
|
||||||
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
|
<FormLabel htmlFor="cap">{t.recapiti.cap}</FormLabel>
|
||||||
|
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
<FormControl>
|
||||||
|
<Input {...field} id="cap" placeholder="00100" type="text" />
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,7 @@ import {
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from "~/components/custom_ui/form";
|
} from "~/components/custom_ui/form";
|
||||||
import Input from "~/components/custom_ui/input";
|
import Input from "~/components/custom_ui/input";
|
||||||
import {
|
import { MultiSelect } from "~/components/custom_ui/multiselect";
|
||||||
MultiSelect,
|
|
||||||
RepackValues,
|
|
||||||
UnpackOptions,
|
|
||||||
} from "~/components/custom_ui/multiselect";
|
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import { Calendar } from "~/components/ui/calendar";
|
import { Calendar } from "~/components/ui/calendar";
|
||||||
import {
|
import {
|
||||||
|
|
@ -27,12 +23,16 @@ import {
|
||||||
} from "~/components/ui/popover";
|
} from "~/components/ui/popover";
|
||||||
import { Separator } from "~/components/ui/separator";
|
import { Separator } from "~/components/ui/separator";
|
||||||
import { Switch } from "~/components/ui/switch";
|
import { Switch } from "~/components/ui/switch";
|
||||||
import { getComuni } from "~/i18n/comuni";
|
import {
|
||||||
import { GetNazioni } from "~/i18n/nazioni";
|
getProvinciaFromSigla,
|
||||||
import { getProvinciaFromSigla, provincieWithSigla } from "~/i18n/provincie";
|
ITALY_CATASTO_CODE,
|
||||||
import { checkFiscalCodeValidity, getComuneFieldValue } from "~/lib/form_utils";
|
parseDBComune,
|
||||||
|
parseDBNazione,
|
||||||
|
} from "~/lib/catasto";
|
||||||
|
import { checkFiscalCodeValidity } from "~/lib/form_utils";
|
||||||
import { cn } from "~/lib/utils";
|
import { cn } from "~/lib/utils";
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
|
import { useCatasto } from "~/providers/CatastoProvider";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import type { UserWithAnagrafica } from "~/server/services/user.service";
|
import type { UserWithAnagrafica } from "~/server/services/user.service";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
|
|
@ -43,15 +43,15 @@ const profileFormSchema = z.object({
|
||||||
civico_residenza: z.string().optional(),
|
civico_residenza: z.string().optional(),
|
||||||
codice_destinatario: z.string().length(7).nullable(),
|
codice_destinatario: z.string().length(7).nullable(),
|
||||||
codice_fiscale: z.string().optional(),
|
codice_fiscale: z.string().optional(),
|
||||||
comune_residenza: z.string().optional(),
|
comune_residenza: z.string().nullable(),
|
||||||
data_nascita: z.date().optional(),
|
data_nascita: z.date().optional(),
|
||||||
fatturazione_aziendale: z.boolean(),
|
fatturazione_aziendale: z.boolean(),
|
||||||
legale_rappresentante: z.string().nullable(),
|
legale_rappresentante: z.string().nullable(),
|
||||||
luogo_nascita: z.string().optional(),
|
luogo_nascita: z.string().nullable(),
|
||||||
nazione_nascita: z.string().optional(),
|
nazione_nascita: z.string().nullable(),
|
||||||
nazione_residenza: z.string().optional(),
|
nazione_residenza: z.string().nullable(),
|
||||||
p_iva: z.string().nullable(),
|
p_iva: z.string().nullable(),
|
||||||
provincia_residenza: z.string().optional(),
|
provincia_residenza: z.string().nullable(),
|
||||||
ragione_sociale: z.string().nullable(),
|
ragione_sociale: z.string().nullable(),
|
||||||
sede_legale: z.string().nullable(),
|
sede_legale: z.string().nullable(),
|
||||||
sesso: z.string().optional(),
|
sesso: z.string().optional(),
|
||||||
|
|
@ -64,6 +64,8 @@ export const ProfileFormAnagrafica = ({
|
||||||
}: {
|
}: {
|
||||||
userData: UserWithAnagrafica;
|
userData: UserWithAnagrafica;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { comuni, nazioni } = useCatasto();
|
||||||
|
|
||||||
const schema = profileFormSchema.superRefine(
|
const schema = profileFormSchema.superRefine(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
|
|
@ -167,6 +169,8 @@ export const ProfileFormAnagrafica = ({
|
||||||
path: "codice_fiscale",
|
path: "codice_fiscale",
|
||||||
refinementContext,
|
refinementContext,
|
||||||
sesso,
|
sesso,
|
||||||
|
comuneCatasto: comuni.find((c) => c.catasto === luogo_nascita),
|
||||||
|
nazioneCatasto: nazioni.find((c) => c.catasto === nazione_nascita),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -178,15 +182,15 @@ export const ProfileFormAnagrafica = ({
|
||||||
civico_residenza: userData.civico_residenza || "",
|
civico_residenza: userData.civico_residenza || "",
|
||||||
codice_destinatario: userData.codice_destinatario || null,
|
codice_destinatario: userData.codice_destinatario || null,
|
||||||
codice_fiscale: userData.codice_fiscale || "",
|
codice_fiscale: userData.codice_fiscale || "",
|
||||||
comune_residenza: userData.comune_residenza || "",
|
comune_residenza: userData.comune_residenza,
|
||||||
data_nascita: userData.data_nascita || new Date(),
|
data_nascita: userData.data_nascita || new Date(),
|
||||||
fatturazione_aziendale: userData.fatturazione_aziendale || false,
|
fatturazione_aziendale: userData.fatturazione_aziendale || false,
|
||||||
legale_rappresentante: userData.legale_rappresentante || null,
|
legale_rappresentante: userData.legale_rappresentante || null,
|
||||||
luogo_nascita: userData.luogo_nascita || "",
|
luogo_nascita: userData.luogo_nascita,
|
||||||
nazione_nascita: userData.nazione_nascita || "",
|
nazione_nascita: userData.nazione_nascita,
|
||||||
nazione_residenza: userData.nazione_residenza || "",
|
nazione_residenza: userData.nazione_residenza,
|
||||||
p_iva: userData.p_iva || null,
|
p_iva: userData.p_iva || null,
|
||||||
provincia_residenza: userData.provincia_residenza || "",
|
provincia_residenza: userData.provincia_residenza,
|
||||||
ragione_sociale: userData.ragione_sociale || null,
|
ragione_sociale: userData.ragione_sociale || null,
|
||||||
sede_legale: userData.sede_legale || null,
|
sede_legale: userData.sede_legale || null,
|
||||||
sesso: userData.sesso || "",
|
sesso: userData.sesso || "",
|
||||||
|
|
@ -222,8 +226,6 @@ export const ProfileFormAnagrafica = ({
|
||||||
data: { ...fields },
|
data: { ...fields },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const nazioni_options = GetNazioni();
|
|
||||||
const comuni_options = getComuni();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -288,46 +290,64 @@ export const ProfileFormAnagrafica = ({
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="nazione_nascita"
|
name="nazione_nascita"
|
||||||
render={({ field }) => (
|
render={({ field }) => {
|
||||||
<FormItem className="w-full">
|
const parsedNazioneNascita = parseDBNazione(
|
||||||
<div className="flex flex-wrap items-center gap-x-2">
|
field.value,
|
||||||
<FormLabel htmlFor="select-naz">
|
nazioni,
|
||||||
{t.anagrafica.nazioneNascita}
|
);
|
||||||
</FormLabel>
|
return (
|
||||||
<FormMessage />
|
<FormItem className="w-full">
|
||||||
</div>
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
|
<FormLabel htmlFor="select-naz">
|
||||||
|
{t.anagrafica.nazioneNascita}
|
||||||
|
</FormLabel>
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
defaultValue={
|
defaultValue={
|
||||||
field.value
|
field.value
|
||||||
? RepackValues({
|
? parsedNazioneNascita
|
||||||
options: nazioni_options,
|
? {
|
||||||
values: field.value,
|
label: parsedNazioneNascita.nome,
|
||||||
})
|
value: parsedNazioneNascita.catasto,
|
||||||
: undefined
|
}
|
||||||
}
|
: {
|
||||||
elementId="select-naz"
|
label: field.value,
|
||||||
elementName="nazione_nascita"
|
value: field.value,
|
||||||
isMulti={false}
|
}
|
||||||
onValueChange={async (value) => {
|
: undefined
|
||||||
field.onChange(value.value);
|
}
|
||||||
await form.trigger("luogo_nascita");
|
elementId="select-naz"
|
||||||
}}
|
elementName="nazione_nascita"
|
||||||
options={UnpackOptions({ options: nazioni_options })}
|
isMulti={false}
|
||||||
placeholder="Seleziona..."
|
onValueChange={async (value) => {
|
||||||
/>
|
field.onChange(value.value);
|
||||||
</FormControl>
|
await form.trigger("luogo_nascita");
|
||||||
</FormItem>
|
form.setValue("luogo_nascita", null);
|
||||||
)}
|
}}
|
||||||
|
options={nazioni.map((n) => ({
|
||||||
|
label: n.nome,
|
||||||
|
value: n.catasto,
|
||||||
|
}))}
|
||||||
|
placeholder="Seleziona..."
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="luogo_nascita"
|
name="luogo_nascita"
|
||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
if (form.watch("nazione_nascita") === "0") {
|
if (form.watch("nazione_nascita") === ITALY_CATASTO_CODE) {
|
||||||
const options = comuni_options.map((c) => c.nome);
|
const parsedComuneNascita = parseDBComune(
|
||||||
|
field.value,
|
||||||
|
comuni,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<FormItem className="w-full">
|
<FormItem className="w-full">
|
||||||
<div className="flex flex-wrap items-center gap-x-2">
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
|
|
@ -340,8 +360,11 @@ export const ProfileFormAnagrafica = ({
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
defaultValue={
|
defaultValue={
|
||||||
field.value
|
field.value && parsedComuneNascita
|
||||||
? getComuneFieldValue(field.value, options)
|
? {
|
||||||
|
label: `${parsedComuneNascita.nome} (${parsedComuneNascita.sigla})`,
|
||||||
|
value: parsedComuneNascita.catasto,
|
||||||
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
elementId="select-comune"
|
elementId="select-comune"
|
||||||
|
|
@ -352,7 +375,10 @@ export const ProfileFormAnagrafica = ({
|
||||||
await form.trigger("luogo_nascita");
|
await form.trigger("luogo_nascita");
|
||||||
await form.trigger("codice_fiscale");
|
await form.trigger("codice_fiscale");
|
||||||
}}
|
}}
|
||||||
options={UnpackOptions({ options })}
|
options={comuni.map((c) => ({
|
||||||
|
label: `${c.nome} (${c.sigla})`,
|
||||||
|
value: c.catasto,
|
||||||
|
}))}
|
||||||
placeholder="Seleziona..."
|
placeholder="Seleziona..."
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
@ -377,6 +403,7 @@ export const ProfileFormAnagrafica = ({
|
||||||
await form.trigger("codice_fiscale");
|
await form.trigger("codice_fiscale");
|
||||||
}}
|
}}
|
||||||
type="text"
|
type="text"
|
||||||
|
value={field.value || ""}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
@ -680,9 +707,9 @@ const ResidenzaSection = ({
|
||||||
setValue: (field: keyof ProfileFormValues, value: any) => void;
|
setValue: (field: keyof ProfileFormValues, value: any) => void;
|
||||||
trigger: (name?: keyof ProfileFormValues) => Promise<boolean>;
|
trigger: (name?: keyof ProfileFormValues) => Promise<boolean>;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { comuni, nazioni, provincie } = useCatasto();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const nazioni_options = GetNazioni();
|
|
||||||
const comuni_options = getComuni();
|
|
||||||
const nazione_residenza = useWatch({
|
const nazione_residenza = useWatch({
|
||||||
control: control,
|
control: control,
|
||||||
name: "nazione_residenza",
|
name: "nazione_residenza",
|
||||||
|
|
@ -698,44 +725,58 @@ const ResidenzaSection = ({
|
||||||
<FormField
|
<FormField
|
||||||
control={control}
|
control={control}
|
||||||
name="nazione_residenza"
|
name="nazione_residenza"
|
||||||
render={({ field }) => (
|
render={({ field }) => {
|
||||||
<FormItem className="w-full">
|
const parsedNazioneResidenza = parseDBNazione(field.value, nazioni);
|
||||||
<div className="flex flex-wrap items-center gap-x-2">
|
return (
|
||||||
<FormLabel htmlFor="nazione_residenza">
|
<FormItem className="w-full">
|
||||||
{t.recapiti.nazione}
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
</FormLabel>
|
<FormLabel htmlFor="nazione_residenza">
|
||||||
<FormMessage />
|
{t.recapiti.nazione}
|
||||||
</div>
|
</FormLabel>
|
||||||
<MultiSelect
|
<FormMessage />
|
||||||
defaultValue={
|
</div>
|
||||||
field.value
|
<MultiSelect
|
||||||
? RepackValues({
|
defaultValue={
|
||||||
options: nazioni_options,
|
field.value
|
||||||
values: field.value,
|
? parsedNazioneResidenza
|
||||||
})
|
? {
|
||||||
: undefined
|
label: parsedNazioneResidenza.nome,
|
||||||
}
|
value: parsedNazioneResidenza.catasto,
|
||||||
elementId="nazione_residenza"
|
}
|
||||||
elementName="nazione"
|
: {
|
||||||
isMulti={false}
|
label: field.value,
|
||||||
onValueChange={async (value) => {
|
value: field.value,
|
||||||
setValue("provincia_residenza", "");
|
}
|
||||||
field.onChange(value.value);
|
: undefined
|
||||||
await trigger("comune_residenza");
|
}
|
||||||
}}
|
elementId="nazione_residenza"
|
||||||
options={UnpackOptions({ options: nazioni_options })}
|
elementName="nazione"
|
||||||
placeholder="Seleziona"
|
isMulti={false}
|
||||||
/>
|
onValueChange={async (value) => {
|
||||||
</FormItem>
|
setValue("provincia_residenza", null);
|
||||||
)}
|
setValue("comune_residenza", null);
|
||||||
|
field.onChange(value.value);
|
||||||
|
await trigger("comune_residenza");
|
||||||
|
}}
|
||||||
|
options={nazioni.map((n) => ({
|
||||||
|
label: n.nome,
|
||||||
|
value: n.catasto,
|
||||||
|
}))}
|
||||||
|
placeholder="Seleziona"
|
||||||
|
/>
|
||||||
|
</FormItem>
|
||||||
|
);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormField
|
<FormField
|
||||||
control={control}
|
control={control}
|
||||||
name="provincia_residenza"
|
name="provincia_residenza"
|
||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
const provinciaName =
|
const parseProvincia = getProvinciaFromSigla(
|
||||||
field.value && getProvinciaFromSigla(field.value);
|
field.value,
|
||||||
|
provincie,
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<FormItem className="w-full">
|
<FormItem className="w-full">
|
||||||
<div className="flex flex-wrap items-center gap-x-2">
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
|
|
@ -745,13 +786,13 @@ const ResidenzaSection = ({
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{nazione_residenza === "0" ? (
|
{nazione_residenza === ITALY_CATASTO_CODE ? (
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
defaultValue={
|
defaultValue={
|
||||||
field.value && provinciaName
|
field.value && parseProvincia
|
||||||
? {
|
? {
|
||||||
label: provinciaName,
|
label: parseProvincia.nome,
|
||||||
value: field.value,
|
value: parseProvincia.sigla,
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
|
@ -760,8 +801,9 @@ const ResidenzaSection = ({
|
||||||
isMulti={false}
|
isMulti={false}
|
||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
field.onChange(value.value);
|
field.onChange(value.value);
|
||||||
|
setValue("comune_residenza", null);
|
||||||
}}
|
}}
|
||||||
options={provincieWithSigla.map((prov) => ({
|
options={provincie.map((prov) => ({
|
||||||
label: prov.nome,
|
label: prov.nome,
|
||||||
value: prov.sigla,
|
value: prov.sigla,
|
||||||
}))}
|
}))}
|
||||||
|
|
@ -769,7 +811,12 @@ const ResidenzaSection = ({
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input {...field} id="provincia_residenza" type="text" />
|
<Input
|
||||||
|
{...field}
|
||||||
|
id="provincia_residenza"
|
||||||
|
type="text"
|
||||||
|
value={field.value || undefined}
|
||||||
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
)}
|
)}
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
@ -782,14 +829,19 @@ const ResidenzaSection = ({
|
||||||
control={control}
|
control={control}
|
||||||
name="comune_residenza"
|
name="comune_residenza"
|
||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
if (nazione_residenza === "0") {
|
if (nazione_residenza === ITALY_CATASTO_CODE) {
|
||||||
const options = comuni_options
|
const parsedComuneResidenza = parseDBComune(field.value, comuni);
|
||||||
|
|
||||||
|
const options = comuni
|
||||||
.filter((comune) =>
|
.filter((comune) =>
|
||||||
provincia_residenza
|
provincia_residenza
|
||||||
? comune.provincia === provincia_residenza
|
? comune.sigla === provincia_residenza
|
||||||
: true,
|
: true,
|
||||||
)
|
)
|
||||||
.map((comune) => comune.nome);
|
.map((comune) => ({
|
||||||
|
label: comune.nome,
|
||||||
|
value: comune.catasto,
|
||||||
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormItem className="w-full">
|
<FormItem className="w-full">
|
||||||
|
|
@ -803,8 +855,11 @@ const ResidenzaSection = ({
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
defaultValue={
|
defaultValue={
|
||||||
field.value
|
field.value && parsedComuneResidenza
|
||||||
? getComuneFieldValue(field.value, options)
|
? {
|
||||||
|
label: parsedComuneResidenza.nome,
|
||||||
|
value: parsedComuneResidenza.catasto,
|
||||||
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
elementId="select-comune"
|
elementId="select-comune"
|
||||||
|
|
@ -814,9 +869,7 @@ const ResidenzaSection = ({
|
||||||
field.onChange(value.value);
|
field.onChange(value.value);
|
||||||
await trigger("comune_residenza");
|
await trigger("comune_residenza");
|
||||||
}}
|
}}
|
||||||
options={UnpackOptions({
|
options={options}
|
||||||
options: options,
|
|
||||||
})}
|
|
||||||
placeholder="Seleziona..."
|
placeholder="Seleziona..."
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
@ -841,6 +894,7 @@ const ResidenzaSection = ({
|
||||||
await trigger("comune_residenza");
|
await trigger("comune_residenza");
|
||||||
}}
|
}}
|
||||||
type="text"
|
type="text"
|
||||||
|
value={field.value || undefined}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,120 +0,0 @@
|
||||||
|
|
||||||
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"}
|
|
||||||
];
|
|
||||||
60
apps/infoalloggi/src/lib/catasto.ts
Normal file
60
apps/infoalloggi/src/lib/catasto.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
import type { Comuni } from "~/schemas/public/Comuni";
|
||||||
|
import type { Nazioni } from "~/schemas/public/Nazioni";
|
||||||
|
import type { Provincie } from "~/schemas/public/Provincie";
|
||||||
|
|
||||||
|
export const ITALY_CATASTO_CODE = "0000";
|
||||||
|
export const isNazioneCatastoValid = (str: string) => {
|
||||||
|
if (str.length !== 4) return false;
|
||||||
|
if (str === ITALY_CATASTO_CODE) return true;
|
||||||
|
return /^Z[0-9]{3}$/.test(str);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isComuneCatastoValid = (str: string) => {
|
||||||
|
if (str.length !== 4) return false;
|
||||||
|
return /^[A-Z][0-9]{3}$/.test(str);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getComuneFromCatasto = (
|
||||||
|
codice_catasto: string,
|
||||||
|
comuni_options: Comuni[],
|
||||||
|
): Comuni | undefined => {
|
||||||
|
return comuni_options.find((c) => c.catasto === codice_catasto);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getNazioneFromCatasto = (
|
||||||
|
codice_catasto: string,
|
||||||
|
nazioni_options: Nazioni[],
|
||||||
|
): Nazioni | undefined => {
|
||||||
|
return nazioni_options.find((n) => n.catasto === codice_catasto);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const parseDBComune = (
|
||||||
|
db_value: string | null,
|
||||||
|
comuni: Comuni[],
|
||||||
|
): Comuni | undefined => {
|
||||||
|
if (!db_value) return undefined;
|
||||||
|
if (isComuneCatastoValid(db_value)) {
|
||||||
|
return getComuneFromCatasto(db_value, comuni);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const parseDBNazione = (
|
||||||
|
db_value: string | null,
|
||||||
|
nazioni: Nazioni[],
|
||||||
|
): Nazioni | undefined => {
|
||||||
|
if (!db_value) return undefined;
|
||||||
|
if (isNazioneCatastoValid(db_value)) {
|
||||||
|
return getNazioneFromCatasto(db_value, nazioni);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getProvinciaFromSigla = (
|
||||||
|
str: string | null,
|
||||||
|
provincie: Provincie[],
|
||||||
|
): Provincie | undefined => {
|
||||||
|
if (!str) return undefined;
|
||||||
|
if (str.length !== 2) return undefined;
|
||||||
|
return provincie.find((p) => p.sigla === str);
|
||||||
|
};
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import type { z } from "zod/v4";
|
import type { z } from "zod/v4";
|
||||||
import type { ListOption } from "~/components/custom_ui/multiselect";
|
import type { ListOption } from "~/components/custom_ui/multiselect";
|
||||||
import { getComuneFromIndex } from "~/i18n/comuni";
|
import type { Comuni } from "~/schemas/public/Comuni";
|
||||||
import { searchNazioneByIndex } from "~/i18n/nazioni";
|
import type { Nazioni } from "~/schemas/public/Nazioni";
|
||||||
|
import { ITALY_CATASTO_CODE } from "./catasto";
|
||||||
|
|
||||||
export const FormDebug: React.ElementType =
|
export const FormDebug: React.ElementType =
|
||||||
process.env.NODE_ENV === "development"
|
process.env.NODE_ENV === "development"
|
||||||
|
|
@ -87,50 +88,22 @@ const getAlternativeCF = (input: string): string[] => {
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
const genCatasto = ({
|
|
||||||
luogoNascita,
|
|
||||||
nazioneNascita,
|
|
||||||
}: {
|
|
||||||
luogoNascita: string;
|
|
||||||
nazioneNascita: string;
|
|
||||||
}) => {
|
|
||||||
let catasto = "";
|
|
||||||
if (nazioneNascita === "0") {
|
|
||||||
if (luogoNascita !== "") {
|
|
||||||
const comune = getComuneFromIndex(parseInt(luogoNascita));
|
|
||||||
if (comune) {
|
|
||||||
catasto = comune.CATASTO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (nazioneNascita !== "") {
|
|
||||||
const nazione = searchNazioneByIndex(parseInt(nazioneNascita));
|
|
||||||
if (nazione) {
|
|
||||||
catasto = nazione.CATASTO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return catasto;
|
|
||||||
};
|
|
||||||
|
|
||||||
const gen15CF = ({
|
const gen15CF = ({
|
||||||
cognome,
|
cognome,
|
||||||
nome,
|
nome,
|
||||||
dataNascita,
|
dataNascita,
|
||||||
sesso,
|
sesso,
|
||||||
luogoNascita,
|
catasto,
|
||||||
nazioneNascita,
|
|
||||||
}: {
|
}: {
|
||||||
cognome: string;
|
cognome: string;
|
||||||
nome: string;
|
nome: string;
|
||||||
dataNascita: Date;
|
dataNascita: Date;
|
||||||
sesso: string;
|
sesso: string;
|
||||||
luogoNascita: string;
|
catasto: string;
|
||||||
nazioneNascita: string;
|
|
||||||
}): string => {
|
}): string => {
|
||||||
const data = new Date(dataNascita);
|
const data = new Date(dataNascita);
|
||||||
|
|
||||||
return `${getInizialiCF(cognome)}${getInizialiCF(nome)}${data.getFullYear().toString().slice(-2)}${getMonthLetterCF(data.getMonth())}${getDayCF(data.getDate(), sesso)}${genCatasto({ luogoNascita, nazioneNascita })}`;
|
return `${getInizialiCF(cognome)}${getInizialiCF(nome)}${data.getFullYear().toString().slice(-2)}${getMonthLetterCF(data.getMonth())}${getDayCF(data.getDate(), sesso)}${catasto}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const set1 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
const set1 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
|
@ -165,6 +138,8 @@ export const checkFiscalCodeValidity = ({
|
||||||
refinementContext,
|
refinementContext,
|
||||||
luogoNascita,
|
luogoNascita,
|
||||||
nazioneNascita,
|
nazioneNascita,
|
||||||
|
comuneCatasto,
|
||||||
|
nazioneCatasto,
|
||||||
}: {
|
}: {
|
||||||
path: string;
|
path: string;
|
||||||
codiceFiscale: string;
|
codiceFiscale: string;
|
||||||
|
|
@ -175,14 +150,31 @@ export const checkFiscalCodeValidity = ({
|
||||||
refinementContext: z.RefinementCtx;
|
refinementContext: z.RefinementCtx;
|
||||||
luogoNascita: string;
|
luogoNascita: string;
|
||||||
nazioneNascita: string;
|
nazioneNascita: string;
|
||||||
|
comuneCatasto: Comuni | undefined;
|
||||||
|
nazioneCatasto: Nazioni | undefined;
|
||||||
}) => {
|
}) => {
|
||||||
const cognomeUpper = cognome.toUpperCase();
|
const cognomeUpper = cognome.toUpperCase();
|
||||||
const nomeUpper = nome.toUpperCase();
|
const nomeUpper = nome.toUpperCase();
|
||||||
|
|
||||||
|
let codiceCatasto = "";
|
||||||
|
if (nazioneNascita === ITALY_CATASTO_CODE) {
|
||||||
|
if (luogoNascita !== "") {
|
||||||
|
if (comuneCatasto) {
|
||||||
|
codiceCatasto = comuneCatasto.catasto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (nazioneNascita !== "") {
|
||||||
|
if (nazioneCatasto) {
|
||||||
|
codiceCatasto = nazioneCatasto.catasto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const gen = gen15CF({
|
const gen = gen15CF({
|
||||||
cognome: cognomeUpper,
|
cognome: cognomeUpper,
|
||||||
dataNascita,
|
dataNascita,
|
||||||
luogoNascita,
|
catasto: codiceCatasto,
|
||||||
nazioneNascita,
|
|
||||||
nome: nomeUpper,
|
nome: nomeUpper,
|
||||||
sesso,
|
sesso,
|
||||||
});
|
});
|
||||||
|
|
@ -228,7 +220,7 @@ export const checkFiscalCodeValidity = ({
|
||||||
refinementContext.issues.push({
|
refinementContext.issues.push({
|
||||||
code: "custom",
|
code: "custom",
|
||||||
input: "",
|
input: "",
|
||||||
message: "Inserisci un codice fiscale valido",
|
message: `Inserisci un codice fiscale valido: received ${codiceFiscale}`,
|
||||||
path: [path],
|
path: [path],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -277,10 +269,13 @@ export const checkFiscalCodeValidity = ({
|
||||||
path: [path],
|
path: [path],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (nazioneNascita === "0") {
|
|
||||||
|
if (nazioneNascita === ITALY_CATASTO_CODE) {
|
||||||
if (luogoNascita !== "") {
|
if (luogoNascita !== "") {
|
||||||
const comune = getComuneFromIndex(parseInt(luogoNascita));
|
if (
|
||||||
if (comune && codiceFiscale.slice(11, 15) !== comune.CATASTO) {
|
comuneCatasto &&
|
||||||
|
codiceFiscale.slice(11, 15) !== comuneCatasto.catasto
|
||||||
|
) {
|
||||||
refinementContext.issues.push({
|
refinementContext.issues.push({
|
||||||
code: "custom",
|
code: "custom",
|
||||||
input: "",
|
input: "",
|
||||||
|
|
@ -291,8 +286,10 @@ export const checkFiscalCodeValidity = ({
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (nazioneNascita !== "") {
|
if (nazioneNascita !== "") {
|
||||||
const nazione = searchNazioneByIndex(parseInt(nazioneNascita));
|
if (
|
||||||
if (nazione && codiceFiscale.slice(11, 15) !== nazione.CATASTO) {
|
nazioneCatasto &&
|
||||||
|
codiceFiscale.slice(11, 15) !== nazioneCatasto.catasto
|
||||||
|
) {
|
||||||
refinementContext.issues.push({
|
refinementContext.issues.push({
|
||||||
code: "custom",
|
code: "custom",
|
||||||
input: "",
|
input: "",
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import { OverridePasswordForm } from "~/forms/FormOverridePassword";
|
||||||
import { ProfileFormAccount } from "~/forms/FormProfilo_Account";
|
import { ProfileFormAccount } from "~/forms/FormProfilo_Account";
|
||||||
import { ProfileFormAnagrafica } from "~/forms/FormProfilo_Anagrafica";
|
import { ProfileFormAnagrafica } from "~/forms/FormProfilo_Anagrafica";
|
||||||
import type { NextPageWithLayout } from "~/pages/_app";
|
import type { NextPageWithLayout } from "~/pages/_app";
|
||||||
|
import { CatastoProvider } from "~/providers/CatastoProvider";
|
||||||
import type { UsersId } from "~/schemas/public/Users";
|
import type { UsersId } from "~/schemas/public/Users";
|
||||||
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
|
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
|
||||||
import { zUserId } from "~/server/utils/zod_types";
|
import { zUserId } from "~/server/utils/zod_types";
|
||||||
|
|
@ -193,7 +194,9 @@ const EditUser: NextPageWithLayout<EditUserProps> = ({
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent className="mt-5 h-full space-y-6" value="anagrafica">
|
<TabsContent className="mt-5 h-full space-y-6" value="anagrafica">
|
||||||
<ProfileFormAnagrafica userData={userData} />
|
<CatastoProvider>
|
||||||
|
<ProfileFormAnagrafica userData={userData} />
|
||||||
|
</CatastoProvider>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent className="mt-5 h-full space-y-6" value="documenti">
|
<TabsContent className="mt-5 h-full space-y-6" value="documenti">
|
||||||
<DocumentiPersonali userData={userData} />
|
<DocumentiPersonali userData={userData} />
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { LoadingPage } from "~/components/loading";
|
||||||
import { Status500 } from "~/components/status-page";
|
import { Status500 } from "~/components/status-page";
|
||||||
import { FormNewServizioAcquisto } from "~/forms/FormNewServizioAcquisto";
|
import { FormNewServizioAcquisto } from "~/forms/FormNewServizioAcquisto";
|
||||||
import type { NextPageWithLayout } from "~/pages/_app";
|
import type { NextPageWithLayout } from "~/pages/_app";
|
||||||
|
import { CatastoProvider } from "~/providers/CatastoProvider";
|
||||||
import type { ServizioServizioId } from "~/schemas/public/Servizio";
|
import type { ServizioServizioId } from "~/schemas/public/Servizio";
|
||||||
import type { UsersId } from "~/schemas/public/Users";
|
import type { UsersId } from "~/schemas/public/Users";
|
||||||
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
|
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
|
||||||
|
|
@ -34,11 +35,13 @@ const OnboardUser: NextPageWithLayout<OnboardUserProps> = ({
|
||||||
Onboarding Utente (Versione Admin)
|
Onboarding Utente (Versione Admin)
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<FormNewServizioAcquisto
|
<CatastoProvider>
|
||||||
initialData={data}
|
<FormNewServizioAcquisto
|
||||||
isAdmin
|
initialData={data}
|
||||||
userId={data.userData.id}
|
isAdmin
|
||||||
/>
|
userId={data.userData.id}
|
||||||
|
/>
|
||||||
|
</CatastoProvider>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import { ChangePasswordForm } from "~/forms/FormChangePassword";
|
||||||
import { ProfileFormAccount } from "~/forms/FormProfilo_Account";
|
import { ProfileFormAccount } from "~/forms/FormProfilo_Account";
|
||||||
import { ProfileFormAnagrafica } from "~/forms/FormProfilo_Anagrafica";
|
import { ProfileFormAnagrafica } from "~/forms/FormProfilo_Anagrafica";
|
||||||
import type { NextPageWithLayout } from "~/pages/_app";
|
import type { NextPageWithLayout } from "~/pages/_app";
|
||||||
|
import { CatastoProvider } from "~/providers/CatastoProvider";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import { useEnforcedSession } from "~/providers/SessionProvider";
|
import { useEnforcedSession } from "~/providers/SessionProvider";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
|
|
@ -104,7 +105,9 @@ const Dashboard: NextPageWithLayout = () => {
|
||||||
</CardDescription>
|
</CardDescription>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<ProfileFormAnagrafica userData={userData} />
|
<CatastoProvider>
|
||||||
|
<ProfileFormAnagrafica userData={userData} />
|
||||||
|
</CatastoProvider>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import { OnboardTutorial } from "~/components/onboard_tutorial";
|
||||||
import { Status500 } from "~/components/status-page";
|
import { Status500 } from "~/components/status-page";
|
||||||
import { FormNewServizioAcquisto } from "~/forms/FormNewServizioAcquisto";
|
import { FormNewServizioAcquisto } from "~/forms/FormNewServizioAcquisto";
|
||||||
import type { NextPageWithLayout } from "~/pages/_app";
|
import type { NextPageWithLayout } from "~/pages/_app";
|
||||||
|
import { CatastoProvider } from "~/providers/CatastoProvider";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
import type { ServizioServizioId } from "~/schemas/public/Servizio";
|
import type { ServizioServizioId } from "~/schemas/public/Servizio";
|
||||||
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
|
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
|
||||||
|
|
@ -36,7 +37,9 @@ const OnboardServizio: NextPageWithLayout<OnboardServizioProps> = ({
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<OnboardTutorial />
|
<OnboardTutorial />
|
||||||
<FormNewServizioAcquisto initialData={data} userId={data.userData.id} />
|
<CatastoProvider>
|
||||||
|
<FormNewServizioAcquisto initialData={data} userId={data.userData.id} />
|
||||||
|
</CatastoProvider>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
42
apps/infoalloggi/src/providers/CatastoProvider.tsx
Normal file
42
apps/infoalloggi/src/providers/CatastoProvider.tsx
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { createContext, type ReactNode, useContext } from "react";
|
||||||
|
import { LoadingPage } from "~/components/loading";
|
||||||
|
import type { Comuni } from "~/schemas/public/Comuni";
|
||||||
|
import type { Nazioni } from "~/schemas/public/Nazioni";
|
||||||
|
import type { Provincie } from "~/schemas/public/Provincie";
|
||||||
|
import { api } from "~/utils/api";
|
||||||
|
|
||||||
|
type CatastoContextType = {
|
||||||
|
comuni: Comuni[];
|
||||||
|
provincie: Provincie[];
|
||||||
|
nazioni: Nazioni[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const CatastoContext = createContext<CatastoContextType | null>(null);
|
||||||
|
|
||||||
|
export const CatastoProvider = ({ children }: { children: ReactNode }) => {
|
||||||
|
const { data: comuni = [], isLoading: isLoadingComune } =
|
||||||
|
api.catasto.getComuni.useQuery();
|
||||||
|
const { data: provincie = [], isLoading: isLoadingProvincie } =
|
||||||
|
api.catasto.getProvincie.useQuery();
|
||||||
|
const { data: nazioni = [], isLoading: isLoadingNazioni } =
|
||||||
|
api.catasto.getNazioni.useQuery();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CatastoContext.Provider value={{ comuni, provincie, nazioni }}>
|
||||||
|
{isLoadingComune || isLoadingProvincie || isLoadingNazioni ? (
|
||||||
|
<LoadingPage />
|
||||||
|
) : (
|
||||||
|
children
|
||||||
|
)}
|
||||||
|
</CatastoContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCatasto = () => {
|
||||||
|
const context = useContext(CatastoContext);
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useCatasto must be used within a CatastoProvider");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
@ -19,6 +19,7 @@ import { stripeRouter } from "~/server/api/routers/stripe";
|
||||||
import { testRouter } from "~/server/api/routers/test";
|
import { testRouter } from "~/server/api/routers/test";
|
||||||
import { usersRouter } from "~/server/api/routers/users";
|
import { usersRouter } from "~/server/api/routers/users";
|
||||||
import { createTRPCRouter } from "~/server/api/trpc";
|
import { createTRPCRouter } from "~/server/api/trpc";
|
||||||
|
import { catastoRouter } from "./routers/catasto";
|
||||||
import { syncRouter } from "./routers/sync";
|
import { syncRouter } from "./routers/sync";
|
||||||
|
|
||||||
//import { lazy } from '@trpc/server';
|
//import { lazy } from '@trpc/server';
|
||||||
|
|
@ -45,5 +46,6 @@ export const appRouter = createTRPCRouter({
|
||||||
test: testRouter,
|
test: testRouter,
|
||||||
users: usersRouter,
|
users: usersRouter,
|
||||||
sync: syncRouter,
|
sync: syncRouter,
|
||||||
|
catasto: catastoRouter,
|
||||||
});
|
});
|
||||||
export type AppRouter = typeof appRouter;
|
export type AppRouter = typeof appRouter;
|
||||||
|
|
|
||||||
41
apps/infoalloggi/src/server/api/routers/catasto.ts
Normal file
41
apps/infoalloggi/src/server/api/routers/catasto.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
import z from "zod";
|
||||||
|
import { createTRPCRouter, publicProcedure } from "~/server/api/trpc";
|
||||||
|
import {
|
||||||
|
getComuneById,
|
||||||
|
getComuni,
|
||||||
|
getNazioneById,
|
||||||
|
getNazioni,
|
||||||
|
getProvincie,
|
||||||
|
} from "~/server/controllers/catasto.controller";
|
||||||
|
|
||||||
|
import { zComuneId, zNazioneId } from "~/server/utils/zod_types";
|
||||||
|
|
||||||
|
export const catastoRouter = createTRPCRouter({
|
||||||
|
getComuni: publicProcedure.query(async () => {
|
||||||
|
return await getComuni();
|
||||||
|
}),
|
||||||
|
getComuneById: publicProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
id: zComuneId,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ input }) => {
|
||||||
|
return await getComuneById(input.id);
|
||||||
|
}),
|
||||||
|
getProvincie: publicProcedure.query(async () => {
|
||||||
|
return await getProvincie();
|
||||||
|
}),
|
||||||
|
getNazioni: publicProcedure.query(async () => {
|
||||||
|
return await getNazioni();
|
||||||
|
}),
|
||||||
|
getNazioneById: publicProcedure
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
id: zNazioneId,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.query(async ({ input }) => {
|
||||||
|
return await getNazioneById(input.id);
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { TRPCError } from "@trpc/server";
|
||||||
|
import type { Comuni, ComuniId } from "~/schemas/public/Comuni";
|
||||||
|
import type { NazioniId } from "~/schemas/public/Nazioni";
|
||||||
|
import { db } from "../db";
|
||||||
|
|
||||||
|
export type Comune = Pick<Comuni, "id" | "nome" | "sigla">;
|
||||||
|
export const getComuni = async () => {
|
||||||
|
try {
|
||||||
|
return await db.selectFrom("comuni").selectAll().execute();
|
||||||
|
} catch (e) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
|
message: `Error while getting Comuni: ${(e as Error).message}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getComuneById = async (id: ComuniId) => {
|
||||||
|
try {
|
||||||
|
return await db
|
||||||
|
.selectFrom("comuni")
|
||||||
|
.selectAll()
|
||||||
|
.where("id", "=", id)
|
||||||
|
.executeTakeFirst();
|
||||||
|
} catch (e) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
|
message: `Error while getting ComuneById: ${(e as Error).message}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getProvincie = async () => {
|
||||||
|
try {
|
||||||
|
return await db.selectFrom("provincie").selectAll().execute();
|
||||||
|
} catch (e) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
|
message: `Error while getting Provincie: ${(e as Error).message}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getNazioni = async () => {
|
||||||
|
try {
|
||||||
|
return await db.selectFrom("nazioni").selectAll().execute();
|
||||||
|
} catch (e) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
|
message: `Error while getting Nazioni: ${(e as Error).message}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const getNazioneById = async (id: NazioniId) => {
|
||||||
|
try {
|
||||||
|
return await db
|
||||||
|
.selectFrom("nazioni")
|
||||||
|
.selectAll()
|
||||||
|
.where("id", "=", id)
|
||||||
|
.executeTakeFirst();
|
||||||
|
} catch (e) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
|
message: `Error while getting NazioneById: ${(e as Error).message}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -3,9 +3,11 @@ import type { AnnunciId } from "~/schemas/public/Annunci";
|
||||||
import type { BanlistId } from "~/schemas/public/Banlist";
|
import type { BanlistId } from "~/schemas/public/Banlist";
|
||||||
import BanType from "~/schemas/public/BanType";
|
import BanType from "~/schemas/public/BanType";
|
||||||
import type { ChatsChatid } from "~/schemas/public/Chats";
|
import type { ChatsChatid } from "~/schemas/public/Chats";
|
||||||
|
import type { ComuniId } from "~/schemas/public/Comuni";
|
||||||
import type { EtichetteIdEtichetta } from "~/schemas/public/Etichette";
|
import type { EtichetteIdEtichetta } from "~/schemas/public/Etichette";
|
||||||
import type { FlagsId } from "~/schemas/public/Flags";
|
import type { FlagsId } from "~/schemas/public/Flags";
|
||||||
import type { MessagesMessageid } from "~/schemas/public/Messages";
|
import type { MessagesMessageid } from "~/schemas/public/Messages";
|
||||||
|
import type { NazioniId } from "~/schemas/public/Nazioni";
|
||||||
import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
|
import type { OrdiniOrdineId } from "~/schemas/public/Ordini";
|
||||||
import type { PaymentsId } from "~/schemas/public/Payments";
|
import type { PaymentsId } from "~/schemas/public/Payments";
|
||||||
import type { PrezziarioIdprezziario } from "~/schemas/public/Prezziario";
|
import type { PrezziarioIdprezziario } from "~/schemas/public/Prezziario";
|
||||||
|
|
@ -82,3 +84,13 @@ export const zPagamentoId = z.custom<PaymentsId>(
|
||||||
(val) => typeof val === "string",
|
(val) => typeof val === "string",
|
||||||
"falied to validate PagamentoId",
|
"falied to validate PagamentoId",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const zComuneId = z.custom<ComuniId>(
|
||||||
|
(val) => typeof val === "number",
|
||||||
|
"falied to validate ComuneId",
|
||||||
|
);
|
||||||
|
|
||||||
|
export const zNazioneId = z.custom<NazioniId>(
|
||||||
|
(val) => typeof val === "number",
|
||||||
|
"falied to validate NazioneId",
|
||||||
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue