// License: LGPL-3.0-or-later import * as React from "react"; import MuiTextField from '@material-ui/core/TextField'; import { fieldToTextField, TextFieldProps } from 'formik-material-ui'; import { Money } from "../../common/money"; import { useIntl } from "../intl"; import { useEffect, useRef } from "react"; import {useI18nCurrencyInput, Types} from '@houdiniproject/react-i18n-currency-input'; import '../../common/intl-polyfills/numberFormat'; export interface UseSerializeMoneyProps extends Omit<Types.UseI18nCurrencyInputProps, 'currency' | 'locale'|'value'> { value:Money; } /** * Hook for serializing a Money object to a string and back again. Particularly * useful for text fields. * * Example: * let money = new Money(100, 'usd') * let { serializedAmount, handleChange} = useSerializeMoney(money, (amount) => {money = amount}) * * // serializedAmount gets $1.00 as a string. handleChange receives the new serializedvalue after a change * @param inputAmount a Money object * @param setOutputAmount used for passing up output of the Hook */ export function useSerializeMoney(props:UseSerializeMoneyProps) : ReturnType<typeof useI18nCurrencyInput> { const intl = useIntl(); const {locale} = intl; const {value, ...other} = props; const {cents, currency} = value; const i18n = useI18nCurrencyInput({...other, locale, currency, value:cents, }); return {...i18n}; } export type IMoneyTextFieldProps = Omit<TextFieldProps,'value'> & Omit<Types.UseI18nCurrencyInputProps, 'currency' | 'locale'|'value'| 'inputRef'|'inputType'> & { value:Money }; /** * A text field which accepts a Money value, uses useI18nCurrencyInput and returns a Money value for various callbacks * * @param {IMoneyTextFieldProps} { children, form, field, currencyDisplay, useGrouping, allowEmpty, selectAllOnFocus, ...props } * @returns {JSX.Element} */ function MoneyTextField({ children, form, field, currencyDisplay, useGrouping, allowEmpty, selectAllOnFocus, ...props }:IMoneyTextFieldProps) : JSX.Element { const {name:fieldName, value} = field; const {setFieldValue} = form; const inputRef = useRef<HTMLInputElement>(); const {currency} = value; const { maskedValue, valueInCents, onChange, onFocus, onMouseUp, onSelect } = useSerializeMoney({ inputRef, value, currencyDisplay, useGrouping, allowEmpty, selectAllOnFocus}); useEffect(() => { setFieldValue(fieldName, Money.fromCents(valueInCents, currency)); }, [fieldName, valueInCents, currency, setFieldValue]); return <MuiTextField {...fieldToTextField({form, field, ...props})} value={maskedValue} onChange={onChange} onFocus={onFocus} onMouseUp={onMouseUp} onSelect={onSelect} inputRef={inputRef}> {children} </MuiTextField>; } export default MoneyTextField;