import { useCallback, useEffect, useState } from "react" import { Control, Controller, ControllerRenderProps, useWatch, } from "react-hook-form" import CurrencyInput, { CurrencyInputProps, formatValue, } from "react-currency-input-field" import { currencies, CurrencyInfo } from "../../../../../lib/data/currencies" import { TieredPriceControls } from "./tiered-price-controls" import { DataGridCellContainer } from "../../../../../components/data-grid/components/data-grid-cell-container" import { useDataGridCell, useDataGridCellError, } from "../../../../../components/data-grid/hooks" import { DataGridCellProps, InputProps, } from "../../../../../components/data-grid/types" import { useCombinedRefs } from "../../../../../hooks/use-combined-refs" export interface TieredPriceCellProps< TData, TValue = any, > extends DataGridCellProps { code: string onOpenModal: (field: string, currency: CurrencyInfo) => void getTieredFieldName: (field: string) => string } export const TieredPriceCell = ({ context, code, onOpenModal, getTieredFieldName, }: TieredPriceCellProps) => { const [symbolWidth, setSymbolWidth] = useState(0) const measuredRef = useCallback((node: HTMLSpanElement) => { if (node) { const width = node.offsetWidth setSymbolWidth(width) } }, []) const { field, control, renderProps } = useDataGridCell({ context, }) const errorProps = useDataGridCellError({ context }) const { container, input } = renderProps const { isAnchor } = container const currency = currencies[code.toUpperCase()] return ( { return ( } > ) }} /> ) } const OuterComponent = ({ isAnchor, field, control, symbolWidth, currency, onOpenModal, getTieredFieldName, }: { isAnchor: boolean field: string control: Control symbolWidth: number currency: CurrencyInfo onOpenModal: (field: string, currency: CurrencyInfo) => void getTieredFieldName: (field: string) => string }) => { const tieredFieldName = getTieredFieldName(field) const tiers = useWatch({ control, name: tieredFieldName }) return ( 0} isAnchor={isAnchor} symbolWidth={symbolWidth} onOpenModal={() => onOpenModal(field, currency)} /> ) } const Inner = ({ field, onMeasureSymbol, inputProps, currencyInfo, }: { field: ControllerRenderProps onMeasureSymbol: (node: HTMLSpanElement) => void inputProps: InputProps currencyInfo: CurrencyInfo }) => { const { value, onChange: _, onBlur, ref, ...rest } = field const { ref: inputRef, onBlur: onInputBlur, onFocus, onChange, ...attributes } = inputProps const formatter = useCallback( (value?: string | number) => { const ensuredValue = typeof value === "number" ? value.toString() : value || "" return formatValue({ value: ensuredValue, decimalScale: currencyInfo.decimal_digits, disableGroupSeparators: true, decimalSeparator: ".", }) }, [currencyInfo] ) const [localValue, setLocalValue] = useState(value || "") const handleValueChange: CurrencyInputProps["onValueChange"] = ( value, _name, _values ) => { if (!value) { setLocalValue("") return } setLocalValue(value) } useEffect(() => { let update = value if (!isNaN(Number(value))) { update = formatter(update) } setLocalValue(update) }, [value, formatter]) const combinedRef = useCombinedRefs(inputRef, ref) return (
{currencyInfo.symbol_native} { onBlur() onInputBlur() onChange(localValue, value) }} onFocus={onFocus} decimalScale={currencyInfo.decimal_digits} decimalsLimit={currencyInfo.decimal_digits} autoComplete="off" tabIndex={-1} />
) }