diff --git a/src/components/Weight/forms/WeightForm.test.tsx b/src/components/Weight/forms/WeightForm.test.tsx index 0f5f49726..802eeb292 100644 --- a/src/components/Weight/forms/WeightForm.test.tsx +++ b/src/components/Weight/forms/WeightForm.test.tsx @@ -84,8 +84,8 @@ describe("Test WeightForm component", () => { const submitButton = screen.getByRole('button', { name: 'submit' }); // Act - user.type(dateInput, '2022-02-28'); - user.type(weightInput, '80'); + await user.type(dateInput, '2022-02-28'); + await user.type(weightInput, '80'); // Assert expect(dateInput).toBeInTheDocument(); @@ -97,4 +97,21 @@ describe("Test WeightForm component", () => { }); }); + test('Creating a new weight entry using a comma decimal separator', async () => { + + // Arrange + const user = userEvent.setup(); + render( + + + + ); + + const weightInput = await screen.findByLabelText('weight'); + + // Act + await user.type(weightInput, "69,1"); + await user.tab(); + expect(screen.queryByText(/weight must be a `number` type/i)).not.toBeInTheDocument(); + }); }); diff --git a/src/components/Weight/forms/WeightForm.tsx b/src/components/Weight/forms/WeightForm.tsx index 26ad3964b..24ae56d6b 100644 --- a/src/components/Weight/forms/WeightForm.tsx +++ b/src/components/Weight/forms/WeightForm.tsx @@ -15,6 +15,13 @@ interface WeightFormProps { closeFn?: () => void, } +const parseLocaleNumber = (numString: string | number) => { + if (typeof(numString) === 'string'){ + return Number(numString.replace(/,/, '.')); + } + return numString; +}; + export const WeightForm = ({ weightEntry, closeFn }: WeightFormProps) => { const weightEntriesQuery = useBodyWeightQuery(); @@ -27,6 +34,9 @@ export const WeightForm = ({ weightEntry, closeFn }: WeightFormProps) => { const validationSchema = yup.object({ weight: yup .number() + .transform((_, value) => { + return parseLocaleNumber(value); + }) .min(30, 'Min weight is 30 kg') .max(300, 'Max weight is 300 kg') .required('Weight field is required'), @@ -45,15 +55,17 @@ export const WeightForm = ({ weightEntry, closeFn }: WeightFormProps) => { validationSchema={validationSchema} onSubmit={async (values) => { + const normalizedWeight = parseLocaleNumber(values.weight); + // Edit existing weight entry if (weightEntry) { - weightEntry.weight = values.weight; + weightEntry.weight = normalizedWeight; weightEntry.date = values.date; editWeightQuery.mutate(weightEntry); // Create a new weight entry } else { - weightEntry = new WeightEntry(values.date, values.weight); + weightEntry = new WeightEntry(values.date, normalizedWeight); addWeightQuery.mutate(weightEntry); } diff --git a/src/components/Weight/widgets/Table/index.tsx b/src/components/Weight/widgets/Table/index.tsx index 4c011df01..f88659c73 100644 --- a/src/components/Weight/widgets/Table/index.tsx +++ b/src/components/Weight/widgets/Table/index.tsx @@ -39,6 +39,10 @@ const buildRows = (weights: WeightEntry[]): GridRowsProp => days: +row.days.toFixed(1), })); +const parseLocaleNumber = (numString: string) => { + return Number(numString.replace(/,/, '.')); +}; + export const WeightTable = ({ weights }: WeightTableProps) => { const [t] = useTranslation(); const rows = buildRows(weights); @@ -73,7 +77,8 @@ export const WeightTable = ({ weights }: WeightTableProps) => { const processRowUpdate = (newRow: GridRowModel) => { const date = newRow.date instanceof Date ? newRow.date : new Date(newRow.date); - editEntryQuery.mutate(new WeightEntry(date, Number(newRow.weight), Number(newRow.id))); + const sanitizedWeight = parseLocaleNumber(newRow.weight); + editEntryQuery.mutate(new WeightEntry(date, sanitizedWeight, Number(newRow.id))); return newRow; }; @@ -98,9 +103,17 @@ export const WeightTable = ({ weights }: WeightTableProps) => { { field: 'weight', headerName: t('weight'), - type: 'number', + type: 'string', width: 100, editable: true, + headerAlign: 'right', + align: 'right', + valueFormatter: (value?: string) => { + if (typeof(value) === 'string'){ + return parseLocaleNumber(value); + } + return value; + }, }, { field: 'change',