fix: respect number format in currency input (#18469)
Fixed #18355 Currency fields ignored the workspace number format when editing: display showed e.g. 5 982,77 € (French style) but the input forced US style (5,982.77) and rejected comma as decimal. Fix: CurrencyInput now uses useNumberFormat() and passes the correct thousandsSeparator and radix to the IMask input so edit mode matches the chosen format (comma/space, dot/comma, etc.). Files: CurrencyInput.tsx (use format for mask), new CurrencyInput.test.tsx . --------- Co-authored-by: root <root@dragon.second> Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
+2
-1
@@ -54,7 +54,8 @@ export const CurrencyFieldInput = () => {
|
||||
amountText: string;
|
||||
currencyCode: string;
|
||||
}) => {
|
||||
const amount = parseFloat(amountText);
|
||||
const normalizedAmountText = amountText.replace(',', '.');
|
||||
const amount = parseFloat(normalizedAmountText);
|
||||
|
||||
const newCurrencyValue = {
|
||||
amountMicros: isNaN(amount)
|
||||
|
||||
@@ -3,12 +3,14 @@ import { styled } from '@linaria/react';
|
||||
import { useContext, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { useRegisterInputEvents } from '@/object-record/record-field/ui/meta-types/input/hooks/useRegisterInputEvents';
|
||||
import { useNumberFormat } from '@/localization/hooks/useNumberFormat';
|
||||
import { CURRENCIES } from '@/settings/data-model/constants/Currencies';
|
||||
import { CurrencyPickerDropdownButton } from '@/ui/input/components/internal/currency/components/CurrencyPickerDropdownButton';
|
||||
import { type Currency } from '@/ui/input/components/internal/types/Currency';
|
||||
import { IMaskInput } from 'react-imask';
|
||||
import { type IconComponent } from 'twenty-ui/display';
|
||||
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
import { getSeparatorsForNumberFormat } from '~/utils/format/getSeparatorsForNumberFormat';
|
||||
|
||||
export const StyledIMaskInput = styled.div`
|
||||
display: contents;
|
||||
@@ -87,9 +89,13 @@ export const CurrencyInput = ({
|
||||
}: CurrencyInputProps) => {
|
||||
const { theme } = useContext(ThemeContext);
|
||||
const [internalText, setInternalText] = useState(value);
|
||||
const { numberFormat } = useNumberFormat();
|
||||
|
||||
const wrapperRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const { thousandsSeparator, radix } =
|
||||
getSeparatorsForNumberFormat(numberFormat);
|
||||
|
||||
const handleChange = (value: string) => {
|
||||
setInternalText(value);
|
||||
onChange?.(value);
|
||||
@@ -132,8 +138,8 @@ export const CurrencyInput = ({
|
||||
<StyledIMaskInput>
|
||||
<IMaskInput
|
||||
mask={Number}
|
||||
thousandsSeparator=","
|
||||
radix="."
|
||||
thousandsSeparator={thousandsSeparator}
|
||||
radix={radix}
|
||||
scale={decimals}
|
||||
onAccept={(value: string) => handleChange(value)}
|
||||
inputRef={wrapperRef}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { NumberFormat } from '@/localization/constants/NumberFormat';
|
||||
import {
|
||||
getSeparatorsForNumberFormat,
|
||||
type NumberFormatSeparators,
|
||||
} from '~/utils/format/getSeparatorsForNumberFormat';
|
||||
|
||||
const expectSeparators = (
|
||||
format: NumberFormat,
|
||||
expected: NumberFormatSeparators,
|
||||
) => {
|
||||
expect(getSeparatorsForNumberFormat(format)).toEqual(expected);
|
||||
};
|
||||
|
||||
describe('getSeparatorsForNumberFormat', () => {
|
||||
it('returns comma thousands and dot radix for COMMAS_AND_DOT', () => {
|
||||
expectSeparators(NumberFormat.COMMAS_AND_DOT, {
|
||||
thousandsSeparator: ',',
|
||||
radix: '.',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns space thousands and comma radix for SPACES_AND_COMMA', () => {
|
||||
expectSeparators(NumberFormat.SPACES_AND_COMMA, {
|
||||
thousandsSeparator: ' ',
|
||||
radix: ',',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns dot thousands and comma radix for DOTS_AND_COMMA', () => {
|
||||
expectSeparators(NumberFormat.DOTS_AND_COMMA, {
|
||||
thousandsSeparator: '.',
|
||||
radix: ',',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns apostrophe thousands and dot radix for APOSTROPHE_AND_DOT', () => {
|
||||
expectSeparators(NumberFormat.APOSTROPHE_AND_DOT, {
|
||||
thousandsSeparator: "'",
|
||||
radix: '.',
|
||||
});
|
||||
});
|
||||
|
||||
it('falls back to COMMAS_AND_DOT separators for SYSTEM', () => {
|
||||
expectSeparators(NumberFormat.SYSTEM, {
|
||||
thousandsSeparator: ',',
|
||||
radix: '.',
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { NumberFormat } from '@/localization/constants/NumberFormat';
|
||||
|
||||
export type NumberFormatSeparators = {
|
||||
thousandsSeparator: string;
|
||||
radix: string;
|
||||
};
|
||||
|
||||
export const getSeparatorsForNumberFormat = (
|
||||
format: NumberFormat,
|
||||
): NumberFormatSeparators => {
|
||||
switch (format) {
|
||||
case NumberFormat.SPACES_AND_COMMA:
|
||||
return {
|
||||
thousandsSeparator: ' ',
|
||||
radix: ',',
|
||||
};
|
||||
case NumberFormat.DOTS_AND_COMMA:
|
||||
return {
|
||||
thousandsSeparator: '.',
|
||||
radix: ',',
|
||||
};
|
||||
case NumberFormat.APOSTROPHE_AND_DOT:
|
||||
return {
|
||||
thousandsSeparator: "'",
|
||||
radix: '.',
|
||||
};
|
||||
case NumberFormat.SYSTEM:
|
||||
case NumberFormat.COMMAS_AND_DOT:
|
||||
default:
|
||||
return {
|
||||
thousandsSeparator: ',',
|
||||
radix: '.',
|
||||
};
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user