import { cn } from "@/lib/utils"; import { FormControl, FormDescription, FormItem, InputProps } from "@/ui"; import { Quantity, QuantityObject } from "@shared/contexts"; import { createElement, forwardRef, useState } from "react"; import { Controller, FieldPath, FieldValues, UseControllerProps, useFormContext, } from "react-hook-form"; import { FormErrorMessage } from "./FormErrorMessage"; import { FormLabel, FormLabelProps } from "./FormLabel"; import { FormInputProps, FormInputWithIconProps } from "./FormProps"; export type FormQuantityFieldProps< TFieldValues extends FieldValues = FieldValues, TName extends FieldPath = FieldPath > = { button?: (props?: React.PropsWithChildren) => React.ReactNode; defaultValue?: any; } & InputProps & FormInputProps & Partial & FormInputWithIconProps & UseControllerProps; export const FormQuantityField = forwardRef< HTMLDivElement, React.HTMLAttributes & FormQuantityFieldProps >((props, ref) => { const { name, label, hint, placeholder, description, required, className, leadIcon, trailIcon, button, defaultValue, } = props; const { control } = useFormContext(); const [precision, setPrecision] = useState(Quantity.DEFAULT_PRECISION); const transform = { input: (value: QuantityObject) => { const quantityOrError = Quantity.create(value); if (quantityOrError.isFailure) { throw quantityOrError.error; } const quantityValue = quantityOrError.object; setPrecision(quantityValue.getPrecision()); return quantityValue.toString(); }, output: (event: React.ChangeEvent): QuantityObject => { const value = parseFloat(event.target.value); const output = !isNaN(value) ? value : 0; const quantityOrError = Quantity.create({ amount: output * Math.pow(10, precision), precision, }); if (quantityOrError.isFailure) { throw quantityOrError.error; } return quantityOrError.object.toObject(); }, }; return ( { return ( field.onChange(transform.output(e))} value={transform.input(field.value)} /> ); return ( {label && }
{leadIcon && (
{createElement( leadIcon, { className: "h-5 w-5 text-muted-foreground", "aria-hidden": true, }, null )}
)} field.onChange(transform.output(e))} value={transform.input(field.value)} /> {trailIcon && (
{createElement( trailIcon, { className: "h-5 w-5 text-muted-foreground", "aria-hidden": true, }, null )}
)}
{button && <>{createElement(button)}}
{description && {description}}
); }} /> ); });