Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fixed 4 decimals for distance rates #49773

Merged
merged 3 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/components/AmountForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ type AmountFormProps = {

/** Whether the form should use a standard TextInput as a base */
displayAsTextInput?: boolean;

/** Number of decimals to display */
fixedDecimals?: number;
} & Pick<TextInputWithCurrencySymbolProps, 'hideCurrencySymbol' | 'extraSymbol'> &
Pick<BaseTextInputProps, 'autoFocus'>;

Expand Down Expand Up @@ -75,6 +78,7 @@ function AmountForm(
displayAsTextInput = false,
isCurrencyPressable = true,
label,
fixedDecimals,
...rest
}: AmountFormProps,
forwardedRef: ForwardedRef<BaseTextInputRef>,
Expand All @@ -84,7 +88,7 @@ function AmountForm(

const textInput = useRef<BaseTextInputRef | null>(null);

const decimals = CurrencyUtils.getCurrencyDecimals(currency) + extraDecimals;
const decimals = fixedDecimals ?? CurrencyUtils.getCurrencyDecimals(currency) + extraDecimals;
daledah marked this conversation as resolved.
Show resolved Hide resolved
const currentAmount = useMemo(() => (typeof amount === 'string' ? amount : ''), [amount]);

const [shouldUpdateSelection, setShouldUpdateSelection] = useState(true);
Expand Down
2 changes: 1 addition & 1 deletion src/libs/CurrencyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ function convertAmountToDisplayString(amount = 0, currency: string = CONST.CURRE
return NumberFormatUtils.format(BaseLocaleListener.getPreferredLocale(), convertedAmount, {
style: 'currency',
currency,
minimumFractionDigits: getCurrencyDecimals(currency) + 1,
minimumFractionDigits: 4,
daledah marked this conversation as resolved.
Show resolved Hide resolved
});
}

Expand Down
3 changes: 1 addition & 2 deletions src/libs/PolicyDistanceRatesUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type {FormInputErrors, FormOnyxValues} from '@components/Form/types';
import CONST from '@src/CONST';
import type ONYXKEYS from '@src/ONYXKEYS';
import type {Rate} from '@src/types/onyx/Policy';
import * as CurrencyUtils from './CurrencyUtils';
import getPermittedDecimalSeparator from './getPermittedDecimalSeparator';
import * as Localize from './Localize';
import * as MoneyRequestUtils from './MoneyRequestUtils';
Expand All @@ -18,7 +17,7 @@ function validateRateValue(values: FormOnyxValues<RateValueForm>, currency: stri
const decimalSeparator = toLocaleDigit('.');

// Allow one more decimal place for accuracy
const rateValueRegex = RegExp(String.raw`^-?\d{0,8}([${getPermittedDecimalSeparator(decimalSeparator)}]\d{0,${CurrencyUtils.getCurrencyDecimals(currency) + 1}})?$`, 'i');
const rateValueRegex = RegExp(String.raw`^-?\d{0,8}([${getPermittedDecimalSeparator(decimalSeparator)}]\d{0,4})?$`, 'i');
daledah marked this conversation as resolved.
Show resolved Hide resolved
if (!rateValueRegex.test(parsedRate) || parsedRate === '') {
errors.rate = Localize.translateLocal('common.error.invalidRateError');
} else if (NumberUtils.parseFloatAnyLocale(parsedRate) <= 0) {
Expand Down
21 changes: 6 additions & 15 deletions src/pages/workspace/distanceRates/CreateDistanceRatePage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type {StackScreenProps} from '@react-navigation/stack';
import React, {useCallback} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import AmountForm from '@components/AmountForm';
import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
import FormProvider from '@components/Form/FormProvider';
Expand All @@ -12,6 +10,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import usePolicy from '@hooks/usePolicy';
import useThemeStyles from '@hooks/useThemeStyles';
import {getOptimisticRateName, validateRateValue} from '@libs/PolicyDistanceRatesUtils';
import Navigation from '@navigation/Navigation';
Expand All @@ -24,18 +23,14 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type SCREENS from '@src/SCREENS';
import INPUT_IDS from '@src/types/form/PolicyCreateDistanceRateForm';
import type {Rate} from '@src/types/onyx/Policy';
import type Policy from '@src/types/onyx/Policy';

type CreateDistanceRatePageOnyxProps = {
policy: OnyxEntry<Policy>;
};
type CreateDistanceRatePageProps = StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.CREATE_DISTANCE_RATE>;

type CreateDistanceRatePageProps = CreateDistanceRatePageOnyxProps & StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.CREATE_DISTANCE_RATE>;

function CreateDistanceRatePage({policy, route}: CreateDistanceRatePageProps) {
function CreateDistanceRatePage({route}: CreateDistanceRatePageProps) {
const styles = useThemeStyles();
const {translate, toLocaleDigit} = useLocalize();
const policyID = route.params.policyID;
const policy = usePolicy(policyID);
const currency = policy?.outputCurrency ?? CONST.CURRENCY.USD;
const customUnits = policy?.customUnits ?? {};
const customUnitID = customUnits[Object.keys(customUnits)[0]]?.customUnitID ?? '';
Expand Down Expand Up @@ -90,7 +85,7 @@ function CreateDistanceRatePage({policy, route}: CreateDistanceRatePageProps) {
<InputWrapperWithRef
InputComponent={AmountForm}
inputID={INPUT_IDS.RATE}
extraDecimals={1}
fixedDecimals={4}
daledah marked this conversation as resolved.
Show resolved Hide resolved
isCurrencyPressable={false}
currency={currency}
ref={inputCallbackRef}
Expand All @@ -104,8 +99,4 @@ function CreateDistanceRatePage({policy, route}: CreateDistanceRatePageProps) {

CreateDistanceRatePage.displayName = 'CreateDistanceRatePage';

export default withOnyx<CreateDistanceRatePageProps, CreateDistanceRatePageOnyxProps>({
policy: {
key: ({route}) => `${ONYXKEYS.COLLECTION.POLICY}${route.params.policyID}`,
},
})(CreateDistanceRatePage);
export default CreateDistanceRatePage;
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type {StackScreenProps} from '@react-navigation/stack';
import React, {useCallback} from 'react';
import {Keyboard} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import AmountForm from '@components/AmountForm';
import FormProvider from '@components/Form/FormProvider';
import InputWrapperWithRef from '@components/Form/InputWrapper';
Expand All @@ -11,6 +9,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton';
import ScreenWrapper from '@components/ScreenWrapper';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import usePolicy from '@hooks/usePolicy';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import {validateRateValue} from '@libs/PolicyDistanceRatesUtils';
Expand All @@ -22,27 +21,23 @@ import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type SCREENS from '@src/SCREENS';
import INPUT_IDS from '@src/types/form/PolicyDistanceRateEditForm';
import type * as OnyxTypes from '@src/types/onyx';

type PolicyDistanceRateEditPageOnyxProps = {
/** Policy details */
policy: OnyxEntry<OnyxTypes.Policy>;
};
type PolicyDistanceRateEditPageProps = StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.DISTANCE_RATE_EDIT>;

type PolicyDistanceRateEditPageProps = PolicyDistanceRateEditPageOnyxProps & StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.WORKSPACE.DISTANCE_RATE_EDIT>;

function PolicyDistanceRateEditPage({policy, route}: PolicyDistanceRateEditPageProps) {
function PolicyDistanceRateEditPage({route}: PolicyDistanceRateEditPageProps) {
const styles = useThemeStyles();
const {translate, toLocaleDigit} = useLocalize();
const {inputCallbackRef} = useAutoFocusInput();

const policyID = route.params.policyID;
const rateID = route.params.rateID;

daledah marked this conversation as resolved.
Show resolved Hide resolved
const policy = usePolicy(policyID);
const customUnits = policy?.customUnits ?? {};
const customUnit = customUnits[Object.keys(customUnits)[0]];
const rate = customUnit?.rates[rateID];
const currency = rate?.currency ?? CONST.CURRENCY.USD;
const currentRateValue = (parseFloat((rate?.rate ?? 0).toString()) / CONST.POLICY.CUSTOM_UNIT_RATE_BASE_OFFSET).toFixed(3);
const currentRateValue = (parseFloat((rate?.rate ?? 0).toString()) / CONST.POLICY.CUSTOM_UNIT_RATE_BASE_OFFSET).toFixed(4);
daledah marked this conversation as resolved.
Show resolved Hide resolved

const submitRate = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.POLICY_DISTANCE_RATE_EDIT_FORM>) => {
if (currentRateValue === values.rate) {
Expand Down Expand Up @@ -94,7 +89,7 @@ function PolicyDistanceRateEditPage({policy, route}: PolicyDistanceRateEditPageP
<InputWrapperWithRef
InputComponent={AmountForm}
inputID={INPUT_IDS.RATE}
extraDecimals={1}
fixedDecimals={4}
daledah marked this conversation as resolved.
Show resolved Hide resolved
defaultValue={currentRateValue}
isCurrencyPressable={false}
currency={currency}
Expand All @@ -108,8 +103,4 @@ function PolicyDistanceRateEditPage({policy, route}: PolicyDistanceRateEditPageP

PolicyDistanceRateEditPage.displayName = 'PolicyDistanceRateEditPage';

export default withOnyx<PolicyDistanceRateEditPageProps, PolicyDistanceRateEditPageOnyxProps>({
policy: {
key: ({route}) => `${ONYXKEYS.COLLECTION.POLICY}${route.params.policyID}`,
},
})(PolicyDistanceRateEditPage);
export default PolicyDistanceRateEditPage;
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import ScreenWrapper from '@components/ScreenWrapper';
import useAutoFocusInput from '@hooks/useAutoFocusInput';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
import {validateTaxClaimableValue} from '@libs/PolicyDistanceRatesUtils';
import type {SettingsNavigatorParamList} from '@navigation/types';
Expand All @@ -35,9 +34,7 @@ function PolicyDistanceRateTaxReclaimableEditPage({route, policy}: PolicyDistanc
const customUnit = customUnits[Object.keys(customUnits)[0]];
const rate = customUnit.rates[rateID];
const currency = rate.currency ?? CONST.CURRENCY.USD;
const extraDecimals = 1;
const decimals = CurrencyUtils.getCurrencyDecimals(currency) + extraDecimals;
const currentTaxReclaimableOnValue = rate.attributes?.taxClaimablePercentage && rate.rate ? ((rate.attributes.taxClaimablePercentage * rate.rate) / 100).toFixed(decimals) : '';
const currentTaxReclaimableOnValue = rate.attributes?.taxClaimablePercentage && rate.rate ? ((rate.attributes.taxClaimablePercentage * rate.rate) / 100).toFixed(4) : '';
daledah marked this conversation as resolved.
Show resolved Hide resolved

const submitTaxReclaimableOn = (values: FormOnyxValues<typeof ONYXKEYS.FORMS.POLICY_DISTANCE_RATE_TAX_RECLAIMABLE_ON_EDIT_FORM>) => {
if (values.taxClaimableValue === currentTaxReclaimableOnValue) {
Expand Down Expand Up @@ -88,7 +85,7 @@ function PolicyDistanceRateTaxReclaimableEditPage({route, policy}: PolicyDistanc
<InputWrapperWithRef
InputComponent={AmountForm}
inputID={INPUT_IDS.TAX_CLAIMABLE_VALUE}
extraDecimals={extraDecimals}
fixedDecimals={4}
daledah marked this conversation as resolved.
Show resolved Hide resolved
defaultValue={currentTaxReclaimableOnValue?.toString() ?? ''}
isCurrencyPressable={false}
currency={currency}
Expand Down
Loading