Next.js template
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CurrencyField.js 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import { ErrorMessage, useField } from 'formik';
  2. import PropTypes from 'prop-types';
  3. import React, { useEffect, useRef } from 'react';
  4. import CurrencyInput from 'react-currency-input-field';
  5. import { formatMoneyNumeral } from '../../../util/helpers/numeralHelpers';
  6. import {
  7. K_KEYCODE,
  8. MINUS_SYMBOL,
  9. NUMPAD_MINUS_SYMBOL,
  10. NUMPAD_PLUS_SYMBOL,
  11. PLUS_SYMBOL,
  12. } from '../../constants/keyCodeConstants';
  13. const CurrencyField = ({
  14. autoFocus,
  15. notCentered,
  16. notBold,
  17. label,
  18. onChange,
  19. value,
  20. ...props
  21. }) => {
  22. const [field, meta] = useField(props);
  23. const inputField = useRef(null);
  24. function styles() {
  25. let style = 'c-currency-field';
  26. if (meta.error && meta.touched) {
  27. style += ` c-currency-field--error`;
  28. }
  29. if (notCentered) {
  30. style += ` c-currency-field--not-centered`;
  31. }
  32. if (notBold) {
  33. style += ` c-currency-field--not-bold`;
  34. }
  35. return style;
  36. }
  37. useEffect(() => {
  38. if (autoFocus) {
  39. inputField.current.focus();
  40. }
  41. }, [autoFocus, inputField]);
  42. const onKeydownHandler = (event) => {
  43. if (
  44. event.keyCode === MINUS_SYMBOL ||
  45. event.keyCode === PLUS_SYMBOL ||
  46. event.keyCode === NUMPAD_MINUS_SYMBOL ||
  47. event.keyCode === NUMPAD_PLUS_SYMBOL ||
  48. event.keyCode === K_KEYCODE
  49. ) {
  50. event.preventDefault();
  51. }
  52. };
  53. const prefix = formatMoneyNumeral(0);
  54. const prefixSymbol = () => {
  55. if (prefix.includes('CAD')) {
  56. return 'CAD ';
  57. }
  58. return '$';
  59. };
  60. return (
  61. <div className={styles()}>
  62. {!!label && (
  63. <label className="c-currency-field__label" htmlFor={field.name}>
  64. {label}
  65. </label>
  66. )}
  67. {value ? (
  68. <CurrencyInput
  69. {...props}
  70. prefix={prefixSymbol()}
  71. onValueChange={(value) => {
  72. onChange(value ? Number(value) : '');
  73. }}
  74. onKeyDown={(event) => onKeydownHandler(event)}
  75. ref={inputField}
  76. defaultValue={0}
  77. value={value}
  78. />
  79. ) : (
  80. <CurrencyInput
  81. {...props}
  82. prefix={prefixSymbol()}
  83. onValueChange={(value) => {
  84. onChange(value ? Number(value) : '');
  85. }}
  86. onKeyDown={(event) => onKeydownHandler(event)}
  87. ref={inputField}
  88. />
  89. )}
  90. <ErrorMessage name={field.name}>
  91. {(errorMessage) => (
  92. <span className="c-currency-field__error">{errorMessage}</span>
  93. )}
  94. </ErrorMessage>
  95. </div>
  96. );
  97. };
  98. CurrencyField.propTypes = {
  99. field: PropTypes.shape({
  100. name: PropTypes.string,
  101. }),
  102. form: PropTypes.shape({}),
  103. label: PropTypes.oneOfType([PropTypes.string, PropTypes.shape({})]),
  104. disabled: PropTypes.bool,
  105. onChange: PropTypes.func,
  106. autoFocus: PropTypes.bool,
  107. notCentered: PropTypes.bool,
  108. notBold: PropTypes.bool,
  109. value: PropTypes.number,
  110. };
  111. export default CurrencyField;