refactor: implement NullableStringOnChange utility for improved form handling across multiple components

This commit is contained in:
Marco Pedone 2025-12-17 16:38:15 +01:00
parent b376de48bb
commit bc9689cb4d
7 changed files with 151 additions and 68 deletions

View file

@ -118,7 +118,7 @@ export const FormBanlist = ({
placeholder=""
{...field}
id="testo"
value={field.value || ""}
value={field.value}
/>
</FormControl>
</FormItem>

View file

@ -18,6 +18,7 @@ import {
SelectValue,
} from "~/components/ui/select";
import { Switch } from "~/components/ui/switch";
import { NullableStringOnChange } from "~/lib/form_utils";
import { useZodForm } from "~/lib/zodForm";
import type { Banners, BannersIdbanner } from "~/schemas/public/Banners";
@ -123,6 +124,7 @@ export const FormBanners = ({
placeholder=""
{...field}
id="titolo"
onChange={(e) => NullableStringOnChange(e, field.onChange)}
value={field.value || ""}
/>
</FormControl>
@ -143,6 +145,7 @@ export const FormBanners = ({
placeholder=""
{...field}
id="testo"
onChange={(e) => NullableStringOnChange(e, field.onChange)}
value={field.value || ""}
/>
</FormControl>
@ -229,6 +232,7 @@ export const FormBanners = ({
placeholder=""
{...field}
id="cta_href"
onChange={(e) => NullableStringOnChange(e, field.onChange)}
value={field.value || ""}
/>
</FormControl>
@ -251,6 +255,7 @@ export const FormBanners = ({
placeholder=""
{...field}
id="cta_icon"
onChange={(e) => NullableStringOnChange(e, field.onChange)}
value={field.value || ""}
/>
</FormControl>
@ -271,6 +276,7 @@ export const FormBanners = ({
placeholder=""
{...field}
id="cta_text"
onChange={(e) => NullableStringOnChange(e, field.onChange)}
value={field.value || ""}
/>
</FormControl>

View file

@ -42,6 +42,7 @@ import {
import { Switch } from "~/components/ui/switch";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "~/components/ui/tabs";
import { filteredCaratteristiche } from "~/hooks/schedaAnnuncioUtils";
import { NullableStringOnChange } from "~/lib/form_utils";
import { cn } from "~/lib/utils";
import { useZodForm } from "~/lib/zodForm";
import { StatusBadge } from "~/pages/area-riservata/admin/edit-annuncio/[id]";
@ -69,7 +70,7 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
desc_en: z.string().nullable(),
desc_it: z.string().nullable(),
disponibile_da: z.date().nullable(),
email: z.email().optional(),
email: z.email().nullable(),
homepage: z.boolean().nullable(),
//BASE
id: zAnnuncioId,
@ -162,7 +163,6 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
const defaultValues: FormValues = {
...data,
mq: Number(data.mq) || null,
email: data.email || undefined,
};
z.config(z.locales[locale]());
@ -174,7 +174,7 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
function onSubmit(fields: FormValues) {
edit({
annuncioId: data.id,
data: { ...fields, email: fields.email || null },
data: fields,
});
}
@ -328,7 +328,13 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="titolo_it"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(
e,
field.onChange,
)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -354,7 +360,13 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="desc_it"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(
e,
field.onChange,
)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -390,7 +402,13 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="titolo_en"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(
e,
field.onChange,
)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -416,7 +434,13 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="desc_en"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(
e,
field.onChange,
)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -549,9 +573,9 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
{...field}
id="locatore"
onChange={(e) =>
field.onChange(e.target.value || null)
NullableStringOnChange(e, field.onChange)
}
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -573,15 +597,12 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
<Input
placeholder="esempio@email.com"
{...field}
autoComplete="off"
id="email"
onChange={(e) =>
field.onChange(
e.target.value && e.target.value !== ""
? e.target.value
: null,
)
NullableStringOnChange(e, field.onChange)
}
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -641,7 +662,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="indirizzo"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -664,7 +688,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="civico"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -689,7 +716,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="comune"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -712,7 +742,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="cap"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -737,7 +770,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="provincia"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -760,7 +796,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="regione"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -785,7 +824,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="lat"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -808,7 +850,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="lon"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -844,7 +889,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="indirizzo_secondario"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -869,7 +917,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="civico_secondario"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -896,7 +947,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="lat_secondario"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -921,7 +975,10 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
placeholder=""
{...field}
id="lon_secondario"
value={field.value || undefined}
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -988,13 +1045,13 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="categorie">Categorie</FormLabel>
<span className="font-medium text-sm leading-none">
Categorie
</span>
<FormMessage />
</div>
<p className="h-[42px]" id="categorie">
{field.value?.join(", ")}
</p>
<p className="h-[42px]">{field.value?.join(", ")}</p>
</FormItem>
)}
/>
@ -1235,11 +1292,9 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
{...field}
id="anno"
onChange={(e) =>
field.onChange(
e.target.value !== "" ? e.target.value : null,
)
NullableStringOnChange(e, field.onChange)
}
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -1262,11 +1317,9 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
{...field}
id="classe"
onChange={(e) =>
field.onChange(
e.target.value !== "" ? e.target.value : null,
)
NullableStringOnChange(e, field.onChange)
}
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -1322,11 +1375,9 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
{...field}
id="piano"
onChange={(e) =>
field.onChange(
e.target.value !== "" ? e.target.value : null,
)
NullableStringOnChange(e, field.onChange)
}
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -1748,14 +1799,14 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="accessori">Accessori</FormLabel>
<span className="font-medium text-sm leading-none">
Accessori
</span>
<FormMessage />
</div>
<FormControl>
<p className="h-[42px]" id="accessori">
{field.value?.join(", ")}
</p>
<p className="h-[42px]">{field.value?.join(", ")}</p>
</FormControl>
</FormItem>
)}
@ -1766,14 +1817,15 @@ export const AnnuncioEditForm = ({ data }: { data: AnnunciWithMedia }) => {
render={({ field }) => (
<FormItem>
<div className="flex flex-wrap items-center gap-x-2">
<FormLabel htmlFor="caratteristiche">
<span className="font-medium text-sm leading-none">
Caratteristiche
</FormLabel>
</span>
<FormMessage />
</div>
<FormControl>
<p className="h-[42px]" id="caratteristiche">
<p className="h-[42px]">
{field.value
? filteredCaratteristiche(field.value)
.map((v) => v.text)

View file

@ -86,7 +86,7 @@ export const FormEtichette = ({
placeholder=""
{...field}
id="value"
value={field.value || ""}
value={field.value}
/>
</FormControl>
</FormItem>

View file

@ -51,7 +51,10 @@ import {
parseDBComune,
parseDBNazione,
} from "~/lib/catasto";
import { checkFiscalCodeValidity } from "~/lib/form_utils";
import {
checkFiscalCodeValidity,
NullableStringOnChange,
} from "~/lib/form_utils";
import { cn } from "~/lib/utils";
import { useZodForm } from "~/lib/zodForm";
import { useCatasto } from "~/providers/CatastoProvider";
@ -1157,13 +1160,14 @@ export const FormNewServizioAcquisto = ({
<Input
{...field}
id="luogoNascita"
onChange={async (v) => {
field.onChange(v.target.value);
onChange={async (e) => {
NullableStringOnChange(e, field.onChange);
await form.trigger("luogo_nascita");
await form.trigger("codice_fiscale");
}}
type="text"
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -1409,8 +1413,9 @@ const AziendaSection = ({
<Input
{...field}
id="ragione_sociale"
onChange={(e) => NullableStringOnChange(e, field.onChange)}
type="text"
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -1431,8 +1436,9 @@ const AziendaSection = ({
<Input
{...field}
id="sede_legale"
onChange={(e) => NullableStringOnChange(e, field.onChange)}
type="text"
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -1459,8 +1465,9 @@ const AziendaSection = ({
<Input
{...field}
id="p_iva"
onChange={(e) => NullableStringOnChange(e, field.onChange)}
type="text"
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -1481,8 +1488,9 @@ const AziendaSection = ({
<Input
{...field}
id="legale_rappresentante"
onChange={(e) => NullableStringOnChange(e, field.onChange)}
type="text"
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -1551,8 +1559,9 @@ const FatturazioneSection = ({
<Input
{...field}
id="codice_destinatario"
onChange={(e) => NullableStringOnChange(e, field.onChange)}
type="text"
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>
@ -1680,8 +1689,11 @@ const ResidenzaSection = ({
<Input
{...field}
id="provinciaRecapiti"
onChange={(e) =>
NullableStringOnChange(e, field.onChange)
}
type="text"
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
)}
@ -1754,12 +1766,12 @@ const ResidenzaSection = ({
<Input
{...field}
id="citta_recapiti"
onChange={async (v) => {
field.onChange(v.target.value);
onChange={async (e) => {
NullableStringOnChange(e, field.onChange);
await trigger("citta_recapiti");
}}
type="text"
value={field.value || undefined}
value={field.value || ""}
/>
</FormControl>
</FormItem>

View file

@ -29,7 +29,10 @@ import {
parseDBComune,
parseDBNazione,
} from "~/lib/catasto";
import { checkFiscalCodeValidity } from "~/lib/form_utils";
import {
checkFiscalCodeValidity,
NullableStringOnChange,
} from "~/lib/form_utils";
import { cn } from "~/lib/utils";
import { useZodForm } from "~/lib/zodForm";
import { useCatasto } from "~/providers/CatastoProvider";
@ -397,8 +400,9 @@ export const ProfileFormAnagrafica = ({
<Input
{...field}
id="luogoNascita"
onChange={async (v) => {
field.onChange(v.target.value);
onChange={async (e) => {
NullableStringOnChange(e, field.onChange);
await form.trigger("luogo_nascita");
await form.trigger("codice_fiscale");
}}

View file

@ -1,10 +1,19 @@
import dynamic from "next/dynamic";
import type { ChangeEvent } from "react";
import type { z } from "zod/v4";
import type { ListOption } from "~/components/custom_ui/multiselect";
import type { Comuni } from "~/schemas/public/Comuni";
import type { Nazioni } from "~/schemas/public/Nazioni";
import { ITALY_CATASTO_CODE } from "./catasto";
export const NullableStringOnChange = (
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
// biome-ignore lint/suspicious/noExplicitAny: <intended>
fn: (...event: any[]) => void,
) => {
fn(e.target.value && e.target.value !== "" ? e.target.value : null);
};
export const FormDebug: React.ElementType =
process.env.NODE_ENV === "development"
? dynamic(