feat: enhance form components with autoComplete attributes and update ResidenzaSection to set cap_recapiti based on selected comune

This commit is contained in:
Marco Pedone 2026-03-20 18:40:48 +01:00
parent 7c49ca8f66
commit 48768c0481
4 changed files with 81 additions and 10 deletions

View file

@ -1,12 +1,29 @@
import { useVirtualizer } from "@tanstack/react-virtual"; import { useVirtualizer } from "@tanstack/react-virtual";
import { type JSX, useRef, useState } from "react"; import {
type HTMLInputAutoCompleteAttribute,
type JSX,
useRef,
useState,
} from "react";
import ReactSelect, { import ReactSelect, {
type CSSObjectWithLabel, type CSSObjectWithLabel,
components,
type GroupBase, type GroupBase,
type InputProps,
type MenuListProps, type MenuListProps,
} from "react-select"; } from "react-select";
import type {} from "react-select/base";
import { cn } from "~/lib/utils"; import { cn } from "~/lib/utils";
declare module "react-select/base" {
export interface Props<
Option,
IsMulti extends boolean,
Group extends GroupBase<Option>,
> {
autoComplete?: HTMLInputAutoCompleteAttribute;
}
}
export type ListOption = { export type ListOption = {
label: string; label: string;
value: string; value: string;
@ -20,6 +37,7 @@ type BaseProps = {
disabled?: boolean; disabled?: boolean;
menuPlacement?: "auto" | "bottom" | "top"; menuPlacement?: "auto" | "bottom" | "top";
defaultValue?: ListOption | ListOption[]; defaultValue?: ListOption | ListOption[];
autoComplete?: HTMLInputAutoCompleteAttribute;
}; };
type MultiProps = { type MultiProps = {
@ -94,6 +112,18 @@ const VirtualizedMenuList = (
); );
}; };
const CustomInput = (
props: InputProps<ListOption, boolean, GroupBase<ListOption>>,
) => {
return (
<components.Input
{...props}
// This pulls the value from the main ReactSelect wrapper
autoComplete={props.selectProps.autoComplete}
/>
);
};
/** /**
* *
* @example * @example
@ -124,11 +154,13 @@ export const MultiSelect = ({
placeholder, placeholder,
disabled, disabled,
menuPlacement, menuPlacement,
autoComplete,
}: MultiSelectProps) => { }: MultiSelectProps) => {
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
return ( return (
<ReactSelect <ReactSelect
autoComplete={autoComplete}
classNamePrefix="select" classNamePrefix="select"
classNames={{ classNames={{
control: () => control: () =>
@ -161,7 +193,10 @@ export const MultiSelect = ({
singleValue: () => cn("text-primary font-medium"), singleValue: () => cn("text-primary font-medium"),
valueContainer: () => cn("min-h-[36px]"), valueContainer: () => cn("min-h-[36px]"),
}} }}
components={{ MenuList: VirtualizedMenuList }} components={{
MenuList: VirtualizedMenuList,
Input: CustomInput,
}}
defaultValue={defaultValue} defaultValue={defaultValue}
inputId={elementId} inputId={elementId}
instanceId={elementId} instanceId={elementId}

View file

@ -104,7 +104,12 @@ export const ProfileFormAccount = ({
</div> </div>
<FormControl> <FormControl>
<Input placeholder="" {...field} id="nome" /> <Input
placeholder=""
{...field}
autoComplete="off"
id="nome"
/>
</FormControl> </FormControl>
</FormItem> </FormItem>
)} )}
@ -124,7 +129,12 @@ export const ProfileFormAccount = ({
</div> </div>
<FormControl> <FormControl>
<Input placeholder="" {...field} id="cognome" /> <Input
placeholder=""
{...field}
autoComplete="off"
id="cognome"
/>
</FormControl> </FormControl>
</FormItem> </FormItem>
)} )}
@ -145,6 +155,7 @@ export const ProfileFormAccount = ({
<FormControl> <FormControl>
<Input <Input
autoComplete="off"
placeholder="esempio@email.com" placeholder="esempio@email.com"
{...field} {...field}
id="email" id="email"
@ -168,7 +179,7 @@ export const ProfileFormAccount = ({
</div> </div>
<FormControl> <FormControl>
<PhoneInput {...field} id="telefono" /> <PhoneInput {...field} autoComplete="off" id="telefono" />
</FormControl> </FormControl>
</FormItem> </FormItem>
)} )}
@ -188,6 +199,7 @@ export const ProfileFormAccount = ({
className="data-[state=checked]:bg-neutral-700" className="data-[state=checked]:bg-neutral-700"
defaultChecked={field.value} defaultChecked={field.value}
id="isAdmin" id="isAdmin"
name="isAdmin"
onCheckedChange={(v) => { onCheckedChange={(v) => {
field.onChange(v); field.onChange(v);
}} }}

View file

@ -571,7 +571,7 @@ const ResidenzaSection = ({
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">
<FormLabel htmlFor="select-comune"> <FormLabel htmlFor="select-comune-residenza">
{t.recapiti.comune} {t.recapiti.comune}
</FormLabel> </FormLabel>
<FormMessage /> <FormMessage />
@ -587,7 +587,7 @@ const ResidenzaSection = ({
} }
: undefined : undefined
} }
elementId="select-comune" elementId="select-comune-residenza"
elementName="comune_residenza" elementName="comune_residenza"
isMulti={false} isMulti={false}
onValueChange={async (value) => { onValueChange={async (value) => {

View file

@ -867,7 +867,12 @@ export const FormServizioAcquisto = ({
</div> </div>
<FormControl> <FormControl>
<Input {...field} id="nome" type="text" /> <Input
{...field}
autoComplete="name"
id="nome"
type="text"
/>
</FormControl> </FormControl>
</FormItem> </FormItem>
)} )}
@ -885,7 +890,12 @@ export const FormServizioAcquisto = ({
</div> </div>
<FormControl> <FormControl>
<Input {...field} id="cognome" type="text" /> <Input
{...field}
autoComplete="family-name"
id="cognome"
type="text"
/>
</FormControl> </FormControl>
</FormItem> </FormItem>
)} )}
@ -1368,6 +1378,7 @@ const ResidenzaSection = ({
<FormControl> <FormControl>
<Input <Input
{...field} {...field}
autoComplete=""
id="provinciaRecapiti" id="provinciaRecapiti"
onChange={(e) => onChange={(e) =>
NullableStringOnChange(e, field.onChange) NullableStringOnChange(e, field.onChange)
@ -1426,6 +1437,12 @@ const ResidenzaSection = ({
onValueChange={async (value) => { onValueChange={async (value) => {
field.onChange(value.value); field.onChange(value.value);
await trigger("citta_recapiti"); await trigger("citta_recapiti");
const selectedComune = comuni.find(
(c) => c.catasto === value.value,
);
if (selectedComune?.cap) {
setValue("cap_recapiti", selectedComune.cap);
}
}} }}
options={options} options={options}
placeholder="Seleziona..." placeholder="Seleziona..."
@ -1445,6 +1462,7 @@ const ResidenzaSection = ({
<FormControl> <FormControl>
<Input <Input
{...field} {...field}
autoComplete=""
id="citta_recapiti" id="citta_recapiti"
onChange={async (e) => { onChange={async (e) => {
NullableStringOnChange(e, field.onChange); NullableStringOnChange(e, field.onChange);
@ -1469,7 +1487,13 @@ const ResidenzaSection = ({
<FormMessage /> <FormMessage />
</div> </div>
<FormControl> <FormControl>
<Input {...field} id="cap" placeholder="00100" type="text" /> <Input
{...field}
autoComplete="postal-code"
id="cap"
placeholder="00100"
type="text"
/>
</FormControl> </FormControl>
</FormItem> </FormItem>
)} )}