Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 21 additions & 2 deletions src/libs/actions/IOU.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,13 @@ function clearMoneyRequest(transactionID) {
* @param {String} transactionID
* @param {Number} amount
* @param {String} currency
* @param {Boolean} [removeOriginalCurrency]
*/
function setMoneyRequestAmount_temporaryForRefactor(transactionID, amount, currency) {
function setMoneyRequestAmount_temporaryForRefactor(transactionID, amount, currency, removeOriginalCurrency = false) {
if (removeOriginalCurrency) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {amount, currency, originalCurrency: null});
return;
}
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {amount, currency});
}

Expand All @@ -193,11 +198,24 @@ function setMoneyRequestCreated_temporaryForRefactor(transactionID, created) {
/**
* @param {String} transactionID
* @param {String} currency
* @param {Boolean} [removeOriginalCurrency]
*/
function setMoneyRequestCurrency_temporaryForRefactor(transactionID, currency) {
function setMoneyRequestCurrency_temporaryForRefactor(transactionID, currency, removeOriginalCurrency = false) {
if (removeOriginalCurrency) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {currency, originalCurrency: null});
return;
}
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {currency});
}

/**
* @param {String} transactionID
* @param {String} originalCurrency
*/
function setMoneyRequestOriginalCurrency_temporaryForRefactor(transactionID, originalCurrency) {
Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {originalCurrency});
}

/**
* @param {String} transactionID
* @param {String} comment
Expand Down Expand Up @@ -3669,6 +3687,7 @@ export {
setMoneyRequestCategory_temporaryForRefactor,
setMoneyRequestCreated_temporaryForRefactor,
setMoneyRequestCurrency_temporaryForRefactor,
setMoneyRequestOriginalCurrency_temporaryForRefactor,
setMoneyRequestDescription_temporaryForRefactor,
setMoneyRequestMerchant_temporaryForRefactor,
setMoneyRequestParticipants_temporaryForRefactor,
Expand Down
28 changes: 23 additions & 5 deletions src/pages/iou/request/step/IOURequestStepAmount.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {useFocusEffect} from '@react-navigation/native';
import PropTypes from 'prop-types';
import React, {useCallback, useRef} from 'react';
import React, {useCallback, useEffect, useRef} from 'react';
import {withOnyx} from 'react-native-onyx';
import taxPropTypes from '@components/taxPropTypes';
import transactionPropTypes from '@components/transactionPropTypes';
Expand Down Expand Up @@ -59,18 +59,19 @@ const getTaxAmount = (transaction, defaultTaxValue, amount) => {
function IOURequestStepAmount({
report,
route: {
params: {iouType, reportID, transactionID, backTo, currency: selectedCurrency},
params: {iouType, reportID, transactionID, backTo},
},
transaction,
transaction: {currency: originalCurrency},
transaction: {currency},
policyTaxRates,
policy,
}) {
const {translate} = useLocalize();
const textInput = useRef(null);
const focusTimeoutRef = useRef(null);
const isSaveButtonPressed = useRef(false);
const originalCurrency = useRef(null);
const iouRequestType = getRequestType(transaction);
const currency = selectedCurrency || originalCurrency;

const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report));
const isTaxTrackingEnabled = isPolicyExpenseChat && policy.isTaxTrackingEnabled;
Expand All @@ -87,6 +88,22 @@ function IOURequestStepAmount({
}, []),
);

useEffect(() => {
if (transaction.originalCurrency) {
originalCurrency.current = transaction.originalCurrency;
} else {
originalCurrency.current = currency;
IOU.setMoneyRequestOriginalCurrency_temporaryForRefactor(transactionID, currency);
}
return () => {
if (isSaveButtonPressed.current) {
return;
}
IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, originalCurrency.current, true);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking is it possible if we don't need an additional useRef and modify current IOU.setMoneyRequestOriginalCurrency_temporaryForRefactor to pass a 3rd params like current implementation.

How about?

useEffect(() => {
    IOU.setMoneyRequestOriginalCurrency_temporaryForRefactor(transactionID, currency);
    return () => {
        if (isSaveButtonPressed.current) {
            return;
        }
        IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, transaction.originalCurrency);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it was creating some problems as it was keeping old values in mount / unmount.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or we can always reset originalCurrency on unmount.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let keep it this way as it helps me with cases of refresh (it will call mount again, and will set wrong value on refresh).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @shubham1206agra I will try to test & complete review checklist tomorrow


const navigateBack = () => {
Navigation.goBack(backTo || ROUTES.HOME);
};
Expand All @@ -99,6 +116,7 @@ function IOURequestStepAmount({
* @param {Number} amount
*/
const navigateToNextPage = ({amount}) => {
isSaveButtonPressed.current = true;
const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(amount));

