From d10afcbc59b5d5ecbda2870000b6836266c107eb Mon Sep 17 00:00:00 2001 From: dominictb Date: Tue, 25 Jun 2024 10:02:38 +0700 Subject: [PATCH 01/12] fix: do not refresh draft txn after redirect --- src/libs/actions/IOU.ts | 15 +++++++++++++++ src/pages/iou/request/IOURequestStartPage.tsx | 10 +++++++++- .../request/step/IOURequestStepConfirmation.tsx | 3 ++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index bc4569bf4603..77c4378c325f 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -364,6 +364,20 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, }); } +/** + * + * @param transactionID + * @param reportID + */ +function resetMoneyRequest(transactionID: string, reportID: string, isFromGlobalCreate: boolean) { + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, { + reportID, + participants: [], + participantsAutoAssigned: false, + isFromGlobalCreate, + }); +} + function createDraftTransaction(transaction: OnyxTypes.Transaction) { if (!transaction) { return; @@ -6998,6 +7012,7 @@ export { detachReceipt, editMoneyRequest, initMoneyRequest, + resetMoneyRequest, navigateToStartStepIfScanFileCannotBeRead, payMoneyRequest, payInvoice, diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 44f3c1b6a1bc..d576f0b5546c 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -96,6 +96,11 @@ function IOURequestStartPage({ if (transaction?.reportID === reportID) { return; } + // if transaction is from global create, reset the reportID & participant + if (transaction?.isFromGlobalCreate && transaction.transactionID) { + IOU.resetMoneyRequest(transaction.transactionID, reportID, isFromGlobalCreate); + return; + } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, transactionRequestType.current); }, [transaction, policy, reportID, iouType, isFromGlobalCreate]); @@ -109,9 +114,12 @@ function IOURequestStartPage({ const resetIOUTypeIfChanged = useCallback( (newIOUType: IOURequestType) => { + if (transaction?.iouRequestType === newIOUType) { + return; + } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, newIOUType); }, - [policy, reportID, isFromGlobalCreate], + [policy, reportID, isFromGlobalCreate, transaction?.iouRequestType], ); if (!transaction?.transactionID) { diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index ea03c9ae3b06..00f43f0c8a63 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -189,7 +189,8 @@ function IOURequestStepConfirmation({ // If there is not a report attached to the IOU with a reportID, then the participants were manually selected and the user needs taken // back to the participants step if (!transaction?.participantsAutoAssigned) { - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID, undefined, action)); + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, transaction?.reportID || reportID, undefined, action)); return; } IOUUtils.navigateToStartMoneyRequestStep(requestType, iouType, transactionID, reportID, action); From 5cd9f11a5623df8ad537161467d63728c3f3cd25 Mon Sep 17 00:00:00 2001 From: dominictb Date: Wed, 26 Jun 2024 19:16:38 +0700 Subject: [PATCH 02/12] fix: update explanation comment Signed-off-by: dominictb --- src/libs/actions/IOU.ts | 8 +++++--- src/pages/iou/request/IOURequestStartPage.tsx | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 89ee7bcd2cdf..479620b29491 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -365,11 +365,13 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, } /** - * + * Reset the money request with a new report ID. Unlike the initMoneyRequest function, this function only + * set the new report ID (and isFromGlobalCreate flag) and reset the participants of the draft transaction * @param transactionID * @param reportID + * @param isFromGlobalCreate */ -function resetMoneyRequest(transactionID: string, reportID: string, isFromGlobalCreate: boolean) { +function resetMoneyRequestReportID(transactionID: string, reportID: string, isFromGlobalCreate: boolean) { Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, { reportID, participants: [], @@ -7010,7 +7012,7 @@ export { detachReceipt, editMoneyRequest, initMoneyRequest, - resetMoneyRequest, + resetMoneyRequestReportID, navigateToStartStepIfScanFileCannotBeRead, payMoneyRequest, payInvoice, diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index d576f0b5546c..8f72e5f455fd 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -96,9 +96,10 @@ function IOURequestStartPage({ if (transaction?.reportID === reportID) { return; } - // if transaction is from global create, reset the reportID & participant + // if transaction is from global create, the original behavior is that the user can change the recipient reportID + // without having to reset the whole transaction, hence we don't need to re-init the transaction in this case if (transaction?.isFromGlobalCreate && transaction.transactionID) { - IOU.resetMoneyRequest(transaction.transactionID, reportID, isFromGlobalCreate); + IOU.resetMoneyRequestReportID(transaction.transactionID, reportID, isFromGlobalCreate); return; } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, transactionRequestType.current); From da444431be049112050d955b19537370b51cf13b Mon Sep 17 00:00:00 2001 From: dominictb Date: Mon, 1 Jul 2024 16:43:00 +0700 Subject: [PATCH 03/12] fix: navigate to scan page instead of start page --- src/libs/actions/IOU.ts | 22 ++--------- src/pages/iou/request/IOURequestStartPage.tsx | 6 --- .../step/IOURequestStepConfirmation.tsx | 38 +++++++++++-------- .../step/IOURequestStepParticipants.tsx | 30 ++++++++++++--- 4 files changed, 50 insertions(+), 46 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 479620b29491..0b119c8cae09 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -364,22 +364,6 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, }); } -/** - * Reset the money request with a new report ID. Unlike the initMoneyRequest function, this function only - * set the new report ID (and isFromGlobalCreate flag) and reset the participants of the draft transaction - * @param transactionID - * @param reportID - * @param isFromGlobalCreate - */ -function resetMoneyRequestReportID(transactionID: string, reportID: string, isFromGlobalCreate: boolean) { - Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, { - reportID, - participants: [], - participantsAutoAssigned: false, - isFromGlobalCreate, - }); -} - function createDraftTransaction(transaction: OnyxTypes.Transaction) { if (!transaction) { return; @@ -6970,6 +6954,7 @@ function navigateToStartStepIfScanFileCannotBeRead( transactionID: string, reportID: string, receiptType: string | undefined, + backToParam?: string, ) { if (!receiptFilename || !receiptPath) { return; @@ -6977,8 +6962,8 @@ function navigateToStartStepIfScanFileCannotBeRead( const onFailure = () => { setMoneyRequestReceipt(transactionID, '', '', true); - if (requestType === CONST.IOU.REQUEST_TYPE.MANUAL) { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams())); + if (requestType === CONST.IOU.REQUEST_TYPE.MANUAL || requestType === CONST.IOU.REQUEST_TYPE.SCAN) { + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToParam ?? Navigation.getActiveRouteWithoutParams())); return; } IOUUtils.navigateToStartMoneyRequestStep(requestType, iouType, transactionID, reportID); @@ -7012,7 +6997,6 @@ export { detachReceipt, editMoneyRequest, initMoneyRequest, - resetMoneyRequestReportID, navigateToStartStepIfScanFileCannotBeRead, payMoneyRequest, payInvoice, diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 8f72e5f455fd..67e8f568f339 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -96,12 +96,6 @@ function IOURequestStartPage({ if (transaction?.reportID === reportID) { return; } - // if transaction is from global create, the original behavior is that the user can change the recipient reportID - // without having to reset the whole transaction, hence we don't need to re-init the transaction in this case - if (transaction?.isFromGlobalCreate && transaction.transactionID) { - IOU.resetMoneyRequestReportID(transaction.transactionID, reportID, isFromGlobalCreate); - return; - } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, transactionRequestType.current); }, [transaction, policy, reportID, iouType, isFromGlobalCreate]); diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 00f43f0c8a63..8f11f8e4e312 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -1,3 +1,4 @@ +import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; @@ -202,25 +203,32 @@ function IOURequestStepConfirmation({ // When the component mounts, if there is a receipt, see if the image can be read from the disk. If not, redirect the user to the starting step of the flow. // This is because until the request is saved, the receipt file is only stored in the browsers memory as a blob:// and if the browser is refreshed, then - // the image ceases to exist. The best way for the user to recover from this is to start over from the start of the request process. + // the image ceases to exist. We will navigate to the user to the scanning page and resume the flow once the user has re-uploaded the file // skip this in case user is moving the transaction as the receipt path will be valid in that case - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const isLocalFile = FileUtils.isLocalFile(receiptPath); + useFocusEffect( + useCallback(() => { + const backToParam = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, reportID); + if (!receiptPath && requestType === CONST.IOU.REQUEST_TYPE.SCAN) { + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToParam)); + return; + } + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const isLocalFile = FileUtils.isLocalFile(receiptPath); - if (!isLocalFile) { - setReceiptFile(transaction?.receipt); - return; - } + if (!isLocalFile) { + setReceiptFile(transaction?.receipt); + return; + } - const onSuccess = (file: File) => { - const receipt: Receipt = file; - receipt.state = file && requestType === CONST.IOU.REQUEST_TYPE.MANUAL ? CONST.IOU.RECEIPT_STATE.OPEN : CONST.IOU.RECEIPT_STATE.SCANREADY; - setReceiptFile(receipt); - }; + const onSuccess = (file: File) => { + const receipt: Receipt = file; + receipt.state = file && requestType === CONST.IOU.REQUEST_TYPE.MANUAL ? CONST.IOU.RECEIPT_STATE.OPEN : CONST.IOU.RECEIPT_STATE.SCANREADY; + setReceiptFile(receipt); + }; - IOU.navigateToStartStepIfScanFileCannotBeRead(receiptFilename, receiptPath, onSuccess, requestType, iouType, transactionID, reportID, receiptType); - }, [receiptType, receiptPath, receiptFilename, requestType, iouType, transactionID, reportID, action, transaction?.receipt]); + IOU.navigateToStartStepIfScanFileCannotBeRead(receiptFilename, receiptPath, onSuccess, requestType, iouType, transactionID, reportID, receiptType, backToParam); + }, [receiptType, receiptPath, receiptFilename, requestType, iouType, transactionID, reportID, action, transaction?.receipt]), + ); const requestMoney = useCallback( (selectedParticipants: Participant[], trimmedComment: string, receiptObj?: Receipt, gpsPoints?: IOU.GpsPoint) => { diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index 7fbc8d260f8a..a281025df479 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -1,4 +1,5 @@ import {useIsFocused} from '@react-navigation/core'; +import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useMemo, useRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; @@ -81,12 +82,29 @@ function IOURequestStepParticipants({ // This is because until the expense is saved, the receipt file is only stored in the browsers memory as a blob:// and if the browser is refreshed, then // the image ceases to exist. The best way for the user to recover from this is to start over from the start of the expense process. // skip this in case user is moving the transaction as the receipt path will be valid in that case - useEffect(() => { - if (IOUUtils.isMovingTransactionFromTrackExpense(action)) { - return; - } - IOU.navigateToStartStepIfScanFileCannotBeRead(receiptFilename ?? '', receiptPath ?? '', () => {}, iouRequestType, iouType, transactionID, reportID, receiptType ?? ''); - }, [receiptType, receiptPath, receiptFilename, iouRequestType, iouType, transactionID, reportID, action]); + useFocusEffect( + useCallback(() => { + if (IOUUtils.isMovingTransactionFromTrackExpense(action)) { + return; + } + const backToParam = ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID, action); + if (!receiptPath && iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN) { + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToParam)); + return; + } + IOU.navigateToStartStepIfScanFileCannotBeRead( + receiptFilename ?? '', + receiptPath ?? '', + () => {}, + iouRequestType, + iouType, + transactionID, + reportID, + receiptType ?? '', + backToParam, + ); + }, [receiptType, receiptPath, receiptFilename, iouRequestType, iouType, transactionID, reportID, action]), + ); const addParticipant = useCallback( (val: Participant[]) => { From c857885f0747880c66048c135e0d1166144ae5c4 Mon Sep 17 00:00:00 2001 From: dominictb Date: Fri, 5 Jul 2024 16:15:55 +0700 Subject: [PATCH 04/12] fix: move the user back to start page if no receipt upload Signed-off-by: dominictb --- .../step/IOURequestStepConfirmation.tsx | 6 +- .../step/IOURequestStepParticipants.tsx | 4 +- .../step/IOURequestStepScan/index.native.tsx | 45 +++----- .../request/step/IOURequestStepScan/index.tsx | 45 +++----- .../useNavigateToNextStepAfterScan.tsx | 101 ++++++++++++++++++ 5 files changed, 134 insertions(+), 67 deletions(-) create mode 100644 src/pages/iou/request/step/IOURequestStepScan/useNavigateToNextStepAfterScan.tsx diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 8f11f8e4e312..1deec76b0e58 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -207,9 +207,8 @@ function IOURequestStepConfirmation({ // skip this in case user is moving the transaction as the receipt path will be valid in that case useFocusEffect( useCallback(() => { - const backToParam = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, reportID); if (!receiptPath && requestType === CONST.IOU.REQUEST_TYPE.SCAN) { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToParam)); + Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(action, iouType, transactionID, transaction?.reportID ?? reportID), true); return; } // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -226,8 +225,9 @@ function IOURequestStepConfirmation({ setReceiptFile(receipt); }; + const backToParam = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, reportID); IOU.navigateToStartStepIfScanFileCannotBeRead(receiptFilename, receiptPath, onSuccess, requestType, iouType, transactionID, reportID, receiptType, backToParam); - }, [receiptType, receiptPath, receiptFilename, requestType, iouType, transactionID, reportID, action, transaction?.receipt]), + }, [receiptType, receiptPath, receiptFilename, requestType, iouType, transactionID, reportID, action, transaction?.receipt, transaction?.reportID]), ); const requestMoney = useCallback( diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index a281025df479..8ead9f63d9a6 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -87,11 +87,11 @@ function IOURequestStepParticipants({ if (IOUUtils.isMovingTransactionFromTrackExpense(action)) { return; } - const backToParam = ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID, action); if (!receiptPath && iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN) { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToParam)); + Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(action, iouType, transactionID, reportID), true); return; } + const backToParam = ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID, action); IOU.navigateToStartStepIfScanFileCannotBeRead( receiptFilename ?? '', receiptPath ?? '', diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 056a03b3b8f5..bb3e46ca619e 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -35,11 +35,11 @@ import withWritableReportOrNotFound from '@pages/iou/request/step/withWritableRe import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; import type {Receipt} from '@src/types/onyx/Transaction'; import CameraPermission from './CameraPermission'; import NavigationAwareCamera from './NavigationAwareCamera/Camera'; import type {IOURequestStepOnyxProps, IOURequestStepScanProps} from './types'; +import useNavigateToNextStepAfterScan from './useNavigateToNextStepAfterScan'; function IOURequestStepScan({ report, @@ -188,42 +188,24 @@ function IOURequestStepScan({ Navigation.goBack(); }; - const navigateToParticipantPage = useCallback(() => { - switch (iouType) { - case CONST.IOU.TYPE.REQUEST: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); - break; - case CONST.IOU.TYPE.SEND: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.PAY, transactionID, reportID)); - break; - default: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID)); - } - }, [iouType, reportID, transactionID]); - - const navigateToConfirmationPage = useCallback(() => { - switch (iouType) { - case CONST.IOU.TYPE.REQUEST: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); - break; - case CONST.IOU.TYPE.SEND: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.PAY, transactionID, reportID)); - break; - default: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); - } - }, [iouType, reportID, transactionID]); + const {moveBackToOriginalPage, moveToParticipantSelectionStep, moveToConfirmationStep} = useNavigateToNextStepAfterScan({ + transaction, + reportID, + iouType, + transactionID, + backTo, + }); const navigateToConfirmationStep = useCallback( (file: FileObject, source: string) => { if (backTo) { - Navigation.goBack(backTo); + moveBackToOriginalPage(file, source); return; } // If the transaction was created from the global create, the person needs to select participants, so take them there. if (transaction?.isFromGlobalCreate && iouType !== CONST.IOU.TYPE.TRACK && !report?.reportID) { - navigateToParticipantPage(); + moveToParticipantSelectionStep(file, source); return; } @@ -348,7 +330,7 @@ function IOURequestStepScan({ ); return; } - navigateToConfirmationPage(); + moveToConfirmationStep(file, source); }, [ iouType, @@ -360,8 +342,9 @@ function IOURequestStepScan({ personalDetails, shouldSkipConfirmation, transaction, - navigateToConfirmationPage, - navigateToParticipantPage, + moveBackToOriginalPage, + moveToConfirmationStep, + moveToParticipantSelectionStep, policy, transactionTaxCode, transactionTaxAmount, diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 00e0e14ee27c..3ce238321a45 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -39,11 +39,11 @@ import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; import type {Receipt} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import NavigationAwareCamera from './NavigationAwareCamera/WebCamera'; import type {IOURequestStepOnyxProps, IOURequestStepScanProps} from './types'; +import useNavigateToNextStepAfterScan from './useNavigateToNextStepAfterScan'; function IOURequestStepScan({ report, @@ -234,42 +234,24 @@ function IOURequestStepScan({ Navigation.goBack(backTo); }; - const navigateToParticipantPage = useCallback(() => { - switch (iouType) { - case CONST.IOU.TYPE.REQUEST: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); - break; - case CONST.IOU.TYPE.SEND: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.PAY, transactionID, reportID)); - break; - default: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID)); - } - }, [iouType, reportID, transactionID]); - - const navigateToConfirmationPage = useCallback(() => { - switch (iouType) { - case CONST.IOU.TYPE.REQUEST: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); - break; - case CONST.IOU.TYPE.SEND: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.PAY, transactionID, reportID)); - break; - default: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); - } - }, [iouType, reportID, transactionID]); + const {moveBackToOriginalPage, moveToParticipantSelectionStep, moveToConfirmationStep} = useNavigateToNextStepAfterScan({ + transaction, + reportID, + iouType, + transactionID, + backTo, + }); const navigateToConfirmationStep = useCallback( (file: FileObject, source: string) => { if (backTo) { - Navigation.goBack(backTo); + moveBackToOriginalPage(file, source); return; } // If the transaction was created from the global create, the person needs to select participants, so take them there. if (transaction?.isFromGlobalCreate && iouType !== CONST.IOU.TYPE.TRACK && !report?.reportID) { - navigateToParticipantPage(); + moveToParticipantSelectionStep(file, source); return; } @@ -394,7 +376,7 @@ function IOURequestStepScan({ ); return; } - navigateToConfirmationPage(); + moveToConfirmationStep(file, source); }, [ iouType, @@ -406,8 +388,9 @@ function IOURequestStepScan({ personalDetails, shouldSkipConfirmation, transaction, - navigateToConfirmationPage, - navigateToParticipantPage, + moveToConfirmationStep, + moveToParticipantSelectionStep, + moveBackToOriginalPage, policy, transactionTaxCode, transactionTaxAmount, diff --git a/src/pages/iou/request/step/IOURequestStepScan/useNavigateToNextStepAfterScan.tsx b/src/pages/iou/request/step/IOURequestStepScan/useNavigateToNextStepAfterScan.tsx new file mode 100644 index 000000000000..279f18dfaf4e --- /dev/null +++ b/src/pages/iou/request/step/IOURequestStepScan/useNavigateToNextStepAfterScan.tsx @@ -0,0 +1,101 @@ +import {useCallback, useEffect, useState} from 'react'; +import type {FileObject} from '@components/AttachmentModal'; +import Navigation from '@libs/Navigation/Navigation'; +import type {IOUType} from '@src/CONST'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; +import type {Route} from '@src/ROUTES'; +import type {IOURequestStepScanProps} from './types'; + +type UseNavigateToNextStepAfterScanParams = { + transaction: IOURequestStepScanProps['transaction']; + reportID: string; + transactionID: string; + backTo: Route; + iouType: IOUType; +}; + +/** + * This is a shared hook to navigate to next step after uploading a receipt + * The idea is to ensure the transaction in Onyx state is updated with uploaded file and source before navigating to the next step + * to avoid the check for missing receipt in the next step. + * + * In order to achieve that, we will set the uploadedFile and uploadedSource in the state + * and install a useEffect to match the uploaded state with the transaction data. Once the uploaded state matches the transaction data, it indicates + * that the uploadedFile and uploadedSource has been updated in the transaction data and we can navigate to the next step. + */ +const useNavigateToNextStepAfterScan = ({transaction, reportID, transactionID, backTo, iouType}: UseNavigateToNextStepAfterScanParams) => { + const [[uploadedFile, uploadedSource], setFileAndSource] = useState<[FileObject | null, string | null]>([null, null]); + const [destinationOption, setDestinationOption] = useState(0); + + const moveBackToOriginalPage = (file: FileObject, source: string) => { + setFileAndSource([file, source]); + setDestinationOption(1); + }; + const moveToParticipantSelectionStep = (file: FileObject, source: string) => { + setFileAndSource([file, source]); + setDestinationOption(2); + }; + const moveToConfirmationStep = (file: FileObject, source: string) => { + setFileAndSource([file, source]); + setDestinationOption(3); + }; + + const navigateToParticipantPage = useCallback(() => { + switch (iouType) { + case CONST.IOU.TYPE.REQUEST: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); + break; + case CONST.IOU.TYPE.SEND: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.PAY, transactionID, reportID)); + break; + default: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID)); + } + }, [iouType, reportID, transactionID]); + + const navigateToConfirmationPage = useCallback(() => { + switch (iouType) { + case CONST.IOU.TYPE.REQUEST: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); + break; + case CONST.IOU.TYPE.SEND: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.PAY, transactionID, reportID)); + break; + default: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); + } + }, [iouType, reportID, transactionID]); + + const resetState = useCallback(() => { + setDestinationOption(0); + setFileAndSource([null, null]); + }, []); + + useEffect(() => { + if (!uploadedFile?.name || !uploadedSource || transaction?.filename !== uploadedFile.name || transaction?.receipt?.source !== uploadedSource) { + return; + } + // reset state, indicating that the navigation has been completed + resetState(); + + // navigate based on destination option + if (destinationOption === 1) { + Navigation.goBack(backTo); + return; + } + + if (destinationOption === 2) { + navigateToParticipantPage(); + return; + } + + if (destinationOption === 3) { + navigateToConfirmationPage(); + } + }, [transaction, uploadedFile, uploadedSource, navigateToParticipantPage, navigateToConfirmationPage, destinationOption, resetState, backTo]); + + return {moveBackToOriginalPage, moveToParticipantSelectionStep, moveToConfirmationStep}; +}; + +export default useNavigateToNextStepAfterScan; From 26dd780b3ddd34304392503915874113f00b629e Mon Sep 17 00:00:00 2001 From: dominictb Date: Wed, 10 Jul 2024 14:43:17 +0700 Subject: [PATCH 05/12] Revert "fix: move the user back to start page if no receipt upload" This reverts commit c857885f0747880c66048c135e0d1166144ae5c4. --- .../step/IOURequestStepConfirmation.tsx | 6 +- .../step/IOURequestStepParticipants.tsx | 4 +- .../step/IOURequestStepScan/index.native.tsx | 45 +++++--- .../request/step/IOURequestStepScan/index.tsx | 45 +++++--- .../useNavigateToNextStepAfterScan.tsx | 101 ------------------ 5 files changed, 67 insertions(+), 134 deletions(-) delete mode 100644 src/pages/iou/request/step/IOURequestStepScan/useNavigateToNextStepAfterScan.tsx diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 1deec76b0e58..8f11f8e4e312 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -207,8 +207,9 @@ function IOURequestStepConfirmation({ // skip this in case user is moving the transaction as the receipt path will be valid in that case useFocusEffect( useCallback(() => { + const backToParam = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, reportID); if (!receiptPath && requestType === CONST.IOU.REQUEST_TYPE.SCAN) { - Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(action, iouType, transactionID, transaction?.reportID ?? reportID), true); + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToParam)); return; } // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing @@ -225,9 +226,8 @@ function IOURequestStepConfirmation({ setReceiptFile(receipt); }; - const backToParam = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, reportID); IOU.navigateToStartStepIfScanFileCannotBeRead(receiptFilename, receiptPath, onSuccess, requestType, iouType, transactionID, reportID, receiptType, backToParam); - }, [receiptType, receiptPath, receiptFilename, requestType, iouType, transactionID, reportID, action, transaction?.receipt, transaction?.reportID]), + }, [receiptType, receiptPath, receiptFilename, requestType, iouType, transactionID, reportID, action, transaction?.receipt]), ); const requestMoney = useCallback( diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index 8ead9f63d9a6..a281025df479 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -87,11 +87,11 @@ function IOURequestStepParticipants({ if (IOUUtils.isMovingTransactionFromTrackExpense(action)) { return; } + const backToParam = ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID, action); if (!receiptPath && iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN) { - Navigation.goBack(ROUTES.MONEY_REQUEST_CREATE_TAB_SCAN.getRoute(action, iouType, transactionID, reportID), true); + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToParam)); return; } - const backToParam = ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID, action); IOU.navigateToStartStepIfScanFileCannotBeRead( receiptFilename ?? '', receiptPath ?? '', diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index bb3e46ca619e..056a03b3b8f5 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -35,11 +35,11 @@ import withWritableReportOrNotFound from '@pages/iou/request/step/withWritableRe import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type {Receipt} from '@src/types/onyx/Transaction'; import CameraPermission from './CameraPermission'; import NavigationAwareCamera from './NavigationAwareCamera/Camera'; import type {IOURequestStepOnyxProps, IOURequestStepScanProps} from './types'; -import useNavigateToNextStepAfterScan from './useNavigateToNextStepAfterScan'; function IOURequestStepScan({ report, @@ -188,24 +188,42 @@ function IOURequestStepScan({ Navigation.goBack(); }; - const {moveBackToOriginalPage, moveToParticipantSelectionStep, moveToConfirmationStep} = useNavigateToNextStepAfterScan({ - transaction, - reportID, - iouType, - transactionID, - backTo, - }); + const navigateToParticipantPage = useCallback(() => { + switch (iouType) { + case CONST.IOU.TYPE.REQUEST: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); + break; + case CONST.IOU.TYPE.SEND: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.PAY, transactionID, reportID)); + break; + default: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID)); + } + }, [iouType, reportID, transactionID]); + + const navigateToConfirmationPage = useCallback(() => { + switch (iouType) { + case CONST.IOU.TYPE.REQUEST: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); + break; + case CONST.IOU.TYPE.SEND: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.PAY, transactionID, reportID)); + break; + default: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); + } + }, [iouType, reportID, transactionID]); const navigateToConfirmationStep = useCallback( (file: FileObject, source: string) => { if (backTo) { - moveBackToOriginalPage(file, source); + Navigation.goBack(backTo); return; } // If the transaction was created from the global create, the person needs to select participants, so take them there. if (transaction?.isFromGlobalCreate && iouType !== CONST.IOU.TYPE.TRACK && !report?.reportID) { - moveToParticipantSelectionStep(file, source); + navigateToParticipantPage(); return; } @@ -330,7 +348,7 @@ function IOURequestStepScan({ ); return; } - moveToConfirmationStep(file, source); + navigateToConfirmationPage(); }, [ iouType, @@ -342,9 +360,8 @@ function IOURequestStepScan({ personalDetails, shouldSkipConfirmation, transaction, - moveBackToOriginalPage, - moveToConfirmationStep, - moveToParticipantSelectionStep, + navigateToConfirmationPage, + navigateToParticipantPage, policy, transactionTaxCode, transactionTaxAmount, diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 3ce238321a45..00e0e14ee27c 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -39,11 +39,11 @@ import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type {Receipt} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import NavigationAwareCamera from './NavigationAwareCamera/WebCamera'; import type {IOURequestStepOnyxProps, IOURequestStepScanProps} from './types'; -import useNavigateToNextStepAfterScan from './useNavigateToNextStepAfterScan'; function IOURequestStepScan({ report, @@ -234,24 +234,42 @@ function IOURequestStepScan({ Navigation.goBack(backTo); }; - const {moveBackToOriginalPage, moveToParticipantSelectionStep, moveToConfirmationStep} = useNavigateToNextStepAfterScan({ - transaction, - reportID, - iouType, - transactionID, - backTo, - }); + const navigateToParticipantPage = useCallback(() => { + switch (iouType) { + case CONST.IOU.TYPE.REQUEST: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); + break; + case CONST.IOU.TYPE.SEND: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.PAY, transactionID, reportID)); + break; + default: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID)); + } + }, [iouType, reportID, transactionID]); + + const navigateToConfirmationPage = useCallback(() => { + switch (iouType) { + case CONST.IOU.TYPE.REQUEST: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); + break; + case CONST.IOU.TYPE.SEND: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.PAY, transactionID, reportID)); + break; + default: + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); + } + }, [iouType, reportID, transactionID]); const navigateToConfirmationStep = useCallback( (file: FileObject, source: string) => { if (backTo) { - moveBackToOriginalPage(file, source); + Navigation.goBack(backTo); return; } // If the transaction was created from the global create, the person needs to select participants, so take them there. if (transaction?.isFromGlobalCreate && iouType !== CONST.IOU.TYPE.TRACK && !report?.reportID) { - moveToParticipantSelectionStep(file, source); + navigateToParticipantPage(); return; } @@ -376,7 +394,7 @@ function IOURequestStepScan({ ); return; } - moveToConfirmationStep(file, source); + navigateToConfirmationPage(); }, [ iouType, @@ -388,9 +406,8 @@ function IOURequestStepScan({ personalDetails, shouldSkipConfirmation, transaction, - moveToConfirmationStep, - moveToParticipantSelectionStep, - moveBackToOriginalPage, + navigateToConfirmationPage, + navigateToParticipantPage, policy, transactionTaxCode, transactionTaxAmount, diff --git a/src/pages/iou/request/step/IOURequestStepScan/useNavigateToNextStepAfterScan.tsx b/src/pages/iou/request/step/IOURequestStepScan/useNavigateToNextStepAfterScan.tsx deleted file mode 100644 index 279f18dfaf4e..000000000000 --- a/src/pages/iou/request/step/IOURequestStepScan/useNavigateToNextStepAfterScan.tsx +++ /dev/null @@ -1,101 +0,0 @@ -import {useCallback, useEffect, useState} from 'react'; -import type {FileObject} from '@components/AttachmentModal'; -import Navigation from '@libs/Navigation/Navigation'; -import type {IOUType} from '@src/CONST'; -import CONST from '@src/CONST'; -import ROUTES from '@src/ROUTES'; -import type {Route} from '@src/ROUTES'; -import type {IOURequestStepScanProps} from './types'; - -type UseNavigateToNextStepAfterScanParams = { - transaction: IOURequestStepScanProps['transaction']; - reportID: string; - transactionID: string; - backTo: Route; - iouType: IOUType; -}; - -/** - * This is a shared hook to navigate to next step after uploading a receipt - * The idea is to ensure the transaction in Onyx state is updated with uploaded file and source before navigating to the next step - * to avoid the check for missing receipt in the next step. - * - * In order to achieve that, we will set the uploadedFile and uploadedSource in the state - * and install a useEffect to match the uploaded state with the transaction data. Once the uploaded state matches the transaction data, it indicates - * that the uploadedFile and uploadedSource has been updated in the transaction data and we can navigate to the next step. - */ -const useNavigateToNextStepAfterScan = ({transaction, reportID, transactionID, backTo, iouType}: UseNavigateToNextStepAfterScanParams) => { - const [[uploadedFile, uploadedSource], setFileAndSource] = useState<[FileObject | null, string | null]>([null, null]); - const [destinationOption, setDestinationOption] = useState(0); - - const moveBackToOriginalPage = (file: FileObject, source: string) => { - setFileAndSource([file, source]); - setDestinationOption(1); - }; - const moveToParticipantSelectionStep = (file: FileObject, source: string) => { - setFileAndSource([file, source]); - setDestinationOption(2); - }; - const moveToConfirmationStep = (file: FileObject, source: string) => { - setFileAndSource([file, source]); - setDestinationOption(3); - }; - - const navigateToParticipantPage = useCallback(() => { - switch (iouType) { - case CONST.IOU.TYPE.REQUEST: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); - break; - case CONST.IOU.TYPE.SEND: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(CONST.IOU.TYPE.PAY, transactionID, reportID)); - break; - default: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID)); - } - }, [iouType, reportID, transactionID]); - - const navigateToConfirmationPage = useCallback(() => { - switch (iouType) { - case CONST.IOU.TYPE.REQUEST: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.SUBMIT, transactionID, reportID)); - break; - case CONST.IOU.TYPE.SEND: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, CONST.IOU.TYPE.PAY, transactionID, reportID)); - break; - default: - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID)); - } - }, [iouType, reportID, transactionID]); - - const resetState = useCallback(() => { - setDestinationOption(0); - setFileAndSource([null, null]); - }, []); - - useEffect(() => { - if (!uploadedFile?.name || !uploadedSource || transaction?.filename !== uploadedFile.name || transaction?.receipt?.source !== uploadedSource) { - return; - } - // reset state, indicating that the navigation has been completed - resetState(); - - // navigate based on destination option - if (destinationOption === 1) { - Navigation.goBack(backTo); - return; - } - - if (destinationOption === 2) { - navigateToParticipantPage(); - return; - } - - if (destinationOption === 3) { - navigateToConfirmationPage(); - } - }, [transaction, uploadedFile, uploadedSource, navigateToParticipantPage, navigateToConfirmationPage, destinationOption, resetState, backTo]); - - return {moveBackToOriginalPage, moveToParticipantSelectionStep, moveToConfirmationStep}; -}; - -export default useNavigateToNextStepAfterScan; From fc9721d3da145bfd246f3ecf386b1253c7d4875e Mon Sep 17 00:00:00 2001 From: dominictb Date: Wed, 10 Jul 2024 14:43:34 +0700 Subject: [PATCH 06/12] Revert "fix: navigate to scan page instead of start page" This reverts commit da444431be049112050d955b19537370b51cf13b. --- src/libs/actions/IOU.ts | 22 +++++++++-- src/pages/iou/request/IOURequestStartPage.tsx | 6 +++ .../step/IOURequestStepConfirmation.tsx | 38 ++++++++----------- .../step/IOURequestStepParticipants.tsx | 30 +++------------ 4 files changed, 46 insertions(+), 50 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 0b119c8cae09..479620b29491 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -364,6 +364,22 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, }); } +/** + * Reset the money request with a new report ID. Unlike the initMoneyRequest function, this function only + * set the new report ID (and isFromGlobalCreate flag) and reset the participants of the draft transaction + * @param transactionID + * @param reportID + * @param isFromGlobalCreate + */ +function resetMoneyRequestReportID(transactionID: string, reportID: string, isFromGlobalCreate: boolean) { + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, { + reportID, + participants: [], + participantsAutoAssigned: false, + isFromGlobalCreate, + }); +} + function createDraftTransaction(transaction: OnyxTypes.Transaction) { if (!transaction) { return; @@ -6954,7 +6970,6 @@ function navigateToStartStepIfScanFileCannotBeRead( transactionID: string, reportID: string, receiptType: string | undefined, - backToParam?: string, ) { if (!receiptFilename || !receiptPath) { return; @@ -6962,8 +6977,8 @@ function navigateToStartStepIfScanFileCannotBeRead( const onFailure = () => { setMoneyRequestReceipt(transactionID, '', '', true); - if (requestType === CONST.IOU.REQUEST_TYPE.MANUAL || requestType === CONST.IOU.REQUEST_TYPE.SCAN) { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToParam ?? Navigation.getActiveRouteWithoutParams())); + if (requestType === CONST.IOU.REQUEST_TYPE.MANUAL) { + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, Navigation.getActiveRouteWithoutParams())); return; } IOUUtils.navigateToStartMoneyRequestStep(requestType, iouType, transactionID, reportID); @@ -6997,6 +7012,7 @@ export { detachReceipt, editMoneyRequest, initMoneyRequest, + resetMoneyRequestReportID, navigateToStartStepIfScanFileCannotBeRead, payMoneyRequest, payInvoice, diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 67e8f568f339..8f72e5f455fd 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -96,6 +96,12 @@ function IOURequestStartPage({ if (transaction?.reportID === reportID) { return; } + // if transaction is from global create, the original behavior is that the user can change the recipient reportID + // without having to reset the whole transaction, hence we don't need to re-init the transaction in this case + if (transaction?.isFromGlobalCreate && transaction.transactionID) { + IOU.resetMoneyRequestReportID(transaction.transactionID, reportID, isFromGlobalCreate); + return; + } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, transactionRequestType.current); }, [transaction, policy, reportID, iouType, isFromGlobalCreate]); diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 8f11f8e4e312..00f43f0c8a63 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -1,4 +1,3 @@ -import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; @@ -203,32 +202,25 @@ function IOURequestStepConfirmation({ // When the component mounts, if there is a receipt, see if the image can be read from the disk. If not, redirect the user to the starting step of the flow. // This is because until the request is saved, the receipt file is only stored in the browsers memory as a blob:// and if the browser is refreshed, then - // the image ceases to exist. We will navigate to the user to the scanning page and resume the flow once the user has re-uploaded the file + // the image ceases to exist. The best way for the user to recover from this is to start over from the start of the request process. // skip this in case user is moving the transaction as the receipt path will be valid in that case - useFocusEffect( - useCallback(() => { - const backToParam = ROUTES.MONEY_REQUEST_STEP_CONFIRMATION.getRoute(action, iouType, transactionID, reportID); - if (!receiptPath && requestType === CONST.IOU.REQUEST_TYPE.SCAN) { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToParam)); - return; - } - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const isLocalFile = FileUtils.isLocalFile(receiptPath); + useEffect(() => { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const isLocalFile = FileUtils.isLocalFile(receiptPath); - if (!isLocalFile) { - setReceiptFile(transaction?.receipt); - return; - } + if (!isLocalFile) { + setReceiptFile(transaction?.receipt); + return; + } - const onSuccess = (file: File) => { - const receipt: Receipt = file; - receipt.state = file && requestType === CONST.IOU.REQUEST_TYPE.MANUAL ? CONST.IOU.RECEIPT_STATE.OPEN : CONST.IOU.RECEIPT_STATE.SCANREADY; - setReceiptFile(receipt); - }; + const onSuccess = (file: File) => { + const receipt: Receipt = file; + receipt.state = file && requestType === CONST.IOU.REQUEST_TYPE.MANUAL ? CONST.IOU.RECEIPT_STATE.OPEN : CONST.IOU.RECEIPT_STATE.SCANREADY; + setReceiptFile(receipt); + }; - IOU.navigateToStartStepIfScanFileCannotBeRead(receiptFilename, receiptPath, onSuccess, requestType, iouType, transactionID, reportID, receiptType, backToParam); - }, [receiptType, receiptPath, receiptFilename, requestType, iouType, transactionID, reportID, action, transaction?.receipt]), - ); + IOU.navigateToStartStepIfScanFileCannotBeRead(receiptFilename, receiptPath, onSuccess, requestType, iouType, transactionID, reportID, receiptType); + }, [receiptType, receiptPath, receiptFilename, requestType, iouType, transactionID, reportID, action, transaction?.receipt]); const requestMoney = useCallback( (selectedParticipants: Participant[], trimmedComment: string, receiptObj?: Receipt, gpsPoints?: IOU.GpsPoint) => { diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.tsx b/src/pages/iou/request/step/IOURequestStepParticipants.tsx index a281025df479..7fbc8d260f8a 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.tsx +++ b/src/pages/iou/request/step/IOURequestStepParticipants.tsx @@ -1,5 +1,4 @@ import {useIsFocused} from '@react-navigation/core'; -import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useMemo, useRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; @@ -82,29 +81,12 @@ function IOURequestStepParticipants({ // This is because until the expense is saved, the receipt file is only stored in the browsers memory as a blob:// and if the browser is refreshed, then // the image ceases to exist. The best way for the user to recover from this is to start over from the start of the expense process. // skip this in case user is moving the transaction as the receipt path will be valid in that case - useFocusEffect( - useCallback(() => { - if (IOUUtils.isMovingTransactionFromTrackExpense(action)) { - return; - } - const backToParam = ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID, action); - if (!receiptPath && iouRequestType === CONST.IOU.REQUEST_TYPE.SCAN) { - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute(CONST.IOU.ACTION.CREATE, iouType, transactionID, reportID, backToParam)); - return; - } - IOU.navigateToStartStepIfScanFileCannotBeRead( - receiptFilename ?? '', - receiptPath ?? '', - () => {}, - iouRequestType, - iouType, - transactionID, - reportID, - receiptType ?? '', - backToParam, - ); - }, [receiptType, receiptPath, receiptFilename, iouRequestType, iouType, transactionID, reportID, action]), - ); + useEffect(() => { + if (IOUUtils.isMovingTransactionFromTrackExpense(action)) { + return; + } + IOU.navigateToStartStepIfScanFileCannotBeRead(receiptFilename ?? '', receiptPath ?? '', () => {}, iouRequestType, iouType, transactionID, reportID, receiptType ?? ''); + }, [receiptType, receiptPath, receiptFilename, iouRequestType, iouType, transactionID, reportID, action]); const addParticipant = useCallback( (val: Participant[]) => { From 7cc38dec35821780782d38e8a4c50532cee2ef20 Mon Sep 17 00:00:00 2001 From: dominictb Date: Wed, 10 Jul 2024 14:44:48 +0700 Subject: [PATCH 07/12] Revert "fix: update explanation comment" This reverts commit 5cd9f11a5623df8ad537161467d63728c3f3cd25. --- src/libs/actions/IOU.ts | 8 +++----- src/pages/iou/request/IOURequestStartPage.tsx | 5 ++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 479620b29491..89ee7bcd2cdf 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -365,13 +365,11 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, } /** - * Reset the money request with a new report ID. Unlike the initMoneyRequest function, this function only - * set the new report ID (and isFromGlobalCreate flag) and reset the participants of the draft transaction + * * @param transactionID * @param reportID - * @param isFromGlobalCreate */ -function resetMoneyRequestReportID(transactionID: string, reportID: string, isFromGlobalCreate: boolean) { +function resetMoneyRequest(transactionID: string, reportID: string, isFromGlobalCreate: boolean) { Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, { reportID, participants: [], @@ -7012,7 +7010,7 @@ export { detachReceipt, editMoneyRequest, initMoneyRequest, - resetMoneyRequestReportID, + resetMoneyRequest, navigateToStartStepIfScanFileCannotBeRead, payMoneyRequest, payInvoice, diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 8f72e5f455fd..d576f0b5546c 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -96,10 +96,9 @@ function IOURequestStartPage({ if (transaction?.reportID === reportID) { return; } - // if transaction is from global create, the original behavior is that the user can change the recipient reportID - // without having to reset the whole transaction, hence we don't need to re-init the transaction in this case + // if transaction is from global create, reset the reportID & participant if (transaction?.isFromGlobalCreate && transaction.transactionID) { - IOU.resetMoneyRequestReportID(transaction.transactionID, reportID, isFromGlobalCreate); + IOU.resetMoneyRequest(transaction.transactionID, reportID, isFromGlobalCreate); return; } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, transactionRequestType.current); From e77ee51a3bedc7297bbff9c6db775ccad961d4e5 Mon Sep 17 00:00:00 2001 From: dominictb Date: Wed, 10 Jul 2024 14:45:15 +0700 Subject: [PATCH 08/12] Revert "fix: do not refresh draft txn after redirect" This reverts commit d10afcbc59b5d5ecbda2870000b6836266c107eb. --- src/libs/actions/IOU.ts | 15 --------------- src/pages/iou/request/IOURequestStartPage.tsx | 10 +--------- .../request/step/IOURequestStepConfirmation.tsx | 3 +-- 3 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 89ee7bcd2cdf..911e1d3cf99e 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -364,20 +364,6 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, }); } -/** - * - * @param transactionID - * @param reportID - */ -function resetMoneyRequest(transactionID: string, reportID: string, isFromGlobalCreate: boolean) { - Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, { - reportID, - participants: [], - participantsAutoAssigned: false, - isFromGlobalCreate, - }); -} - function createDraftTransaction(transaction: OnyxTypes.Transaction) { if (!transaction) { return; @@ -7010,7 +6996,6 @@ export { detachReceipt, editMoneyRequest, initMoneyRequest, - resetMoneyRequest, navigateToStartStepIfScanFileCannotBeRead, payMoneyRequest, payInvoice, diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index d576f0b5546c..44f3c1b6a1bc 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -96,11 +96,6 @@ function IOURequestStartPage({ if (transaction?.reportID === reportID) { return; } - // if transaction is from global create, reset the reportID & participant - if (transaction?.isFromGlobalCreate && transaction.transactionID) { - IOU.resetMoneyRequest(transaction.transactionID, reportID, isFromGlobalCreate); - return; - } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, transactionRequestType.current); }, [transaction, policy, reportID, iouType, isFromGlobalCreate]); @@ -114,12 +109,9 @@ function IOURequestStartPage({ const resetIOUTypeIfChanged = useCallback( (newIOUType: IOURequestType) => { - if (transaction?.iouRequestType === newIOUType) { - return; - } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, newIOUType); }, - [policy, reportID, isFromGlobalCreate, transaction?.iouRequestType], + [policy, reportID, isFromGlobalCreate], ); if (!transaction?.transactionID) { diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 00f43f0c8a63..ea03c9ae3b06 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -189,8 +189,7 @@ function IOURequestStepConfirmation({ // If there is not a report attached to the IOU with a reportID, then the participants were manually selected and the user needs taken // back to the participants step if (!transaction?.participantsAutoAssigned) { - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, transaction?.reportID || reportID, undefined, action)); + Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID, undefined, action)); return; } IOUUtils.navigateToStartMoneyRequestStep(requestType, iouType, transactionID, reportID, action); From e45629841bdef4473f5af5eeeb1300f4fc84a366 Mon Sep 17 00:00:00 2001 From: dominictb Date: Wed, 10 Jul 2024 17:00:10 +0700 Subject: [PATCH 09/12] fix: add a flag to keep the existing draft txn data during initMoneyRequest Signed-off-by: dominictb --- src/libs/actions/IOU.ts | 20 ++++++++++++++++--- src/pages/iou/request/IOURequestStartPage.tsx | 12 +++++++---- .../step/IOURequestStepConfirmation.tsx | 3 ++- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index df199a2a36ae..a7c562a99540 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -321,15 +321,29 @@ function getReportPreviewAction(chatReportID: string, iouReportID: string): Onyx * @param reportID to attach the transaction to * @param policy * @param isFromGlobalCreate + * @param shouldKeepExistingData * @param iouRequestType one of manual/scan/distance - * @param skipConfirmation if true, skip confirmation step */ -function initMoneyRequest(reportID: string, policy: OnyxEntry, isFromGlobalCreate: boolean, iouRequestType: IOURequestType = CONST.IOU.REQUEST_TYPE.MANUAL) { +function initMoneyRequest(reportID: string, policy: OnyxEntry, isFromGlobalCreate: boolean, shouldKeepExistingData: boolean, iouRequestType: IOURequestType = CONST.IOU.REQUEST_TYPE.MANUAL) { // Generate a brand new transactionID const newTransactionID = CONST.IOU.OPTIMISTIC_TRANSACTION_ID; + const currency = policy?.outputCurrency ?? currentUserPersonalDetails?.localCurrencyCode ?? CONST.CURRENCY.USD; // Disabling this line since currentDate can be an empty string // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const created = currentDate || format(new Date(), 'yyyy-MM-dd'); + + // In case we should keep existing transaction data, we only need to update the reportID, isFromGlobalCreate, created and currency + if(shouldKeepExistingData) { + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${newTransactionID}`, { + reportID, + isFromGlobalCreate, + created, + currency, + transactionID: newTransactionID, + }) + return; + } + const comment: Comment = {}; // Add initial empty waypoints when starting a distance expense @@ -350,7 +364,7 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, amount: 0, comment, created, - currency: policy?.outputCurrency ?? currentUserPersonalDetails?.localCurrencyCode ?? CONST.CURRENCY.USD, + currency, iouRequestType, reportID, transactionID: newTransactionID, diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 44f3c1b6a1bc..d12c790ae743 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -93,10 +93,11 @@ function IOURequestStartPage({ // Clear out the temporary expense if the reportID in the URL has changed from the transaction's reportID useEffect(() => { - if (transaction?.reportID === reportID) { + if(transaction?.reportID === reportID) { return; } - IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, transactionRequestType.current); + const shouldKeepExistingData = !!transaction?.isFromGlobalCreate && transaction?.iouRequestType === transactionRequestType.current; + IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, shouldKeepExistingData, transactionRequestType.current); }, [transaction, policy, reportID, iouType, isFromGlobalCreate]); const isExpenseChat = ReportUtils.isPolicyExpenseChat(report); @@ -109,9 +110,12 @@ function IOURequestStartPage({ const resetIOUTypeIfChanged = useCallback( (newIOUType: IOURequestType) => { - IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, newIOUType); + if(transaction?.iouRequestType === newIOUType) { + return; + } + IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, false, newIOUType); }, - [policy, reportID, isFromGlobalCreate], + [policy, reportID, isFromGlobalCreate, transaction], ); if (!transaction?.transactionID) { diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 5fef11fa4b15..db688156a0d7 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -187,7 +187,8 @@ function IOURequestStepConfirmation({ // If there is not a report attached to the IOU with a reportID, then the participants were manually selected and the user needs taken // back to the participants step if (!transaction?.participantsAutoAssigned) { - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID, undefined, action)); + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, transaction?.reportID || reportID, undefined, action)); return; } IOUUtils.navigateToStartMoneyRequestStep(requestType, iouType, transactionID, reportID, action); From 23493ff04681103d4feb9f2a91ec6054b8684986 Mon Sep 17 00:00:00 2001 From: dominictb Date: Wed, 10 Jul 2024 17:08:06 +0700 Subject: [PATCH 10/12] fix: update lint and prettier Signed-off-by: dominictb --- src/libs/actions/IOU.ts | 12 +++++++++--- src/pages/iou/request/IOURequestStartPage.tsx | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index a7c562a99540..9e1dbb3c299c 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -324,7 +324,13 @@ function getReportPreviewAction(chatReportID: string, iouReportID: string): Onyx * @param shouldKeepExistingData * @param iouRequestType one of manual/scan/distance */ -function initMoneyRequest(reportID: string, policy: OnyxEntry, isFromGlobalCreate: boolean, shouldKeepExistingData: boolean, iouRequestType: IOURequestType = CONST.IOU.REQUEST_TYPE.MANUAL) { +function initMoneyRequest( + reportID: string, + policy: OnyxEntry, + isFromGlobalCreate: boolean, + shouldKeepExistingData: boolean, + iouRequestType: IOURequestType = CONST.IOU.REQUEST_TYPE.MANUAL, +) { // Generate a brand new transactionID const newTransactionID = CONST.IOU.OPTIMISTIC_TRANSACTION_ID; const currency = policy?.outputCurrency ?? currentUserPersonalDetails?.localCurrencyCode ?? CONST.CURRENCY.USD; @@ -333,14 +339,14 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, const created = currentDate || format(new Date(), 'yyyy-MM-dd'); // In case we should keep existing transaction data, we only need to update the reportID, isFromGlobalCreate, created and currency - if(shouldKeepExistingData) { + if (shouldKeepExistingData) { Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${newTransactionID}`, { reportID, isFromGlobalCreate, created, currency, transactionID: newTransactionID, - }) + }); return; } diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index d12c790ae743..823b3999890e 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -93,7 +93,7 @@ function IOURequestStartPage({ // Clear out the temporary expense if the reportID in the URL has changed from the transaction's reportID useEffect(() => { - if(transaction?.reportID === reportID) { + if (transaction?.reportID === reportID) { return; } const shouldKeepExistingData = !!transaction?.isFromGlobalCreate && transaction?.iouRequestType === transactionRequestType.current; @@ -110,7 +110,7 @@ function IOURequestStartPage({ const resetIOUTypeIfChanged = useCallback( (newIOUType: IOURequestType) => { - if(transaction?.iouRequestType === newIOUType) { + if (transaction?.iouRequestType === newIOUType) { return; } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, false, newIOUType); From 2f5cd9b04765c7cf2c6d0560e43310c53308fed5 Mon Sep 17 00:00:00 2001 From: dominictb Date: Thu, 11 Jul 2024 15:48:16 +0700 Subject: [PATCH 11/12] fix: update logic of checking shouldKeepData Signed-off-by: dominictb Signed-off-by: dominictb --- src/libs/actions/IOU.ts | 16 +++++++--------- src/pages/iou/request/IOURequestStartPage.tsx | 5 ++--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index bd4331b19403..ddd9f7ff5f1d 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -324,13 +324,7 @@ function getReportPreviewAction(chatReportID: string, iouReportID: string): Onyx * @param shouldKeepExistingData * @param iouRequestType one of manual/scan/distance */ -function initMoneyRequest( - reportID: string, - policy: OnyxEntry, - isFromGlobalCreate: boolean, - shouldKeepExistingData: boolean, - iouRequestType: IOURequestType = CONST.IOU.REQUEST_TYPE.MANUAL, -) { +function initMoneyRequest(reportID: string, policy: OnyxEntry, isFromGlobalCreate: boolean, iouRequestType: IOURequestType = CONST.IOU.REQUEST_TYPE.MANUAL) { // Generate a brand new transactionID const newTransactionID = CONST.IOU.OPTIMISTIC_TRANSACTION_ID; const currency = policy?.outputCurrency ?? currentUserPersonalDetails?.localCurrencyCode ?? CONST.CURRENCY.USD; @@ -338,8 +332,12 @@ function initMoneyRequest( // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const created = currentDate || format(new Date(), 'yyyy-MM-dd'); - // In case we should keep existing transaction data, we only need to update the reportID, isFromGlobalCreate, created and currency - if (shouldKeepExistingData) { + const currentTransaction = allTransactionDrafts?.[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${newTransactionID}`]; + + // in case we have to re-init money request, but the IOU request type is the same with the old draft transaction, + // we should keep most of the existing data by using the ONYX MERGE operation + if (currentTransaction?.iouRequestType === iouRequestType) { + // so, we just need to update the reportID, isFromGlobalCreate, created, currency Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${newTransactionID}`, { reportID, isFromGlobalCreate, diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 823b3999890e..82bb947d1525 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -96,8 +96,7 @@ function IOURequestStartPage({ if (transaction?.reportID === reportID) { return; } - const shouldKeepExistingData = !!transaction?.isFromGlobalCreate && transaction?.iouRequestType === transactionRequestType.current; - IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, shouldKeepExistingData, transactionRequestType.current); + IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, transactionRequestType.current); }, [transaction, policy, reportID, iouType, isFromGlobalCreate]); const isExpenseChat = ReportUtils.isPolicyExpenseChat(report); @@ -113,7 +112,7 @@ function IOURequestStartPage({ if (transaction?.iouRequestType === newIOUType) { return; } - IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, false, newIOUType); + IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, newIOUType); }, [policy, reportID, isFromGlobalCreate, transaction], ); From 07e9c6ed995829fb724ad93a9ed7eb8e63eb7ee4 Mon Sep 17 00:00:00 2001 From: dominictb Date: Thu, 11 Jul 2024 16:50:58 +0700 Subject: [PATCH 12/12] fix: remove redundant comment Signed-off-by: dominictb --- src/libs/actions/IOU.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index ddd9f7ff5f1d..d72e7d5c83ba 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -321,7 +321,6 @@ function getReportPreviewAction(chatReportID: string, iouReportID: string): Onyx * @param reportID to attach the transaction to * @param policy * @param isFromGlobalCreate - * @param shouldKeepExistingData * @param iouRequestType one of manual/scan/distance */ function initMoneyRequest(reportID: string, policy: OnyxEntry, isFromGlobalCreate: boolean, iouRequestType: IOURequestType = CONST.IOU.REQUEST_TYPE.MANUAL) {