feat: enhance form components with autoComplete attributes and update ResidenzaSection to set cap_recapiti based on selected comune
This commit is contained in:
parent
7c49ca8f66
commit
48768c0481
4 changed files with 81 additions and 10 deletions
|
|
@ -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}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -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) => {
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue