diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 08ee36ab3944..7050360c2e8e 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -277,10 +277,6 @@ const ROUTES = { route: 'r/:reportID/invite', getRoute: (reportID: string) => `r/${reportID}/invite` as const, }, - MONEY_REQUEST_AMOUNT: { - route: ':iouType/new/amount/:reportID?', - getRoute: (iouType: string, reportID = '') => `${iouType}/new/amount/${reportID}` as const, - }, MONEY_REQUEST_PARTICIPANTS: { route: ':iouType/new/participants/:reportID?', getRoute: (iouType: string, reportID = '') => `${iouType}/new/participants/${reportID}` as const, @@ -304,7 +300,7 @@ const ROUTES = { MONEY_REQUEST_CREATE: { route: ':action/:iouType/start/:transactionID/:reportID', getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string) => - `create/${iouType}/start/${transactionID}/${reportID}` as const, + `${action}/${iouType}/start/${transactionID}/${reportID}` as const, }, MONEY_REQUEST_STEP_CONFIRMATION: { route: ':action/:iouType/confirmation/:transactionID/:reportID', @@ -312,9 +308,9 @@ const ROUTES = { `${action}/${iouType}/confirmation/${transactionID}/${reportID}` as const, }, MONEY_REQUEST_STEP_AMOUNT: { - route: 'create/:iouType/amount/:transactionID/:reportID', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => - getUrlWithBackToParam(`create/${iouType}/amount/${transactionID}/${reportID}`, backTo), + route: ':action/:iouType/amount/:transactionID/:reportID', + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`${action}/${iouType}/amount/${transactionID}/${reportID}`, backTo), }, MONEY_REQUEST_STEP_TAX_RATE: { route: 'create/:iouType/taxRate/:transactionID/:reportID?', @@ -332,9 +328,9 @@ const ROUTES = { getUrlWithBackToParam(`${action}/${iouType}/category/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo), }, MONEY_REQUEST_STEP_CURRENCY: { - route: 'create/:iouType/currency/:transactionID/:reportID/:pageIndex?', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string, pageIndex = '', backTo = '') => - getUrlWithBackToParam(`create/${iouType}/currency/${transactionID}/${reportID}/${pageIndex}`, backTo), + route: ':action/:iouType/currency/:transactionID/:reportID/:pageIndex?', + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string, pageIndex = '', backTo = '') => + getUrlWithBackToParam(`${action}/${iouType}/currency/${transactionID}/${reportID}/${pageIndex}`, backTo), }, MONEY_REQUEST_STEP_DATE: { route: ':action/:iouType/date/:transactionID/:reportID', @@ -397,7 +393,7 @@ const ROUTES = { MONEY_REQUEST_CREATE_TAB_MANUAL: { route: ':action/:iouType/start/:transactionID/:reportID/manual', getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string) => - `create/${iouType}/start/${transactionID}/${reportID}/manual` as const, + `${action}/${iouType}/start/${transactionID}/${reportID}/manual` as const, }, MONEY_REQUEST_CREATE_TAB_SCAN: { route: ':action/:iouType/start/:transactionID/:reportID/scan', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 4da2cb50bf58..c732594cdcbe 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -149,7 +149,6 @@ const SCREENS = { STEP_WAYPOINT: 'Money_Request_Step_Waypoint', STEP_TAX_AMOUNT: 'Money_Request_Step_Tax_Amount', STEP_TAX_RATE: 'Money_Request_Step_Tax_Rate', - AMOUNT: 'Money_Request_Amount', PARTICIPANTS: 'Money_Request_Participants', CURRENCY: 'Money_Request_Currency', WAYPOINT: 'Money_Request_Waypoint', diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 2cda2530d769..e1e39279336f 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -650,11 +650,9 @@ function MoneyRequestConfirmationList({ if (isDistanceRequest) { return; } - if (isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.AMOUNT)); - return; - } - Navigation.navigate(ROUTES.MONEY_REQUEST_AMOUNT.getRoute(iouType, reportID)); + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_AMOUNT.getRoute(CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams()), + ); }} style={[styles.moneyRequestMenuItem, styles.mt2]} titleStyle={styles.moneyRequestConfirmationAmount} diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 3fd76eea657b..afc0c7b703dc 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -681,7 +681,9 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID, CONST.EDIT_REQUEST_FIELD.AMOUNT)); return; } - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_AMOUNT.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams())); + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_AMOUNT.getRoute(CONST.IOU.ACTION.CREATE, iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams()), + ); }} style={[styles.moneyRequestMenuItem, styles.mt2]} titleStyle={styles.moneyRequestConfirmationAmount} diff --git a/src/components/ReportActionItem/MoneyRequestView.tsx b/src/components/ReportActionItem/MoneyRequestView.tsx index 37d939e13868..074baa586dba 100644 --- a/src/components/ReportActionItem/MoneyRequestView.tsx +++ b/src/components/ReportActionItem/MoneyRequestView.tsx @@ -301,7 +301,9 @@ function MoneyRequestView({ titleStyle={styles.textHeadlineH2} interactive={canEditAmount} shouldShowRightIcon={canEditAmount} - onPress={() => Navigation.navigate(ROUTES.EDIT_REQUEST.getRoute(report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))} + onPress={() => + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_AMOUNT.getRoute(CONST.IOU.ACTION.EDIT, CONST.IOU.TYPE.REQUEST, transaction?.transactionID ?? '', report.reportID)) + } brickRoadIndicator={getErrorForField('amount') ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} error={getErrorForField('amount')} /> diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index eb9839077f90..55c58290b1cd 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -86,7 +86,6 @@ const MoneyRequestModalStackNavigator = createModalStackNavigator require('../../../../pages/iou/request/step/IOURequestStepScan').default as React.ComponentType, [SCREENS.MONEY_REQUEST.STEP_TAG]: () => require('../../../../pages/iou/request/step/IOURequestStepTag').default as React.ComponentType, [SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: () => require('../../../../pages/iou/request/step/IOURequestStepWaypoint').default as React.ComponentType, - [SCREENS.MONEY_REQUEST.AMOUNT]: () => require('../../../../pages/iou/steps/NewRequestAmountPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.PARTICIPANTS]: () => require('../../../../pages/iou/steps/MoneyRequstParticipantsPage/MoneyRequestParticipantsPage').default as React.ComponentType, [SCREENS.MONEY_REQUEST.CURRENCY]: () => require('../../../../pages/iou/IOUCurrencySelection').default as React.ComponentType, [SCREENS.MONEY_REQUEST.HOLD]: () => require('../../../../pages/iou/HoldReasonPage').default as React.ComponentType, diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index a5025b3aebeb..f272ae24973a 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -522,7 +522,6 @@ const config: LinkingOptions['config'] = { [SCREENS.MONEY_REQUEST.STEP_SCAN]: ROUTES.MONEY_REQUEST_STEP_SCAN.route, [SCREENS.MONEY_REQUEST.STEP_TAG]: ROUTES.MONEY_REQUEST_STEP_TAG.route, [SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: ROUTES.MONEY_REQUEST_STEP_WAYPOINT.route, - [SCREENS.MONEY_REQUEST.AMOUNT]: ROUTES.MONEY_REQUEST_AMOUNT.route, [SCREENS.MONEY_REQUEST.STEP_TAX_AMOUNT]: ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.route, [SCREENS.MONEY_REQUEST.STEP_TAX_RATE]: ROUTES.MONEY_REQUEST_STEP_TAX_RATE.route, [SCREENS.MONEY_REQUEST.PARTICIPANTS]: ROUTES.MONEY_REQUEST_PARTICIPANTS.route, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 576ccda44dbf..dac3a98f4d7c 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -336,10 +336,12 @@ type RoomInviteNavigatorParamList = { }; type MoneyRequestNavigatorParamList = { - [SCREENS.MONEY_REQUEST.AMOUNT]: { + [SCREENS.MONEY_REQUEST.STEP_AMOUNT]: { + action: ValueOf; iouType: ValueOf; + transactionID: string; reportID: string; - currency: string; + backTo: string; }; [SCREENS.MONEY_REQUEST.PARTICIPANTS]: { iouType: string; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 64f2864d2e62..f99942a3d7a8 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -352,12 +352,13 @@ function setMoneyRequestCreated(transactionID: string, created: string, isDraft: } // eslint-disable-next-line @typescript-eslint/naming-convention -function setMoneyRequestCurrency_temporaryForRefactor(transactionID: string, currency: string, removeOriginalCurrency = false) { +function setMoneyRequestCurrency_temporaryForRefactor(transactionID: string, currency: string, removeOriginalCurrency = false, isEditing = false) { + const fieldToUpdate = isEditing ? 'modifiedCurrency' : 'currency'; if (removeOriginalCurrency) { - Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {currency, originalCurrency: null}); + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {[fieldToUpdate]: currency, originalCurrency: null}); return; } - Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {currency}); + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, {[fieldToUpdate]: currency}); } // eslint-disable-next-line @typescript-eslint/naming-convention @@ -5063,45 +5064,6 @@ function setShownHoldUseExplanation() { Onyx.set(ONYXKEYS.NVP_HOLD_USE_EXPLAINED, true); } -/** Navigates to the next IOU page based on where the IOU request was started */ -function navigateToNextPage(iou: OnyxEntry, iouType: string, report?: OnyxEntry, path = '') { - const moneyRequestID = `${iouType}${report?.reportID ?? ''}`; - const shouldReset = iou?.id !== moneyRequestID && !!report?.reportID; - - // If the money request ID in Onyx does not match the ID from params, we want to start a new request - // with the ID from params. We need to clear the participants in case the new request is initiated from FAB. - if (shouldReset) { - resetMoneyRequestInfo(moneyRequestID); - } - - // If we're adding a receipt, that means the user came from the confirmation page and we need to navigate back to it. - if (path.slice(1) === ROUTES.MONEY_REQUEST_RECEIPT.getRoute(iouType, report?.reportID)) { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType as ValueOf, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, report?.reportID ?? '1'), - ); - return; - } - - // If a request is initiated on a report, skip the participants selection step and navigate to the confirmation page. - if (report?.reportID) { - // If the report is iou or expense report, we should get the chat report to set participant for request money - const chatReport = ReportUtils.isMoneyRequestReport(report) ? ReportUtils.getReport(report.chatReportID) : report; - // Reinitialize the participants when the money request ID in Onyx does not match the ID from params - if (!iou?.participants?.length || shouldReset) { - const currentUserAccountID = currentUserPersonalDetails.accountID; - const participants: Participant[] = ReportUtils.isPolicyExpenseChat(chatReport) - ? [{reportID: chatReport?.reportID, isPolicyExpenseChat: true, selected: true}] - : (chatReport?.participantAccountIDs ?? []).filter((accountID) => currentUserAccountID !== accountID).map((accountID) => ({accountID, selected: true})); - setMoneyRequestParticipants(participants); - } - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType as ValueOf, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, report.reportID), - ); - return; - } - Navigation.navigate(ROUTES.MONEY_REQUEST_PARTICIPANTS.getRoute(iouType)); -} - /** * Put money request on HOLD */ @@ -5295,7 +5257,6 @@ export { setMoneyRequestTaxAmount, setMoneyRequestTaxRate, setShownHoldUseExplanation, - navigateToNextPage, updateMoneyRequestDate, updateMoneyRequestBillable, updateMoneyRequestMerchant, diff --git a/src/pages/EditRequestAmountPage.js b/src/pages/EditRequestAmountPage.js deleted file mode 100644 index bc77b9ecca75..000000000000 --- a/src/pages/EditRequestAmountPage.js +++ /dev/null @@ -1,66 +0,0 @@ -import {useFocusEffect} from '@react-navigation/native'; -import PropTypes from 'prop-types'; -import React, {useCallback, useRef} from 'react'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import useLocalize from '@hooks/useLocalize'; -import * as DeviceCapabilities from '@libs/DeviceCapabilities'; -import CONST from '@src/CONST'; -import MoneyRequestAmountForm from './iou/steps/MoneyRequestAmountForm'; - -const propTypes = { - /** Transaction default amount value */ - defaultAmount: PropTypes.number.isRequired, - - /** Transaction default currency value */ - defaultCurrency: PropTypes.string.isRequired, - - /** Callback to fire when the Save button is pressed */ - onSubmit: PropTypes.func.isRequired, - - /** Callback to fire when we press on the currency */ - onNavigateToCurrency: PropTypes.func.isRequired, -}; - -function EditRequestAmountPage({defaultAmount, defaultCurrency, onNavigateToCurrency, onSubmit}) { - const {translate} = useLocalize(); - - const textInput = useRef(null); - const focusTimeoutRef = useRef(null); - - useFocusEffect( - useCallback(() => { - focusTimeoutRef.current = setTimeout(() => textInput.current && textInput.current.focus(), CONST.ANIMATED_TRANSITION); - return () => { - if (!focusTimeoutRef.current) { - return; - } - clearTimeout(focusTimeoutRef.current); - }; - }, []), - ); - - return ( - - - (textInput.current = e)} - onCurrencyButtonPress={onNavigateToCurrency} - onSubmitButtonPress={onSubmit} - isEditing - /> - - ); -} - -EditRequestAmountPage.propTypes = propTypes; -EditRequestAmountPage.displayName = 'EditRequestAmountPage'; - -export default EditRequestAmountPage; diff --git a/src/pages/EditRequestPage.js b/src/pages/EditRequestPage.js index eecffd81d88b..d3941dca044e 100644 --- a/src/pages/EditRequestPage.js +++ b/src/pages/EditRequestPage.js @@ -8,7 +8,6 @@ import ScreenWrapper from '@components/ScreenWrapper'; import tagPropTypes from '@components/tagPropTypes'; import transactionPropTypes from '@components/transactionPropTypes'; import compose from '@libs/compose'; -import * as CurrencyUtils from '@libs/CurrencyUtils'; import * as IOUUtils from '@libs/IOUUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; @@ -18,8 +17,6 @@ import * as TransactionUtils from '@libs/TransactionUtils'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import EditRequestAmountPage from './EditRequestAmountPage'; import EditRequestReceiptPage from './EditRequestReceiptPage'; import EditRequestTagPage from './EditRequestTagPage'; import reportActionPropTypes from './home/report/reportActionPropTypes'; @@ -74,9 +71,8 @@ const defaultProps = { function EditRequestPage({report, route, policy, policyCategories, policyTags, parentReportActions, transaction}) { const parentReportActionID = lodashGet(report, 'parentReportActionID', '0'); const parentReportAction = lodashGet(parentReportActions, parentReportActionID, {}); - const {amount: transactionAmount, currency: transactionCurrency, tag: transactionTag} = ReportUtils.getTransactionDetails(transaction); + const {tag: transactionTag} = ReportUtils.getTransactionDetails(transaction); - const defaultCurrency = lodashGet(route, 'params.currency', '') || transactionCurrency; const fieldToEdit = lodashGet(route, ['params', 'field'], ''); const tagListIndex = Number(lodashGet(route, ['params', 'tagIndex'], undefined)); @@ -103,22 +99,6 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p }); }, [parentReportAction, fieldToEdit]); - const saveAmountAndCurrency = useCallback( - ({amount, currency: newCurrency}) => { - const newAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(amount)); - - // If the value hasn't changed, don't request to save changes on the server and just close the modal - if (newAmount === TransactionUtils.getAmount(transaction) && newCurrency === TransactionUtils.getCurrency(transaction)) { - Navigation.dismissModal(); - return; - } - - IOU.updateMoneyRequestAmountAndCurrency(transaction.transactionID, report.reportID, newCurrency, newAmount, policy, policyTags, policyCategories); - Navigation.dismissModal(); - }, - [transaction, report, policy, policyTags, policyCategories], - ); - const saveTag = useCallback( ({tag: newTag}) => { let updatedTag = newTag; @@ -139,21 +119,6 @@ function EditRequestPage({report, route, policy, policyCategories, policyTags, p [tag, transaction.transactionID, report.reportID, transactionTag, tagListIndex, policy, policyTags, policyCategories], ); - if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.AMOUNT) { - return ( - { - const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); - Navigation.navigate(ROUTES.EDIT_CURRENCY_REQUEST.getRoute(report.reportID, defaultCurrency, activeRoute)); - }} - /> - ); - } - if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.TAG && shouldShowTags) { return ( ; function EditSplitBillPage({route, transaction, draftTransaction, report}: EditSplitBillProps) { - const {field: fieldToEdit, reportID, reportActionID, currency, tagIndex} = route.params; + const {field: fieldToEdit, reportID, reportActionID, tagIndex} = route.params; - const {amount: transactionAmount, currency: transactionCurrency, tag: transactionTag} = ReportUtils.getTransactionDetails(draftTransaction ?? transaction) ?? {}; + const {tag: transactionTag} = ReportUtils.getTransactionDetails(draftTransaction ?? transaction) ?? {}; - const defaultCurrency = currency ?? transactionCurrency; function navigateBackToSplitDetails() { Navigation.navigate(ROUTES.SPLIT_BILL_DETAILS.getRoute(reportID, reportActionID)); } @@ -53,27 +50,6 @@ function EditSplitBillPage({route, transaction, draftTransaction, report}: EditS navigateBackToSplitDetails(); }; - if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.AMOUNT) { - return ( - { - const amount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(transactionChanges.amount)); - - setDraftSplitTransaction({ - amount, - currency: transactionChanges.currency, - }); - }} - onNavigateToCurrency={() => { - const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL_CURRENCY.getRoute(reportID, reportActionID, defaultCurrency, activeRoute)); - }} - /> - ); - } - if (fieldToEdit === CONST.EDIT_REQUEST_FIELD.TAG) { return ( { function IOURequestStepAmount({ report, route: { - params: {iouType, reportID, transactionID, backTo}, + params: {iouType, reportID, transactionID, backTo, action}, }, transaction, - transaction: {currency}, + splitDraftTransaction, + draftTransaction, policy, }) { const {translate} = useLocalize(); @@ -79,6 +90,11 @@ function IOURequestStepAmount({ const isSaveButtonPressed = useRef(false); const originalCurrency = useRef(null); const iouRequestType = getRequestType(transaction); + const isEditing = action === CONST.IOU.ACTION.EDIT; + const isSplitBill = iouType === CONST.IOU.TYPE.SPLIT; + const isEditingSplitBill = isEditing && isSplitBill; + const {amount: transactionAmount} = ReportUtils.getTransactionDetails(isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? splitDraftTransaction : transaction); + const {currency} = ReportUtils.getTransactionDetails(isEditing ? draftTransaction : transaction); const taxRates = lodashGet(policy, 'taxRates', {}); const isPolicyExpenseChat = ReportUtils.isPolicyExpenseChat(ReportUtils.getRootParentReport(report)); @@ -97,6 +113,19 @@ function IOURequestStepAmount({ ); useEffect(() => { + if (isEditing) { + // A temporary solution to not prevent users from editing the currency + // We create a backup transaction and use it to save the currency and remove this transaction backup if we don't save the amount + // It should be removed after this issue https://github.com/Expensify/App/issues/34607 is fixed + TransactionEdit.createBackupTransaction(isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? splitDraftTransaction : transaction); + + return () => { + if (isSaveButtonPressed.current) { + return; + } + TransactionEdit.removeBackupTransaction(transaction.transactionID || ''); + }; + } if (transaction.originalCurrency) { originalCurrency.current = transaction.originalCurrency; } else { @@ -117,7 +146,7 @@ function IOURequestStepAmount({ }; const navigateToCurrencySelectionPage = () => { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CURRENCY.getRoute(iouType, transactionID, reportID, backTo ? 'confirm' : '', Navigation.getActiveRouteWithoutParams())); + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CURRENCY.getRoute(action, iouType, transactionID, reportID, backTo ? 'confirm' : '', Navigation.getActiveRouteWithoutParams())); }; /** @@ -154,21 +183,45 @@ function IOURequestStepAmount({ Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID)); }; + const saveAmountAndCurrency = ({amount}) => { + if (!isEditing) { + navigateToNextPage({amount}); + return; + } + + const newAmount = CurrencyUtils.convertToBackendAmount(Number.parseFloat(amount)); + + // If the value hasn't changed, don't request to save changes on the server and just close the modal + if (newAmount === TransactionUtils.getAmount(transaction) && currency === TransactionUtils.getCurrency(transaction)) { + Navigation.dismissModal(); + return; + } + + if (isSplitBill) { + IOU.setDraftSplitTransaction(transactionID, {amount: newAmount, currency}); + Navigation.goBack(backTo); + return; + } + + IOU.updateMoneyRequestAmountAndCurrency(transactionID, reportID, currency, newAmount); + Navigation.dismissModal(); + }; + return ( (textInput.current = e)} onCurrencyButtonPress={navigateToCurrencySelectionPage} - onSubmitButtonPress={navigateToNextPage} + onSubmitButtonPress={saveAmountAndCurrency} selectedTab={iouRequestType} /> @@ -183,8 +236,20 @@ export default compose( withWritableReportOrNotFound, withFullTransactionOrNotFound, withOnyx({ + splitDraftTransaction: { + key: ({route}) => { + const transactionID = lodashGet(route, 'params.transactionID', 0); + return `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`; + }, + }, policy: { key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report ? report.policyID : '0'}`, }, + draftTransaction: { + key: ({route}) => { + const transactionID = lodashGet(route, 'params.transactionID', 0); + return `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`; + }, + }, }), )(IOURequestStepAmount); diff --git a/src/pages/iou/request/step/IOURequestStepCurrency.js b/src/pages/iou/request/step/IOURequestStepCurrency.js index 53f623eaea63..51dba5858cb5 100644 --- a/src/pages/iou/request/step/IOURequestStepCurrency.js +++ b/src/pages/iou/request/step/IOURequestStepCurrency.js @@ -1,4 +1,5 @@ import Str from 'expensify-common/lib/str'; +import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; import React, {useMemo, useRef, useState} from 'react'; import {Keyboard} from 'react-native'; @@ -11,6 +12,7 @@ import useLocalize from '@hooks/useLocalize'; import compose from '@libs/compose'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import Navigation from '@libs/Navigation/Navigation'; +import * as ReportUtils from '@libs/ReportUtils'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -41,25 +43,26 @@ const propTypes = { ), /* Onyx Props */ - /** The transaction being modified */ - transaction: transactionPropTypes, + /** The draft transaction object being modified in Onyx */ + draftTransaction: transactionPropTypes, }; const defaultProps = { currencyList: {}, - transaction: {}, + draftTransaction: {}, }; function IOURequestStepCurrency({ currencyList, route: { - params: {backTo, iouType, pageIndex, reportID, transactionID}, + params: {backTo, iouType, pageIndex, reportID, transactionID, action}, }, - transaction: {currency}, + draftTransaction, }) { const {translate} = useLocalize(); const [searchValue, setSearchValue] = useState(''); const optionsSelectorRef = useRef(); + const {currency} = ReportUtils.getTransactionDetails(draftTransaction); const navigateBack = () => { // If the currency selection was done from the confirmation step (eg. + > request money > manual > confirm > amount > currency) @@ -83,7 +86,7 @@ function IOURequestStepCurrency({ */ const confirmCurrencySelection = (option) => { Keyboard.dismiss(); - IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, option.currencyCode); + IOU.setMoneyRequestCurrency_temporaryForRefactor(transactionID, option.currencyCode, false, action === CONST.IOU.ACTION.EDIT); navigateBack(); }; @@ -157,5 +160,11 @@ export default compose( withFullTransactionOrNotFound, withOnyx({ currencyList: {key: ONYXKEYS.CURRENCY_LIST}, + draftTransaction: { + key: ({route}) => { + const transactionID = lodashGet(route, 'params.transactionID', 0); + return `${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`; + }, + }, }), )(IOURequestStepCurrency); diff --git a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js index 1c3e4197a146..fb984cb801c1 100644 --- a/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js +++ b/src/pages/iou/request/step/IOURequestStepTaxAmountPage.js @@ -112,7 +112,9 @@ function IOURequestStepTaxAmountPage({ // If the money request being created is a distance request, don't allow the user to choose the currency. // Only USD is allowed for distance requests. // Remove query from the route and encode it. - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CURRENCY.getRoute(iouType, transactionID, reportID, backTo ? 'confirm' : '', Navigation.getActiveRouteWithoutParams())); + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_CURRENCY.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backTo ? 'confirm' : '', Navigation.getActiveRouteWithoutParams()), + ); }; const updateTaxAmount = (currentAmount) => { diff --git a/src/pages/iou/steps/NewRequestAmountPage.tsx b/src/pages/iou/steps/NewRequestAmountPage.tsx deleted file mode 100644 index 0528af502e99..000000000000 --- a/src/pages/iou/steps/NewRequestAmountPage.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import {useFocusEffect} from '@react-navigation/native'; -import type {StackScreenProps} from '@react-navigation/stack'; -import React, {useCallback, useEffect, useRef} from 'react'; -import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; -import type {OnyxEntry} from 'react-native-onyx'; -import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; -import useLocalize from '@hooks/useLocalize'; -import useThemeStyles from '@hooks/useThemeStyles'; -import * as CurrencyUtils from '@libs/CurrencyUtils'; -import * as IOUUtils from '@libs/IOUUtils'; -import * as MoneyRequestUtils from '@libs/MoneyRequestUtils'; -import Navigation from '@libs/Navigation/Navigation'; -import type {MoneyRequestNavigatorParamList} from '@libs/Navigation/types'; -import * as IOU from '@userActions/IOU'; -import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type SCREENS from '@src/SCREENS'; -import type {IOU as IOUType, Report, SelectedTabRequest} from '@src/types/onyx'; -import MoneyRequestAmountForm from './MoneyRequestAmountForm'; - -type NavigateToNextPageOptions = {amount: string}; - -type NewRequestAmountPageOnyxProps = { - /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ - iou: OnyxEntry; - - /** The report on which the request is initiated on */ - report: OnyxEntry; - - /** The current tab we have navigated to in the request modal. String that corresponds to the request type. */ - selectedTab: OnyxEntry; -}; - -type NewRequestAmountPageProps = NewRequestAmountPageOnyxProps & StackScreenProps; - -function NewRequestAmountPage({route, iou, report, selectedTab}: NewRequestAmountPageProps) { - const styles = useThemeStyles(); - const {translate} = useLocalize(); - - const prevMoneyRequestID = useRef(iou?.id); - const textInput = useRef(null); - - const iouType = route.params.iouType ?? ''; - const reportID = route.params.reportID ?? ''; - const isEditing = Navigation.getActiveRoute().includes('amount'); - const currentCurrency = route.params.currency ?? ''; - const isDistanceRequestTab = MoneyRequestUtils.isDistanceRequest(iouType, selectedTab); - - const currency = CurrencyUtils.isValidCurrencyCode(currentCurrency) ? currentCurrency : iou?.currency ?? ''; - - const focusTimeoutRef = useRef(null); - - useFocusEffect( - useCallback(() => { - focusTimeoutRef.current = setTimeout(() => textInput.current?.focus(), CONST.ANIMATED_TRANSITION); - return () => { - if (!focusTimeoutRef.current) { - return; - } - clearTimeout(focusTimeoutRef.current); - }; - }, []), - ); - - // Because we use Onyx to store IOU info, when we try to make two different money requests from different tabs, - // it can result in an IOU sent with improper values. In such cases we want to reset the flow and redirect the user to the first step of the IOU. - useEffect(() => { - if (isEditing) { - // ID in Onyx could change by initiating a new request in a separate browser tab or completing a request - if (prevMoneyRequestID.current !== iou?.id) { - // The ID is cleared on completing a request. In that case, we will do nothing. - if (!iou?.id) { - return; - } - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, '1', reportID), true); - return; - } - const moneyRequestID = `${iouType}${reportID}`; - const shouldReset = iou?.id !== moneyRequestID; - if (shouldReset) { - IOU.resetMoneyRequestInfo(moneyRequestID); - } - - if (!isDistanceRequestTab && (!iou?.participants?.length || iou?.amount === 0 || shouldReset)) { - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, '1', reportID), true); - } - } - - return () => { - prevMoneyRequestID.current = iou?.id; - }; - }, [isEditing, iouType, reportID, isDistanceRequestTab, report?.reportID, iou?.id, iou?.participants?.length, iou?.amount]); - - const navigateBack = () => { - Navigation.goBack(isEditing ? ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, '1', reportID) : ROUTES.HOME); - }; - - const navigateToCurrencySelectionPage = () => { - // If the money request being created is a distance request, don't allow the user to choose the currency. - // Only USD is allowed for distance requests. - if (isDistanceRequestTab) { - return; - } - - // Remove query from the route and encode it. - const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); - Navigation.navigate(ROUTES.MONEY_REQUEST_CURRENCY.getRoute(iouType, reportID, currency, activeRoute)); - }; - - const navigateToNextPage = ({amount}: NavigateToNextPageOptions) => { - const amountInSmallestCurrencyUnits = CurrencyUtils.convertToBackendAmount(Number.parseFloat(amount)); - IOU.setMoneyRequestAmount(amountInSmallestCurrencyUnits); - IOU.setMoneyRequestCurrency(currency); - - if (isEditing) { - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, '1', reportID)); - return; - } - - IOU.navigateToNextPage(iou, iouType, report); - }; - - const content = ( - - ); - - // ScreenWrapper is only needed in edit mode because we have a dedicated route for the edit amount page (MoneyRequestEditAmountPage). - // The rest of the cases this component is rendered through which has it's own ScreenWrapper - if (!isEditing) { - return content; - } - - return ( - - {({safeAreaPaddingBottomStyle}) => ( - - - - {content} - - - )} - - ); -} - -NewRequestAmountPage.displayName = 'NewRequestAmountPage'; - -export default withOnyx({ - iou: {key: ONYXKEYS.IOU}, - report: { - key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID}`, - }, - selectedTab: { - key: `${ONYXKEYS.COLLECTION.SELECTED_TAB}${CONST.TAB.RECEIPT_TAB_ID}`, - }, -})(NewRequestAmountPage);