From 147775413fd3cc00d1f845a9427fad43054fff00 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 21 Mar 2024 09:20:19 +0100 Subject: [PATCH 1/7] fix ValuePage autofocus --- src/pages/workspace/taxes/ValuePage.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pages/workspace/taxes/ValuePage.tsx b/src/pages/workspace/taxes/ValuePage.tsx index d008b11ecb15..f97ae1e58e45 100644 --- a/src/pages/workspace/taxes/ValuePage.tsx +++ b/src/pages/workspace/taxes/ValuePage.tsx @@ -7,6 +7,7 @@ import type {FormOnyxValues} from '@components/Form/types'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; +import useAutoFocusInput from '@hooks/useAutoFocusInput'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import {updatePolicyTaxValue, validateTaxValue} from '@libs/actions/TaxRate'; @@ -37,6 +38,7 @@ function ValuePage({ const {translate} = useLocalize(); const currentTaxRate = PolicyUtils.getTaxByID(policy, taxID); const [value, setValue] = useState(currentTaxRate?.value?.replace('%', '')); + const {inputCallbackRef} = useAutoFocusInput(); const goBack = useCallback(() => Navigation.goBack(ROUTES.WORKSPACE_TAX_EDIT.getRoute(policyID ?? '', taxID)), [policyID, taxID]); @@ -89,6 +91,7 @@ function ValuePage({ onInputChange={setValue} hideCurrencySymbol extraSymbol={%} + ref={inputCallbackRef} /> From 3e7c3f6add2f1f4aeebe2c6891ded29e19472a2f Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 21 Mar 2024 09:31:50 +0100 Subject: [PATCH 2/7] extra decimals --- src/pages/workspace/taxes/ValuePage.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/workspace/taxes/ValuePage.tsx b/src/pages/workspace/taxes/ValuePage.tsx index f97ae1e58e45..9e092e4a7c76 100644 --- a/src/pages/workspace/taxes/ValuePage.tsx +++ b/src/pages/workspace/taxes/ValuePage.tsx @@ -90,6 +90,8 @@ function ValuePage({ defaultValue={value} onInputChange={setValue} hideCurrencySymbol + // The default currency uses 2 decimal places, and we add 6 extra decimal places for the percentage + extraDecimals={6} extraSymbol={%} ref={inputCallbackRef} /> From a00e4f2d6876d15ca9e61dbfb24f8f27387e2957 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Thu, 21 Mar 2024 09:36:38 +0100 Subject: [PATCH 3/7] extra decimals 2 --- src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx b/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx index ccc0d4ad9e7b..6473150de467 100644 --- a/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx +++ b/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx @@ -106,6 +106,7 @@ function WorkspaceCreateTaxPage({ description={translate('workspace.taxes.value')} rightLabel={translate('common.required')} hideCurrencySymbol + extraDecimals={6} extraSymbol={%} /> From 925b03a65fc145e0f324051d7621b472d06f0023 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Mon, 25 Mar 2024 11:47:39 +0100 Subject: [PATCH 4/7] update accroding to the new API --- src/libs/API/parameters/UpdatePolicyTaxValueParams.ts | 3 ++- src/libs/actions/TaxRate.ts | 2 +- src/pages/workspace/taxes/ValuePage.tsx | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/API/parameters/UpdatePolicyTaxValueParams.ts b/src/libs/API/parameters/UpdatePolicyTaxValueParams.ts index 1124755ea9ef..63fd1a1e85d9 100644 --- a/src/libs/API/parameters/UpdatePolicyTaxValueParams.ts +++ b/src/libs/API/parameters/UpdatePolicyTaxValueParams.ts @@ -1,7 +1,8 @@ type UpdatePolicyTaxValueParams = { policyID: string; taxCode: string; - taxAmount: number; + // String in the format: "1.1234%" + taxRate: string; }; export default UpdatePolicyTaxValueParams; diff --git a/src/libs/actions/TaxRate.ts b/src/libs/actions/TaxRate.ts index 3f2420c76f87..115c6543a216 100644 --- a/src/libs/actions/TaxRate.ts +++ b/src/libs/actions/TaxRate.ts @@ -380,7 +380,7 @@ function updatePolicyTaxValue(policyID: string, taxID: string, taxValue: number) const parameters = { policyID, taxCode: taxID, - taxAmount: Number(taxValue), + taxRate: stringTaxValue, } satisfies UpdatePolicyTaxValueParams; API.write(WRITE_COMMANDS.UPDATE_POLICY_TAX_VALUE, parameters, onyxData); diff --git a/src/pages/workspace/taxes/ValuePage.tsx b/src/pages/workspace/taxes/ValuePage.tsx index 62074e04e6c8..38da26e8d6de 100644 --- a/src/pages/workspace/taxes/ValuePage.tsx +++ b/src/pages/workspace/taxes/ValuePage.tsx @@ -39,7 +39,6 @@ function ValuePage({ const {inputCallbackRef} = useAutoFocusInput(); const currentTaxRate = PolicyUtils.getTaxByID(policy, taxID); const [value, setValue] = useState(currentTaxRate?.value?.replace('%', '')); - const {inputCallbackRef} = useAutoFocusInput(); const goBack = useCallback(() => Navigation.goBack(ROUTES.WORKSPACE_TAX_EDIT.getRoute(policyID ?? '', taxID)), [policyID, taxID]); From d8ded94c831002e813ef27d6ab04fd8adffeca71 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Mon, 25 Mar 2024 12:27:55 +0100 Subject: [PATCH 5/7] add 16 decimal places support --- src/CONST.ts | 2 ++ src/components/AmountForm.tsx | 11 +++++++---- src/libs/MoneyRequestUtils.ts | 4 ++-- src/libs/actions/TaxRate.ts | 2 +- src/pages/workspace/taxes/ValuePage.tsx | 15 ++++++++------- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index d13c3b374f5a..7a9f73f564f9 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -4149,6 +4149,8 @@ const CONST = { }, }, }, + + MAX_TAX_RATE_DECIMAL_PLACES: 16, } as const; type Country = keyof typeof CONST.ALL_COUNTRIES; diff --git a/src/components/AmountForm.tsx b/src/components/AmountForm.tsx index 48035dd884bd..e947c74f7c60 100644 --- a/src/components/AmountForm.tsx +++ b/src/components/AmountForm.tsx @@ -37,6 +37,9 @@ type AmountFormProps = { /** Whether the currency symbol is pressable */ isCurrencyPressable?: boolean; + + /** Custom max amount length. It defaults to CONST.IOU.AMOUNT_MAX_LENGTH */ + amountMaxLength?: number; } & Pick & Pick; @@ -53,7 +56,7 @@ const NUM_PAD_CONTAINER_VIEW_ID = 'numPadContainerView'; const NUM_PAD_VIEW_ID = 'numPadView'; function AmountForm( - {value: amount, currency = CONST.CURRENCY.USD, extraDecimals = 0, errorText, onInputChange, onCurrencyButtonPress, isCurrencyPressable = true, ...rest}: AmountFormProps, + {value: amount, currency = CONST.CURRENCY.USD, extraDecimals = 0, amountMaxLength, errorText, onInputChange, onCurrencyButtonPress, isCurrencyPressable = true, ...rest}: AmountFormProps, forwardedRef: ForwardedRef, ) { const styles = useThemeStyles(); @@ -101,7 +104,7 @@ function AmountForm( const newAmountWithoutSpaces = MoneyRequestUtils.stripSpacesFromAmount(newAmount); // Use a shallow copy of selection to trigger setSelection // More info: https://github.com/Expensify/App/issues/16385 - if (!MoneyRequestUtils.validateAmount(newAmountWithoutSpaces, decimals)) { + if (!MoneyRequestUtils.validateAmount(newAmountWithoutSpaces, decimals, amountMaxLength)) { setSelection((prevSelection) => ({...prevSelection})); return; } @@ -111,13 +114,13 @@ function AmountForm( setSelection((prevSelection) => getNewSelection(prevSelection, isForwardDelete ? strippedAmount.length : currentAmount.length, strippedAmount.length)); onInputChange?.(strippedAmount); }, - [currentAmount, decimals, onInputChange], + [amountMaxLength, currentAmount, decimals, onInputChange], ); // Modifies the amount to match the decimals for changed currency. useEffect(() => { // If the changed currency supports decimals, we can return - if (MoneyRequestUtils.validateAmount(currentAmount, decimals)) { + if (MoneyRequestUtils.validateAmount(currentAmount, decimals, amountMaxLength)) { return; } diff --git a/src/libs/MoneyRequestUtils.ts b/src/libs/MoneyRequestUtils.ts index da8a5b843ec1..d3969558dab9 100644 --- a/src/libs/MoneyRequestUtils.ts +++ b/src/libs/MoneyRequestUtils.ts @@ -49,13 +49,13 @@ function calculateAmountLength(amount: string, decimals: number): number { /** * Check if amount is a decimal up to 3 digits */ -function validateAmount(amount: string, decimals: number): boolean { +function validateAmount(amount: string, decimals: number, amountMaxLength: number = CONST.IOU.AMOUNT_MAX_LENGTH): boolean { const regexString = decimals === 0 ? `^\\d+(,\\d*)*$` // Don't allow decimal point if decimals === 0 : `^\\d+(,\\d*)*(\\.\\d{0,${decimals}})?$`; // Allow the decimal point and the desired number of digits after the point const decimalNumberRegex = new RegExp(regexString, 'i'); - return amount === '' || (decimalNumberRegex.test(amount) && calculateAmountLength(amount, decimals) <= CONST.IOU.AMOUNT_MAX_LENGTH); + return amount === '' || (decimalNumberRegex.test(amount) && calculateAmountLength(amount, decimals) <= amountMaxLength); } /** diff --git a/src/libs/actions/TaxRate.ts b/src/libs/actions/TaxRate.ts index 115c6543a216..8ee20b9fed11 100644 --- a/src/libs/actions/TaxRate.ts +++ b/src/libs/actions/TaxRate.ts @@ -322,7 +322,7 @@ function deletePolicyTaxes(policyID: string, taxesToDelete: string[]) { API.write(WRITE_COMMANDS.DELETE_POLICY_TAXES, parameters, onyxData); } -function updatePolicyTaxValue(policyID: string, taxID: string, taxValue: number) { +function updatePolicyTaxValue(policyID: string, taxID: string, taxValue: string) { const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]; const originalTaxRate = {...policy?.taxRates?.taxes[taxID]}; const stringTaxValue = `${taxValue}%`; diff --git a/src/pages/workspace/taxes/ValuePage.tsx b/src/pages/workspace/taxes/ValuePage.tsx index 38da26e8d6de..02972a6dbb38 100644 --- a/src/pages/workspace/taxes/ValuePage.tsx +++ b/src/pages/workspace/taxes/ValuePage.tsx @@ -1,5 +1,5 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import React, {useCallback, useState} from 'react'; +import React, {useCallback} from 'react'; import AmountForm from '@components/AmountForm'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; @@ -38,13 +38,13 @@ function ValuePage({ const {translate} = useLocalize(); const {inputCallbackRef} = useAutoFocusInput(); const currentTaxRate = PolicyUtils.getTaxByID(policy, taxID); - const [value, setValue] = useState(currentTaxRate?.value?.replace('%', '')); + const defaultValue = currentTaxRate?.value?.replace('%', ''); const goBack = useCallback(() => Navigation.goBack(ROUTES.WORKSPACE_TAX_EDIT.getRoute(policyID ?? '', taxID)), [policyID, taxID]); const submit = useCallback( (values: FormOnyxValues) => { - updatePolicyTaxValue(policyID, taxID, Number(values.value)); + updatePolicyTaxValue(policyID, taxID, values.value); goBack(); }, [goBack, policyID, taxID], @@ -87,11 +87,12 @@ function ValuePage({ %} ref={inputCallbackRef} /> From c5c1413b685188c0f168d75ee91e8ad3c2999605 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Mon, 25 Mar 2024 12:34:01 +0100 Subject: [PATCH 6/7] decimals support for creating new taxes --- src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx b/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx index 6473150de467..9d7c1a400870 100644 --- a/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx +++ b/src/pages/workspace/taxes/WorkspaceCreateTaxPage.tsx @@ -106,7 +106,10 @@ function WorkspaceCreateTaxPage({ description={translate('workspace.taxes.value')} rightLabel={translate('common.required')} hideCurrencySymbol - extraDecimals={6} + // The default currency uses 2 decimal places, so we substract it + extraDecimals={CONST.MAX_TAX_RATE_DECIMAL_PLACES - 2} + // We increase the amount max length. We have to add 2 places for one digit and comma. + amountMaxLength={CONST.MAX_TAX_RATE_DECIMAL_PLACES + 2} extraSymbol={%} /> From 56d745ea709bf00e71d96c36c5f5ae4032db3326 Mon Sep 17 00:00:00 2001 From: Jakub Kosmydel <104823336+kosmydel@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:59:01 +0100 Subject: [PATCH 7/7] 4 decimal places --- src/CONST.ts | 2 +- src/libs/actions/TaxRate.ts | 2 +- src/pages/workspace/taxes/ValuePage.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 7a9f73f564f9..d109b9f76456 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -4150,7 +4150,7 @@ const CONST = { }, }, - MAX_TAX_RATE_DECIMAL_PLACES: 16, + MAX_TAX_RATE_DECIMAL_PLACES: 4, } as const; type Country = keyof typeof CONST.ALL_COUNTRIES; diff --git a/src/libs/actions/TaxRate.ts b/src/libs/actions/TaxRate.ts index 8ee20b9fed11..115c6543a216 100644 --- a/src/libs/actions/TaxRate.ts +++ b/src/libs/actions/TaxRate.ts @@ -322,7 +322,7 @@ function deletePolicyTaxes(policyID: string, taxesToDelete: string[]) { API.write(WRITE_COMMANDS.DELETE_POLICY_TAXES, parameters, onyxData); } -function updatePolicyTaxValue(policyID: string, taxID: string, taxValue: string) { +function updatePolicyTaxValue(policyID: string, taxID: string, taxValue: number) { const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${policyID}`]; const originalTaxRate = {...policy?.taxRates?.taxes[taxID]}; const stringTaxValue = `${taxValue}%`; diff --git a/src/pages/workspace/taxes/ValuePage.tsx b/src/pages/workspace/taxes/ValuePage.tsx index 02972a6dbb38..4ec932fbcc14 100644 --- a/src/pages/workspace/taxes/ValuePage.tsx +++ b/src/pages/workspace/taxes/ValuePage.tsx @@ -44,7 +44,7 @@ function ValuePage({ const submit = useCallback( (values: FormOnyxValues) => { - updatePolicyTaxValue(policyID, taxID, values.value); + updatePolicyTaxValue(policyID, taxID, Number(values.value)); goBack(); }, [goBack, policyID, taxID],