if ((iouRequestType === CONST.IOU.REQUEST_TYPE.MANUAL || backTo) && isTaxTrackingEnabled) {
Expand All @@ -107,7 +125,7 @@ function IOURequestStepAmount({
IOU.setMoneyRequestTaxAmount(transaction.transactionID, taxAmountInSmallestCurrencyUnits);
}

IOU.setMoneyRequestAmount_temporaryForRefactor(transactionID, amountInSmallestCurrencyUnits, currency || CONST.CURRENCY.USD);
IOU.setMoneyRequestAmount_temporaryForRefactor(transactionID, amountInSmallestCurrencyUnits, currency || CONST.CURRENCY.USD, true);

if (backTo) {
Navigation.goBack(backTo);
Expand Down
82 changes: 50 additions & 32 deletions src/pages/iou/request/step/IOURequestStepConfirmation.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import _ from 'underscore';
import categoryPropTypes from '@components/categoryPropTypes';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import * as Expensicons from '@components/Icon/Expensicons';
import MoneyRequestConfirmationList from '@components/MoneyTemporaryForRefactorRequestConfirmationList';
Expand Down Expand Up @@ -103,6 +104,15 @@ function IOURequestStepConfirmation({
);
const isPolicyExpenseChat = useMemo(() => ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)), [report]);

useEffect(() => {
if (!transaction || !transaction.originalCurrency) {
return;
}
// If user somehow lands on this page without the currency reset, then reset it here.
IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, transaction.originalCurrency, true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useEffect(() => {
const policyExpenseChat = _.find(participants, (participant) => participant.isPolicyExpenseChat);
if (policyExpenseChat) {
Expand Down Expand Up @@ -318,6 +328,10 @@ function IOURequestStepConfirmation({
IOU.setMoneyRequestBillable_temporaryForRefactor(transactionID, billable);
};

// This loading indicator is shown because the transaction originalCurrency is being updated later than the component mounts.
// To prevent the component from rendering with the wrong currency, we show a loading indicator until the correct currency is set.
const isLoading = !!(transaction && transaction.originalCurrency);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to leave comment here to explain why we have this code

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shubham1206agra could you help to leave a comment here, other than that it looks good to me.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks mate


return (
<ScreenWrapper
includeSafeAreaPaddingBottom={false}
Expand All @@ -339,38 +353,42 @@ function IOURequestStepConfirmation({
},
]}
/>
<MoneyRequestConfirmationList
transaction={transaction}
hasMultipleParticipants={iouType === CONST.IOU.TYPE.SPLIT}
selectedParticipants={participants}
iouAmount={transaction.amount}
iouComment={lodashGet(transaction, 'comment.comment', '')}
iouCurrencyCode={transaction.currency}
iouIsBillable={transaction.billable}
onToggleBillable={setBillable}
iouCategory={transaction.category}
iouTag={transaction.tag}
onConfirm={createTransaction}
onSendMoney={sendMoney}
onSelectParticipant={addNewParticipant}
receiptPath={receiptPath}
receiptFilename={receiptFilename}
iouType={iouType}
reportID={reportID}
isPolicyExpenseChat={isPolicyExpenseChat}
// The participants can only be modified when the action is initiated from directly within a group chat and not the floating-action-button.
// This is because when there is a group of people, say they are on a trip, and you have some shared expenses with some of the people,
// but not all of them (maybe someone skipped out on dinner). Then it's nice to be able to select/deselect people from the group chat bill
// split rather than forcing the user to create a new group, just for that expense. The reportID is empty, when the action was initiated from
// the floating-action-button (since it is something that exists outside the context of a report).
canModifyParticipants={!transaction.isFromGlobalCreate}
policyID={report.policyID}
bankAccountRoute={ReportUtils.getBankAccountRoute(report)}
iouMerchant={transaction.merchant}
iouCreated={transaction.created}
isDistanceRequest={requestType === CONST.IOU.REQUEST_TYPE.DISTANCE}
shouldShowSmartScanFields={_.isEmpty(lodashGet(transaction, 'receipt.source', ''))}
/>
{isLoading ? (
<FullScreenLoadingIndicator />
) : (
<MoneyRequestConfirmationList
transaction={transaction}
hasMultipleParticipants={iouType === CONST.IOU.TYPE.SPLIT}
selectedParticipants={participants}
iouAmount={transaction.amount}
iouComment={lodashGet(transaction, 'comment.comment', '')}
iouCurrencyCode={transaction.currency}
iouIsBillable={transaction.billable}
onToggleBillable={setBillable}
iouCategory={transaction.category}
iouTag={transaction.tag}
onConfirm={createTransaction}
onSendMoney={sendMoney}
onSelectParticipant={addNewParticipant}
receiptPath={receiptPath}
receiptFilename={receiptFilename}
iouType={iouType}
reportID={reportID}
isPolicyExpenseChat={isPolicyExpenseChat}
// The participants can only be modified when the action is initiated from directly within a group chat and not the floating-action-button.
// This is because when there is a group of people, say they are on a trip, and you have some shared expenses with some of the people,
// but not all of them (maybe someone skipped out on dinner). Then it's nice to be able to select/deselect people from the group chat bill
// split rather than forcing the user to create a new group, just for that expense. The reportID is empty, when the action was initiated from
// the floating-action-button (since it is something that exists outside the context of a report).
canModifyParticipants={!transaction.isFromGlobalCreate}
policyID={report.policyID}
bankAccountRoute={ReportUtils.getBankAccountRoute(report)}
iouMerchant={transaction.merchant}
iouCreated={transaction.created}
isDistanceRequest={requestType === CONST.IOU.REQUEST_TYPE.DISTANCE}
shouldShowSmartScanFields={_.isEmpty(lodashGet(transaction, 'receipt.source', ''))}
/>
)}
</View>
)}
</ScreenWrapper>
Expand Down
14 changes: 4 additions & 10 deletions src/pages/iou/request/step/IOURequestStepCurrency.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,14 @@ function IOURequestStepCurrency({
const [searchValue, setSearchValue] = useState('');
const optionsSelectorRef = useRef();

const navigateBack = (selectedCurrency = undefined) => {
const navigateBack = () => {
// If the currency selection was done from the confirmation step (eg. + > request money > manual > confirm > amount > currency)
// then the user needs taken back to the confirmation page instead of the initial amount page. This is because the route params
// are only able to handle one backTo param at a time and the user needs to go back to the amount page before going back
// to the confirmation page
if (pageIndex === 'confirm') {
const routeToAmountPageWithConfirmationAsBackTo = getUrlWithBackToParam(backTo, `/${ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(iouType, transactionID, reportID)}`);
if (selectedCurrency) {
Navigation.navigate(`${routeToAmountPageWithConfirmationAsBackTo}&currency=${selectedCurrency}`);
} else {
Navigation.goBack(routeToAmountPageWithConfirmationAsBackTo);
}
Navigation.goBack(routeToAmountPageWithConfirmationAsBackTo);
return;
}
Navigation.goBack(backTo || ROUTES.HOME);
Expand All @@ -82,10 +78,8 @@ function IOURequestStepCurrency({
*/
const confirmCurrencySelection = (option) => {
Keyboard.dismiss();
if (pageIndex !== 'confirm') {
IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, option.currencyCode);
}
navigateBack(option.currencyCode);
IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, option.currencyCode);
navigateBack();
};

const {sections, headerMessage, initiallyFocusedOptionKey} = useMemo(() => {
Expand Down
30 changes: 24 additions & 6 deletions src/pages/iou/request/step/IOURequestStepTaxAmountPage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {useFocusEffect} from '@react-navigation/native';
import React, {useCallback, useRef} from 'react';
import React, {useCallback, useEffect, useRef} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
Expand Down Expand Up @@ -53,10 +53,10 @@ const getTaxAmount = (transaction, defaultTaxValue) => {

function IOURequestStepTaxAmountPage({
route: {
params: {iouType, reportID, transactionID, backTo, currency: selectedCurrency},
params: {iouType, reportID, transactionID, backTo},
},
transaction,
transaction: {currency: originalCurrency},
transaction: {currency},
report,
policyTaxRates,
}) {
Expand All @@ -65,10 +65,27 @@ function IOURequestStepTaxAmountPage({
const textInput = useRef(null);
const isEditing = Navigation.getActiveRoute().includes('taxAmount');

const currency = selectedCurrency || originalCurrency;

const focusTimeoutRef = useRef(null);

const isSaveButtonPressed = useRef(false);
const originalCurrency = useRef(null);

useEffect(() => {
if (transaction.originalCurrency) {
originalCurrency.current = transaction.originalCurrency;
} else {
originalCurrency.current = currency;
IOU.setMoneyRequestOriginalCurrency_temporaryForRefactor(transactionID, currency);
}
return () => {
if (isSaveButtonPressed.current) {
return;
}
IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, originalCurrency.current, true);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useFocusEffect(
useCallback(() => {
focusTimeoutRef.current = setTimeout(() => textInput.current && textInput.current.focus(), CONST.ANIMATED_TRANSITION);
Expand All @@ -93,10 +110,11 @@ function IOURequestStepTaxAmountPage({
};

const updateTaxAmount = (currentAmount) => {
isSaveButtonPressed.current = true;
const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(currentAmount.amount));
IOU.setMoneyRequestTaxAmount(transactionID, amountInSmallestCurrencyUnits);

IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, currency || CONST.CURRENCY.USD);
IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, currency || CONST.CURRENCY.USD, true);

if (backTo) {
Navigation.goBack(backTo);
Expand Down