Refactor formularios para eliminar el uso de register en favor de name en los campos de formulario, mejorando la legibilidad y simplificando la gestión de formularios.
This commit is contained in:
parent
3eb0396cbd
commit
6a79ea2299
@ -66,7 +66,7 @@ const calculateQuoteTotals = (prices: any) => {
|
||||
};
|
||||
|
||||
export const QuotePricesResume = ({ currency }: { currency: CurrencyData }) => {
|
||||
const { register, formState, control } = useFormContext();
|
||||
const { formState, control } = useFormContext();
|
||||
const { formatNumber } = useLocalization();
|
||||
|
||||
const pricesWatch = useWatch({ control, name: ["subtotal_price", "discount", "tax"] });
|
||||
@ -105,9 +105,7 @@ export const QuotePricesResume = ({ currency }: { currency: CurrencyData }) => {
|
||||
scale={2}
|
||||
disabled={formState.disabled}
|
||||
placeholder={t("quotes.form_fields.discount.placeholder")}
|
||||
{...register("discount", {
|
||||
required: false,
|
||||
})}
|
||||
name='discount'
|
||||
onChange={(value) => {
|
||||
console.log("discount", value);
|
||||
}}
|
||||
@ -134,9 +132,7 @@ export const QuotePricesResume = ({ currency }: { currency: CurrencyData }) => {
|
||||
scale={2}
|
||||
disabled={formState.disabled}
|
||||
placeholder={t("quotes.form_fields.tax.placeholder")}
|
||||
{...register("tax", {
|
||||
required: false,
|
||||
})}
|
||||
name='tax'
|
||||
/>
|
||||
</div>
|
||||
<div className='grid gap-1 font-semibold text-muted-foreground'>
|
||||
|
||||
@ -31,7 +31,7 @@ export const QuoteDetailsCardEditor = ({
|
||||
defaultValues: Readonly<{ [x: string]: any }> | undefined;
|
||||
}) => {
|
||||
const { toast } = useToast();
|
||||
const { control, register } = useFormContext();
|
||||
const { control } = useFormContext();
|
||||
|
||||
const [pickerMode] = useState<"dialog" | "panel">("dialog");
|
||||
|
||||
@ -65,7 +65,7 @@ export const QuoteDetailsCardEditor = ({
|
||||
<FormTextAreaField
|
||||
readOnly={original?.id_article}
|
||||
autoSize
|
||||
{...register(`items.${index}.id_article`)}
|
||||
name={`items.${index}.id_article`}
|
||||
/>
|
||||
);
|
||||
},
|
||||
@ -80,7 +80,7 @@ export const QuoteDetailsCardEditor = ({
|
||||
<FormTextAreaField
|
||||
readOnly={original?.id_article}
|
||||
autoSize
|
||||
{...register(`items.${index}.description`)}
|
||||
name={`items.${index}.description`}
|
||||
/>
|
||||
);
|
||||
},
|
||||
@ -98,7 +98,7 @@ export const QuoteDetailsCardEditor = ({
|
||||
<FormQuantityField
|
||||
scale={0}
|
||||
className='text-right'
|
||||
{...register(`items.${index}.quantity`)}
|
||||
name={`items.${index}.quantity`}
|
||||
/>
|
||||
);
|
||||
},
|
||||
@ -117,7 +117,7 @@ export const QuoteDetailsCardEditor = ({
|
||||
language={language}
|
||||
scale={2}
|
||||
className='text-right'
|
||||
{...register(`items.${index}.unit_price`)}
|
||||
name={`items.${index}.unit_price`}
|
||||
/>
|
||||
);
|
||||
},
|
||||
@ -138,7 +138,7 @@ export const QuoteDetailsCardEditor = ({
|
||||
scale={2}
|
||||
readOnly
|
||||
className='text-right'
|
||||
{...register(`items.${index}.subtotal_price`)}
|
||||
name={`items.${index}.subtotal_price`}
|
||||
/>
|
||||
);
|
||||
},
|
||||
@ -155,7 +155,7 @@ export const QuoteDetailsCardEditor = ({
|
||||
<FormPercentageField
|
||||
scale={2}
|
||||
className='text-right'
|
||||
{...register(`items.${index}.discount`)}
|
||||
name={`items.${index}.discount`}
|
||||
/>
|
||||
);
|
||||
},
|
||||
@ -176,7 +176,7 @@ export const QuoteDetailsCardEditor = ({
|
||||
scale={2}
|
||||
readOnly
|
||||
className='font-semibold text-right'
|
||||
{...register(`items.${index}.total_price`)}
|
||||
name={`items.${index}.total_price`}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
@ -4,7 +4,7 @@ import { t } from "i18next";
|
||||
import { useFormContext } from "react-hook-form";
|
||||
|
||||
export const QuoteGeneralCardEditor = () => {
|
||||
const { register, formState } = useFormContext();
|
||||
const { formState } = useFormContext();
|
||||
|
||||
return (
|
||||
<div className='grid gap-6 md:grid-cols-6'>
|
||||
@ -21,7 +21,7 @@ export const QuoteGeneralCardEditor = () => {
|
||||
description={t("quotes.form_fields.customer_reference.desc")}
|
||||
disabled={formState.disabled}
|
||||
placeholder={t("quotes.form_fields.customer_reference.placeholder")}
|
||||
{...register("customer_reference")}
|
||||
name='customer_reference'
|
||||
/>
|
||||
|
||||
<FormDatePickerField
|
||||
@ -30,18 +30,14 @@ export const QuoteGeneralCardEditor = () => {
|
||||
description={t("quotes.form_fields.date.desc")}
|
||||
disabled={formState.disabled}
|
||||
placeholder={t("quotes.form_fields.date.placeholder")}
|
||||
{...register("date", {
|
||||
required: true,
|
||||
})}
|
||||
name='date'
|
||||
/>
|
||||
<FormTextField
|
||||
label={t("quotes.form_fields.validity.label")}
|
||||
description={t("quotes.form_fields.validity.desc")}
|
||||
disabled={formState.disabled}
|
||||
placeholder={t("quotes.form_fields.validity.placeholder")}
|
||||
{...register("validity", {
|
||||
required: false,
|
||||
})}
|
||||
name='validity'
|
||||
/>
|
||||
<FormTextAreaField
|
||||
className='col-span-2'
|
||||
@ -49,9 +45,7 @@ export const QuoteGeneralCardEditor = () => {
|
||||
description={t("quotes.form_fields.payment_method.desc")}
|
||||
disabled={formState.disabled}
|
||||
placeholder={t("quotes.form_fields.payment_method.placeholder")}
|
||||
{...register("payment_method", {
|
||||
required: false,
|
||||
})}
|
||||
name='payment_method'
|
||||
/>
|
||||
</div>
|
||||
<div className='grid grid-cols-6 gap-6'>
|
||||
@ -62,9 +56,7 @@ export const QuoteGeneralCardEditor = () => {
|
||||
description={t("quotes.form_fields.customer_information.desc")}
|
||||
disabled={formState.disabled}
|
||||
placeholder={t("quotes.form_fields.customer_information.placeholder")}
|
||||
{...register("customer_information", {
|
||||
required: true,
|
||||
})}
|
||||
name='customer_information'
|
||||
errors={formState.errors}
|
||||
/>
|
||||
|
||||
@ -74,9 +66,7 @@ export const QuoteGeneralCardEditor = () => {
|
||||
description={t("quotes.form_fields.notes.desc")}
|
||||
disabled={formState.disabled}
|
||||
placeholder={t("quotes.form_fields.notes.placeholder")}
|
||||
{...register("notes", {
|
||||
required: false,
|
||||
})}
|
||||
name='notes'
|
||||
/>
|
||||
</div>
|
||||
</FormGroup>
|
||||
@ -105,9 +95,7 @@ export const QuoteGeneralCardEditor = () => {
|
||||
description={t("quotes.form_fields.lang_code.desc")}
|
||||
//disabled={formState.disabled}
|
||||
placeholder={t("quotes.form_fields.lang_code.placeholder")}
|
||||
{...register("lang_code", {
|
||||
required: true,
|
||||
})}
|
||||
name='lang_code'
|
||||
/>
|
||||
<FormTextField
|
||||
required
|
||||
@ -115,9 +103,7 @@ export const QuoteGeneralCardEditor = () => {
|
||||
description={t("quotes.form_fields.currency_code.desc")}
|
||||
//disabled={formState.disabled}
|
||||
placeholder={t("quotes.form_fields.currency_code.placeholder")}
|
||||
{...register("currency_code", {
|
||||
required: true,
|
||||
})}
|
||||
name='currency_code'
|
||||
/>
|
||||
</div>
|
||||
</FormGroup>
|
||||
|
||||
@ -43,8 +43,7 @@ export type FormCurrencyFieldProps<
|
||||
scale: number;
|
||||
};
|
||||
|
||||
export const FormCurrencyField = React.forwardRef<HTMLInputElement, FormCurrencyFieldProps>(
|
||||
(props /*ref*/) => {
|
||||
export const FormCurrencyField = (props: FormCurrencyFieldProps) => {
|
||||
const {
|
||||
name,
|
||||
label,
|
||||
@ -156,7 +155,6 @@ export const FormCurrencyField = React.forwardRef<HTMLInputElement, FormCurrency
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
FormCurrencyField.displayName = "FormCurrencyField";
|
||||
|
||||
@ -42,10 +42,7 @@ export type FormPercentageFieldProps<
|
||||
scale: number;
|
||||
};
|
||||
|
||||
export const FormPercentageField = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement> & FormPercentageFieldProps
|
||||
>((props /*ref*/) => {
|
||||
export const FormPercentageField = (props: FormPercentageFieldProps) => {
|
||||
const {
|
||||
name,
|
||||
label,
|
||||
@ -144,4 +141,4 @@ export const FormPercentageField = React.forwardRef<
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
@ -41,8 +41,7 @@ export type FormQuantityFieldProps<
|
||||
scale: number;
|
||||
};
|
||||
|
||||
export const FormQuantityField = React.forwardRef<HTMLInputElement, FormQuantityFieldProps>(
|
||||
(props /*ref*/) => {
|
||||
export const FormQuantityField = (props: FormQuantityFieldProps) => {
|
||||
const {
|
||||
name,
|
||||
label,
|
||||
@ -140,5 +139,4 @@ export const FormQuantityField = React.forwardRef<HTMLInputElement, FormQuantity
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@ -46,11 +46,7 @@ export type FormTextAreaFieldProps<
|
||||
errors?: FieldErrors<TFieldValues>;
|
||||
} & VariantProps<typeof formTextAreaFieldVariants>;
|
||||
|
||||
export const FormTextAreaField = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.TextareaHTMLAttributes<HTMLTextAreaElement> & FormTextAreaFieldProps
|
||||
>(
|
||||
({
|
||||
export const FormTextAreaField = ({
|
||||
name,
|
||||
label,
|
||||
hint,
|
||||
@ -64,11 +60,9 @@ export const FormTextAreaField = React.forwardRef<
|
||||
variant,
|
||||
|
||||
...props
|
||||
}) =>
|
||||
/*ref*/
|
||||
{
|
||||
const { control } = useFormContext();
|
||||
return (
|
||||
}: React.TextareaHTMLAttributes<HTMLTextAreaElement> & FormTextAreaFieldProps) => {
|
||||
const { control } = useFormContext();
|
||||
return (
|
||||
<FormField
|
||||
control={control}
|
||||
name={name}
|
||||
@ -108,6 +102,5 @@ export const FormTextAreaField = React.forwardRef<
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
@ -33,8 +33,7 @@ export type FormTextFieldProps<
|
||||
UseControllerProps<TFieldValues, TName> &
|
||||
VariantProps<typeof formTextFieldVariants>;
|
||||
|
||||
export const FormTextField = React.forwardRef<HTMLInputElement, FormTextFieldProps>(
|
||||
(props /*ref*/) => {
|
||||
export const FormTextField = (props: FormTextFieldProps) => {
|
||||
const {
|
||||
name,
|
||||
label,
|
||||
@ -87,5 +86,4 @@ export const FormTextField = React.forwardRef<HTMLInputElement, FormTextFieldPro
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { act, useEffect, useRef } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { FormProvider, UseFormReturn, useForm } from "react-hook-form";
|
||||
import { FormTextField } from "@/components/Forms/FormTextField";
|
||||
import { FormField } from "./form";
|
||||
|
||||
type TestFormValues = {
|
||||
items: Array<{ quantity: string }>;
|
||||
title: string;
|
||||
};
|
||||
|
||||
declare global {
|
||||
@ -41,6 +43,7 @@ const FormHarness = ({ name, onMount, onFormReady }: FormHarnessProps) => {
|
||||
const form = useForm<TestFormValues>({
|
||||
defaultValues: {
|
||||
items: [{ quantity: "1" }, { quantity: "2" }],
|
||||
title: "before",
|
||||
},
|
||||
});
|
||||
|
||||
@ -55,6 +58,25 @@ const FormHarness = ({ name, onMount, onFormReady }: FormHarnessProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const ControlledTextFieldHarness = ({ onFormReady }: Pick<FormHarnessProps, "onFormReady">) => {
|
||||
const form = useForm<TestFormValues>({
|
||||
defaultValues: {
|
||||
items: [],
|
||||
title: "before",
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
onFormReady(form);
|
||||
}, [form, onFormReady]);
|
||||
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<FormTextField name='title' />
|
||||
</FormProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe("FormField", () => {
|
||||
let container: HTMLDivElement;
|
||||
let root: ReturnType<typeof createRoot>;
|
||||
@ -98,4 +120,23 @@ describe("FormField", () => {
|
||||
expect((container.querySelector("input[aria-label='quantity']") as HTMLInputElement).value).toBe("5");
|
||||
expect(form?.getValues("items.1.quantity")).toBe("5");
|
||||
});
|
||||
|
||||
it("updates React Hook Form through a Controller without an external register spread", () => {
|
||||
let form: UseFormReturn<TestFormValues> | undefined;
|
||||
|
||||
act(() => {
|
||||
root.render(<ControlledTextFieldHarness onFormReady={(value) => (form = value)} />);
|
||||
});
|
||||
|
||||
const input = container.querySelector("input[name='title']") as HTMLInputElement;
|
||||
const valueSetter = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set;
|
||||
|
||||
act(() => {
|
||||
valueSetter?.call(input, "after");
|
||||
input.dispatchEvent(new Event("input", { bubbles: true }));
|
||||
});
|
||||
|
||||
expect(input.value).toBe("after");
|
||||
expect(form?.getValues("title")).toBe("after");
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user