Presupuestador_web/client/src/components/Forms/FormQuantityField.tsx
2024-07-11 13:08:53 +02:00

117 lines
3.5 KiB
TypeScript

import * as React from "react";
import { cn } from "@/lib/utils";
import { FormControl, FormDescription, FormField, FormItem, Input, InputProps } from "@/ui";
import { Quantity } from "@shared/contexts";
import { cva, type VariantProps } from "class-variance-authority";
import { FieldPath, FieldValues, UseControllerProps, useFormContext } from "react-hook-form";
import { FormErrorMessage } from "./FormErrorMessage";
import { FormLabel, FormLabelProps } from "./FormLabel";
import { FormInputProps, FormInputWithIconProps } from "./FormProps";
const formQuantityFieldVariants = cva(
"text-right [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",
{
variants: {
variant: {
default: "",
outline:
"border-0 focus-visible:border focus-visible:border-input focus-visible:ring-0 focus-visible:ring-offset-0 ",
},
},
defaultVariants: {
variant: "default",
},
}
);
export type FormQuantityFieldProps<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
> = {
button?: (props?: React.PropsWithChildren) => React.ReactNode;
defaultValue?: any;
} & InputProps &
FormInputProps &
Partial<FormLabelProps> &
FormInputWithIconProps &
UseControllerProps<TFieldValues, TName> &
VariantProps<typeof formQuantityFieldVariants> & {
precision: number;
};
export const FormQuantityField = React.forwardRef<HTMLInputElement, FormQuantityFieldProps>(
(props, ref) => {
const {
name,
label,
hint,
description,
placeholder,
className,
disabled,
defaultValue,
rules,
precision,
variant,
} = props;
const { control } = useFormContext();
const transformToInput = (value: any) => {
if (typeof value !== "object") {
return value;
}
const quantityOrError = Quantity.create(value);
if (quantityOrError.isFailure) {
throw quantityOrError.error;
}
return (
quantityOrError.object
.toNumber()
//.toPrecision(precision ?? value.precision)
.toString()
);
};
return (
<FormField
defaultValue={defaultValue}
control={control}
name={name}
disabled={disabled}
rules={rules}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
render={({ field }) => {
return (
<FormItem ref={ref} className={cn(className, "space-y-3")}>
{label && <FormLabel label={label} hint={hint} required={rules?.required ?? false} />}
<FormControl>
<Input
type='number'
name={field.name}
//ref={field.ref} <-- no activar que hace cosas raras
onBlur={field.onBlur}
disabled={field.disabled}
className={cn(formQuantityFieldVariants({ variant, className }))}
placeholder={placeholder}
value={transformToInput(field.value)}
onChange={(value) => {
// "value" ya viene con los "0" de la precisión
console.log(value);
field.onChange(value ?? "");
}}
/>
</FormControl>
{description && <FormDescription>{description}</FormDescription>}
<FormErrorMessage />
</FormItem>
);
}}
/>
);
}
);