import React from 'react'; import ReactCurrencyInput, { CurrencyInputProps } from 'react-currency-input-field'; import classnames from 'classnames'; import { useField, useFormikContext } from 'formik'; import Feedback from './Feedback'; export type Props = { name: string; onValueChanged: (value: string | undefined) => void; id?: string; value?: string; placeholder?: string; disabled?: boolean; } & CurrencyInputProps; const CurrencyInput = ({ name, onValueChanged, id, value, placeholder, disabled, ...attributes }: Props) => { const { setFieldValue, setFieldTouched } = useFormikContext(); const [, metadata] = useField({ name, }); const classes = classnames( metadata.touched ? 'is-touched' : 'is-untouched', metadata.error ? 'av-invalid' : 'av-valid', metadata.touched && metadata.error && 'is-invalid', 'form-control' ); const formatDecimals = async (value: string | undefined): Promise => { setFieldTouched(name, true); if (value === '') { setFieldValue(name, undefined); if (onValueChanged) { onValueChanged(undefined); } return; } const noCommasValue = value?.replaceAll(',', ''); const number = Number(noCommasValue); const options = { minimumFractionDigits: 2, maximumFractionDigits: 2, }; // eslint-disable-next-line unicorn/prefer-string-replace-all const decimalValue = number.toLocaleString(undefined, options).replace(/,/g, ''); setFieldValue(name, decimalValue); if (onValueChanged) { onValueChanged(decimalValue); } }; return ( <> ) => { formatDecimals(event.target.value.replace('$', '')); }} onValueChange={onValueChanged} allowNegativeValue={false} transformRawValue={(rawValue: string) => { // This resolves an issue where entering decimals first will not format properly: https://github.com/cchanxzy/react-currency-input-field/issues/249 if (rawValue && rawValue.startsWith('.')) { return `0${rawValue}`; } return rawValue; }} {...attributes} /> ); }; export default CurrencyInput;