From 356432f177187b6dc74e8fceb60d13d8b49e7910 Mon Sep 17 00:00:00 2001 From: Rafa Gares Date: Fri, 12 Jul 2024 15:10:36 +0200 Subject: [PATCH 1/3] feat: add `belowMin` and `aboveMax` error keys to `NumberField` --- .changeset/thirty-bikes-kneel.md | 6 ++++ .../components/fields/number-field/README.md | 2 ++ .../number-field/docs/additional-info.md | 2 ++ .../fields/number-field/src/messages.ts | 14 ++++++++ .../number-field/src/number-field.spec.js | 30 ++++++++++++++++- .../number-field/src/number-field.story.js | 7 +++- .../fields/number-field/src/number-field.tsx | 33 ++++++++++++++++++- packages/i18n/data/core.json | 8 +++++ 8 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 .changeset/thirty-bikes-kneel.md create mode 100644 packages/components/fields/number-field/src/messages.ts diff --git a/.changeset/thirty-bikes-kneel.md b/.changeset/thirty-bikes-kneel.md new file mode 100644 index 0000000000..b041169ab2 --- /dev/null +++ b/.changeset/thirty-bikes-kneel.md @@ -0,0 +1,6 @@ +--- +'@commercetools-uikit/number-field': minor +'@commercetools-uikit/i18n': minor +--- + +Add `belowMin` and `aboveMax` error keys to `NumberField` diff --git a/packages/components/fields/number-field/README.md b/packages/components/fields/number-field/README.md index 9165a1e47a..bc8937bb36 100644 --- a/packages/components/fields/number-field/README.md +++ b/packages/components/fields/number-field/README.md @@ -116,6 +116,8 @@ When the `key` is known, and when the value is truthy, and when `renderError` re Known error keys are: - `missing`: tells the user that this field is required +- `belowMin`: tells the user that the value is below the minimum +- `aboveMax`: tells the user that the value is above the maximum ## Static methods diff --git a/packages/components/fields/number-field/docs/additional-info.md b/packages/components/fields/number-field/docs/additional-info.md index e9fd413577..203246af9c 100644 --- a/packages/components/fields/number-field/docs/additional-info.md +++ b/packages/components/fields/number-field/docs/additional-info.md @@ -17,6 +17,8 @@ When the `key` is known, and when the value is truthy, and when `renderError` re Known error keys are: - `missing`: tells the user that this field is required +- `belowMin`: tells the user that the value is below the minimum +- `aboveMax`: tells the user that the value is above the maximum ## Static methods diff --git a/packages/components/fields/number-field/src/messages.ts b/packages/components/fields/number-field/src/messages.ts new file mode 100644 index 0000000000..0da1992c47 --- /dev/null +++ b/packages/components/fields/number-field/src/messages.ts @@ -0,0 +1,14 @@ +import { defineMessages } from 'react-intl'; + +export default defineMessages({ + belowMinError: { + id: 'UIKit.NumberField.belowMinError', + description: 'An error message to show when the value is below the minimum', + defaultMessage: 'Value must be greater than or equal to {min}.', + }, + aboveMaxError: { + id: 'UIKit.NumberField.aboveMaxError', + description: 'An error message to show when the value is above the maximum', + defaultMessage: 'Value must be less than or equal to {max}.', + }, +}); diff --git a/packages/components/fields/number-field/src/number-field.spec.js b/packages/components/fields/number-field/src/number-field.spec.js index 5e7a7ddd41..f1f52a5f99 100644 --- a/packages/components/fields/number-field/src/number-field.spec.js +++ b/packages/components/fields/number-field/src/number-field.spec.js @@ -14,7 +14,7 @@ class Story extends Component { static displayName = 'Story'; static propTypes = { onChange: PropTypes.func.isRequired, - value: PropTypes.string, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), id: PropTypes.string, }; static defaultProps = { @@ -212,6 +212,34 @@ describe('when field is touched and has errors', () => { expect(getByText(/field is required/i)).toBeInTheDocument(); }); }); + describe('when value is below min', () => { + it('should render a default error', () => { + const min = 2; + const { getByText } = renderNumberField({ + value: 1, + min, + touched: true, + errors: { belowMin: true }, + }); + expect( + getByText(`Value must be greater than or equal to ${min}.`) + ).toBeInTheDocument(); + }); + }); + describe('when value is above max', () => { + it('should render a default error', () => { + const max = 2; + const { getByText } = renderNumberField({ + value: 3, + max, + touched: true, + errors: { aboveMax: true }, + }); + expect( + getByText(`Value must be less than or equal to ${max}.`) + ).toBeInTheDocument(); + }); + }); describe('when there is a custom error', () => { it('should render the custom error message', () => { const { getByText } = renderNumberField({ diff --git a/packages/components/fields/number-field/src/number-field.story.js b/packages/components/fields/number-field/src/number-field.story.js index 0903cd2e2f..876f05f1b1 100644 --- a/packages/components/fields/number-field/src/number-field.story.js +++ b/packages/components/fields/number-field/src/number-field.story.js @@ -53,7 +53,12 @@ storiesOf('Components|Fields', module) warnings={object('warnings', { customWarning: true, })} - errors={object('errors', { missing: true, customError: true })} + errors={object('errors', { + missing: true, + belowMin: true, + aboveMax: true, + customError: true, + })} renderError={(key) => { switch (key) { case 'customError': diff --git a/packages/components/fields/number-field/src/number-field.tsx b/packages/components/fields/number-field/src/number-field.tsx index 433977b902..7da6299c80 100644 --- a/packages/components/fields/number-field/src/number-field.tsx +++ b/packages/components/fields/number-field/src/number-field.tsx @@ -20,6 +20,8 @@ import FieldLabel from '@commercetools-uikit/field-label'; import FieldErrors from '@commercetools-uikit/field-errors'; import FieldWarnings from '@commercetools-uikit/field-warnings'; import NumberInput from '@commercetools-uikit/number-input'; +import messages from './messages'; +import { FormattedMessage } from 'react-intl'; const sequentialId = createSequentialId('number-field-'); const sequentialErrorsId = createSequentialId('number-field-error-')(); @@ -278,7 +280,36 @@ class NumberField extends Component { id={sequentialErrorsId} errors={this.props.errors} isVisible={hasError} - renderError={this.props.renderError} + renderError={(key: string, error?: boolean) => { + const element = this.props.renderError?.(key, error); + if (element) { + return element; + } else { + switch (key) { + case 'belowMin': + if (typeof this.props.min === 'number') { + return ( + + ); + } + break; + case 'aboveMax': + if (typeof this.props.max === 'number') { + return ( + + ); + } + break; + } + return null; + } + }} /> Date: Mon, 22 Jul 2024 17:15:30 +0200 Subject: [PATCH 2/3] fix: improve code readability --- .../fields/number-field/src/number-field.tsx | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/packages/components/fields/number-field/src/number-field.tsx b/packages/components/fields/number-field/src/number-field.tsx index 7da6299c80..51e7907b00 100644 --- a/packages/components/fields/number-field/src/number-field.tsx +++ b/packages/components/fields/number-field/src/number-field.tsx @@ -222,6 +222,33 @@ class NumberField extends Component { return errors as TCustomFormErrors; } + renderError(key?: string): ReactNode | null { + switch (key) { + case 'belowMin': + if (typeof this.props.min === 'number') { + return ( + + ); + } + break; + case 'aboveMax': + if (typeof this.props.max === 'number') { + return ( + + ); + } + break; + } + + return null; + } + render() { if (!this.props.isReadOnly) { warning( @@ -280,36 +307,10 @@ class NumberField extends Component { id={sequentialErrorsId} errors={this.props.errors} isVisible={hasError} - renderError={(key: string, error?: boolean) => { - const element = this.props.renderError?.(key, error); - if (element) { - return element; - } else { - switch (key) { - case 'belowMin': - if (typeof this.props.min === 'number') { - return ( - - ); - } - break; - case 'aboveMax': - if (typeof this.props.max === 'number') { - return ( - - ); - } - break; - } - return null; - } - }} + renderError={(key: string, error?: boolean) => + // Custom errors take precedence over the default errors + this.props.renderError?.(key, error) ?? this.renderError(key) + } /> Date: Mon, 22 Jul 2024 17:28:45 +0200 Subject: [PATCH 3/3] refactor: widen or operator --- packages/components/fields/number-field/src/number-field.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/components/fields/number-field/src/number-field.tsx b/packages/components/fields/number-field/src/number-field.tsx index 51e7907b00..9900faa1a9 100644 --- a/packages/components/fields/number-field/src/number-field.tsx +++ b/packages/components/fields/number-field/src/number-field.tsx @@ -309,7 +309,7 @@ class NumberField extends Component { isVisible={hasError} renderError={(key: string, error?: boolean) => // Custom errors take precedence over the default errors - this.props.renderError?.(key, error) ?? this.renderError(key) + this.props.renderError?.(key, error) || this.renderError(key) } />