diff --git a/config/eslint/eslint.seatbelt.tsv b/config/eslint/eslint.seatbelt.tsv index a2d77a673bf5..41c4addbeb44 100644 --- a/config/eslint/eslint.seatbelt.tsv +++ b/config/eslint/eslint.seatbelt.tsv @@ -1214,14 +1214,14 @@ "../../src/pages/TransactionDuplicate/Confirmation.tsx" "react-hooks/refs" 12 "../../src/pages/TransactionDuplicate/DuplicateTransactionItem.tsx" "@typescript-eslint/no-unsafe-type-assertion" 2 "../../src/pages/TransactionDuplicate/Review.tsx" "no-restricted-imports" 1 -"../../src/pages/TransactionMerge/ConfirmationPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/TransactionMerge/ConfirmationPage.tsx" "no-restricted-imports" 1 -"../../src/pages/TransactionMerge/DetailsReviewPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/TransactionMerge/DetailsReviewPage.tsx" "no-restricted-imports" 1 +"../../src/pages/TransactionMerge/DynamicConfirmationPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 +"../../src/pages/TransactionMerge/DynamicConfirmationPage.tsx" "no-restricted-imports" 1 +"../../src/pages/TransactionMerge/DynamicDetailsReviewPage.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 +"../../src/pages/TransactionMerge/DynamicDetailsReviewPage.tsx" "no-restricted-imports" 1 "../../src/pages/TransactionMerge/MergeTransactionItem.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 "../../src/pages/TransactionMerge/MergeTransactionsListContent.tsx" "@typescript-eslint/no-unsafe-type-assertion" 1 -"../../src/pages/TransactionMerge/ReceiptReviewPage.tsx" "no-restricted-imports" 1 -"../../src/pages/TransactionMerge/TransactionMergeReceipts.tsx" "no-restricted-imports" 1 +"../../src/pages/TransactionMerge/DynamicReceiptReviewPage.tsx" "no-restricted-imports" 1 +"../../src/pages/TransactionMerge/DynamicTransactionMergeReceipts.tsx" "no-restricted-imports" 1 "../../src/pages/Travel/DynamicDomainPermissionInfoPage.tsx" "no-restricted-imports" 1 "../../src/pages/Travel/DynamicDomainSelectorPage.tsx" "no-restricted-imports" 1 "../../src/pages/Travel/DynamicPublicDomainErrorPage.tsx" "no-restricted-imports" 1 diff --git a/src/ROUTES.ts b/src/ROUTES.ts index bc8e77350a68..916bae37e969 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -1119,6 +1119,50 @@ const DYNAMIC_ROUTES = { path: 'initial-list-value', entryScreens: [SCREENS.WORKSPACE.REPORT_FIELDS_CREATE], }, + MERGE_TRANSACTION_LIST: { + path: 'merge/:transactionID', + entryScreens: [SCREENS.REPORT, SCREENS.RIGHT_MODAL.SEARCH_REPORT, SCREENS.RIGHT_MODAL.EXPENSE_REPORT, SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT, SCREENS.SEARCH.ROOT], + getRoute: (transactionID: string) => `merge/${transactionID}` as const, + }, + MERGE_TRANSACTION_RECEIPT: { + path: 'merge/:transactionID/receipt', + entryScreens: [ + SCREENS.MERGE_TRANSACTION.DYNAMIC_LIST_PAGE, + SCREENS.REPORT, + SCREENS.RIGHT_MODAL.SEARCH_REPORT, + SCREENS.RIGHT_MODAL.EXPENSE_REPORT, + SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT, + SCREENS.SEARCH.ROOT, + ], + getRoute: (transactionID: string) => `merge/${transactionID}/receipt` as const, + }, + MERGE_TRANSACTION_DETAILS: { + path: 'merge/:transactionID/details', + entryScreens: [ + SCREENS.MERGE_TRANSACTION.DYNAMIC_LIST_PAGE, + SCREENS.MERGE_TRANSACTION.DYNAMIC_RECEIPT_PAGE, + SCREENS.REPORT, + SCREENS.RIGHT_MODAL.SEARCH_REPORT, + SCREENS.RIGHT_MODAL.EXPENSE_REPORT, + SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT, + SCREENS.SEARCH.ROOT, + ], + getRoute: (transactionID: string) => `merge/${transactionID}/details` as const, + }, + MERGE_TRANSACTION_CONFIRMATION: { + path: 'merge/:transactionID/confirmation', + entryScreens: [ + SCREENS.MERGE_TRANSACTION.DYNAMIC_LIST_PAGE, + SCREENS.MERGE_TRANSACTION.DYNAMIC_RECEIPT_PAGE, + SCREENS.MERGE_TRANSACTION.DYNAMIC_DETAILS_PAGE, + SCREENS.REPORT, + SCREENS.RIGHT_MODAL.SEARCH_REPORT, + SCREENS.RIGHT_MODAL.EXPENSE_REPORT, + SCREENS.RIGHT_MODAL.SEARCH_MONEY_REQUEST_REPORT, + SCREENS.SEARCH.ROOT, + ], + getRoute: (transactionID: string) => `merge/${transactionID}/confirmation` as const, + }, } as const satisfies DynamicRoutes; const ROUTES = { @@ -3556,38 +3600,6 @@ const ROUTES = { getRoute: (threadReportID: string, backTo?: string) => getUrlWithBackToParam(`r/${threadReportID}/duplicates/confirm` as const, backTo), }, - MERGE_TRANSACTION_LIST_PAGE: { - route: 'merge/:transactionID', - - getRoute: (transactionID: string, backTo: string, isOnSearch = false) => { - const url = getUrlWithBackToParam(`merge/${transactionID}` as const, backTo); - return isOnSearch ? (`${url}&isOnSearch=true` as const) : url; - }, - }, - MERGE_TRANSACTION_RECEIPT_PAGE: { - route: 'merge/:transactionID/receipt', - - getRoute: (transactionID: string, backTo: string, isOnSearch = false) => { - const url = getUrlWithBackToParam(`merge/${transactionID}/receipt` as const, backTo); - return isOnSearch ? (`${url}&isOnSearch=true` as const) : url; - }, - }, - MERGE_TRANSACTION_DETAILS_PAGE: { - route: 'merge/:transactionID/details', - - getRoute: (transactionID: string, backTo: string, isOnSearch = false) => { - const url = getUrlWithBackToParam(`merge/${transactionID}/details` as const, backTo); - return isOnSearch ? (`${url}&isOnSearch=true` as const) : url; - }, - }, - MERGE_TRANSACTION_CONFIRMATION_PAGE: { - route: 'merge/:transactionID/confirmation', - - getRoute: (transactionID: string, backTo: string, isOnSearch = false) => { - const url = getUrlWithBackToParam(`merge/${transactionID}/confirmation` as const, backTo); - return isOnSearch ? (`${url}&isOnSearch=true` as const) : url; - }, - }, POLICY_ACCOUNTING_XERO_SETUP: { route: 'workspaces/:policyID/accounting/xero/setup', getRoute: (policyID: string) => `workspaces/${policyID}/accounting/xero/setup` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index eb40b61b6080..cbf9ece9be29 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -393,10 +393,10 @@ const SCREENS = { }, MERGE_TRANSACTION: { - LIST_PAGE: 'Merge_Transaction_List_Page', - RECEIPT_PAGE: 'Merge_Transaction_Receipt_Page', - DETAILS_PAGE: 'Merge_Transaction_Details_Page', - CONFIRMATION_PAGE: 'Merge_Transaction_Confirmation_Page', + DYNAMIC_LIST_PAGE: 'Dynamic_Merge_Transaction_List_Page', + DYNAMIC_RECEIPT_PAGE: 'Dynamic_Merge_Transaction_Receipt_Page', + DYNAMIC_DETAILS_PAGE: 'Dynamic_Merge_Transaction_Details_Page', + DYNAMIC_CONFIRMATION_PAGE: 'Dynamic_Merge_Transaction_Confirmation_Page', }, IOU_SEND: { diff --git a/src/components/MoneyRequestHeaderSecondaryActions.tsx b/src/components/MoneyRequestHeaderSecondaryActions.tsx index dc640cf73251..fd87654eaccf 100644 --- a/src/components/MoneyRequestHeaderSecondaryActions.tsx +++ b/src/components/MoneyRequestHeaderSecondaryActions.tsx @@ -381,8 +381,7 @@ function MoneyRequestHeaderSecondaryActions({reportID, onBackButtonPress}: Money if (!transaction) { return; } - const isOnSearch = route.name.toLowerCase().startsWith('search'); - setupMergeTransactionDataAndNavigate(transaction.transactionID, [transaction], localeCompare, getCurrencyDecimals, [], false, isOnSearch); + setupMergeTransactionDataAndNavigate(transaction.transactionID, [transaction], localeCompare, getCurrencyDecimals, [], false); }, }, [CONST.REPORT.TRANSACTION_SECONDARY_ACTIONS.DUPLICATE]: { diff --git a/src/hooks/useSearchBulkActions.ts b/src/hooks/useSearchBulkActions.ts index ce43f5f9e5e8..739e22d66e1d 100644 --- a/src/hooks/useSearchBulkActions.ts +++ b/src/hooks/useSearchBulkActions.ts @@ -2019,7 +2019,7 @@ function useSearchBulkActions({queryJSON}: UseSearchBulkActionsParams) { text: translate('common.merge'), icon: expensifyIcons.ArrowCollapse, value: CONST.SEARCH.BULK_ACTION_TYPES.MERGE, - onSelected: () => setupMergeTransactionDataAndNavigate(transactionID, searchedTransactions, localeCompare, getCurrencyDecimals, reports, false, true), + onSelected: () => setupMergeTransactionDataAndNavigate(transactionID, searchedTransactions, localeCompare, getCurrencyDecimals, reports, false), }); } } diff --git a/src/hooks/useSelectedTransactionsActions.ts b/src/hooks/useSelectedTransactionsActions.ts index 4c282f351f99..d388a7a6e934 100644 --- a/src/hooks/useSelectedTransactionsActions.ts +++ b/src/hooks/useSelectedTransactionsActions.ts @@ -470,7 +470,6 @@ function useSelectedTransactionsActions({ getCurrencyDecimals, [], false, - isOnSearch, selectedTransactionsList.length > 1 ? [policy, policy] : undefined, ), }); diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 6ea2192c34d5..9e0134e3cc4f 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -1178,10 +1178,10 @@ const TransactionDuplicateStackNavigator = createModalStackNavigator({ - [SCREENS.MERGE_TRANSACTION.LIST_PAGE]: () => require('../../../../pages/TransactionMerge/MergeTransactionsListPage').default, - [SCREENS.MERGE_TRANSACTION.RECEIPT_PAGE]: () => require('../../../../pages/TransactionMerge/ReceiptReviewPage').default, - [SCREENS.MERGE_TRANSACTION.DETAILS_PAGE]: () => require('../../../../pages/TransactionMerge/DetailsReviewPage').default, - [SCREENS.MERGE_TRANSACTION.CONFIRMATION_PAGE]: () => require('../../../../pages/TransactionMerge/ConfirmationPage').default, + [SCREENS.MERGE_TRANSACTION.DYNAMIC_LIST_PAGE]: () => require('../../../../pages/TransactionMerge/DynamicMergeTransactionsListPage').default, + [SCREENS.MERGE_TRANSACTION.DYNAMIC_RECEIPT_PAGE]: () => require('../../../../pages/TransactionMerge/DynamicReceiptReviewPage').default, + [SCREENS.MERGE_TRANSACTION.DYNAMIC_DETAILS_PAGE]: () => require('../../../../pages/TransactionMerge/DynamicDetailsReviewPage').default, + [SCREENS.MERGE_TRANSACTION.DYNAMIC_CONFIRMATION_PAGE]: () => require('../../../../pages/TransactionMerge/DynamicConfirmationPage').default, }); const SearchReportActionsModalStackNavigator = createModalStackNavigator({ diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 7d42422f1aa6..46a43f32def5 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -1876,10 +1876,10 @@ const config: LinkingOptions['config'] = { }, [SCREENS.RIGHT_MODAL.MERGE_TRANSACTION]: { screens: { - [SCREENS.MERGE_TRANSACTION.LIST_PAGE]: ROUTES.MERGE_TRANSACTION_LIST_PAGE.route, - [SCREENS.MERGE_TRANSACTION.RECEIPT_PAGE]: ROUTES.MERGE_TRANSACTION_RECEIPT_PAGE.route, - [SCREENS.MERGE_TRANSACTION.DETAILS_PAGE]: ROUTES.MERGE_TRANSACTION_DETAILS_PAGE.route, - [SCREENS.MERGE_TRANSACTION.CONFIRMATION_PAGE]: ROUTES.MERGE_TRANSACTION_CONFIRMATION_PAGE.route, + [SCREENS.MERGE_TRANSACTION.DYNAMIC_LIST_PAGE]: DYNAMIC_ROUTES.MERGE_TRANSACTION_LIST.path, + [SCREENS.MERGE_TRANSACTION.DYNAMIC_RECEIPT_PAGE]: DYNAMIC_ROUTES.MERGE_TRANSACTION_RECEIPT.path, + [SCREENS.MERGE_TRANSACTION.DYNAMIC_DETAILS_PAGE]: DYNAMIC_ROUTES.MERGE_TRANSACTION_DETAILS.path, + [SCREENS.MERGE_TRANSACTION.DYNAMIC_CONFIRMATION_PAGE]: DYNAMIC_ROUTES.MERGE_TRANSACTION_CONFIRMATION.path, }, }, [SCREENS.RIGHT_MODAL.SPLIT_DETAILS]: { diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 96e9f76c5cdb..f27031082843 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -2587,29 +2587,17 @@ type TransactionDuplicateNavigatorParamList = { }; type MergeTransactionNavigatorParamList = { - [SCREENS.MERGE_TRANSACTION.LIST_PAGE]: { + [SCREENS.MERGE_TRANSACTION.DYNAMIC_LIST_PAGE]: { transactionID: string; - // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md - backTo?: Routes; - isOnSearch?: boolean; }; - [SCREENS.MERGE_TRANSACTION.RECEIPT_PAGE]: { + [SCREENS.MERGE_TRANSACTION.DYNAMIC_RECEIPT_PAGE]: { transactionID: string; - // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md - backTo?: Routes; - isOnSearch?: boolean; }; - [SCREENS.MERGE_TRANSACTION.DETAILS_PAGE]: { + [SCREENS.MERGE_TRANSACTION.DYNAMIC_DETAILS_PAGE]: { transactionID: string; - // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md - backTo?: Routes; - isOnSearch?: boolean; }; - [SCREENS.MERGE_TRANSACTION.CONFIRMATION_PAGE]: { + [SCREENS.MERGE_TRANSACTION.DYNAMIC_CONFIRMATION_PAGE]: { transactionID: string; - // eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md - backTo?: Routes; - isOnSearch?: boolean; }; }; diff --git a/src/libs/actions/MergeTransaction.ts b/src/libs/actions/MergeTransaction.ts index 009321b90137..23ed844726d0 100644 --- a/src/libs/actions/MergeTransaction.ts +++ b/src/libs/actions/MergeTransaction.ts @@ -14,6 +14,7 @@ import { shouldNavigateToReceiptReview, } from '@libs/MergeTransactionUtils'; import type {MergeFieldKey, MergeTransactionUpdateValues} from '@libs/MergeTransactionUtils'; +import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute'; import Navigation from '@libs/Navigation/Navigation'; import {isPaidGroupPolicy, isPolicyAdmin} from '@libs/PolicyUtils'; import {getIOUActionForReportID, getReportAction, getTrackExpenseActionableWhisper} from '@libs/ReportActionsUtils'; @@ -30,7 +31,8 @@ import { import CONST from '@src/CONST'; import {isDistanceRequest, isTransactionPendingDelete} from '@src/libs/TransactionUtils'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; +import {DYNAMIC_ROUTES} from '@src/ROUTES'; +import type {Route} from '@src/ROUTES'; import type {CardList, MergeTransaction, Policy, PolicyCategories, PolicyTagLists, Report, ReportNextStepDeprecated, Transaction, TransactionViolations} from '@src/types/onyx'; import type {OnyxCollection, OnyxEntry, OnyxMergeInput, OnyxUpdate} from 'react-native-onyx'; @@ -65,8 +67,8 @@ function setupMergeTransactionDataAndNavigate( getCurrencyDecimals: CurrencyListActionsContextType['getCurrencyDecimals'], searchReports?: Report[], isSelectingSourceTransaction?: boolean, - isOnSearch?: boolean, policies?: Array>, + basePath?: Route, ) { if (!transactions.length || transactions.length > 2) { return; @@ -76,7 +78,7 @@ function setupMergeTransactionDataAndNavigate( const transaction = transactions.at(0); if (transaction) { setupMergeTransactionData(navigationTransactionID, {targetTransactionID: transaction.transactionID}); - Navigation.navigate(ROUTES.MERGE_TRANSACTION_LIST_PAGE.getRoute(transaction.transactionID, Navigation.getActiveRoute(), isOnSearch)); + Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MERGE_TRANSACTION_LIST.getRoute(transaction.transactionID))); return; } } @@ -99,7 +101,7 @@ function setupMergeTransactionDataAndNavigate( } if (shouldNavigateToReceiptReview([targetTransaction, sourceTransaction])) { // Navigate to the receipt review page if both transactions have a receipt - Navigation.navigate(ROUTES.MERGE_TRANSACTION_RECEIPT_PAGE.getRoute(navigationTransactionID, Navigation.getActiveRoute(), isOnSearch)); + Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MERGE_TRANSACTION_RECEIPT.getRoute(navigationTransactionID), basePath)); } else { const receipt = targetTransaction.receipt?.receiptID ? targetTransaction.receipt : sourceTransaction.receipt; if (receipt) { @@ -119,11 +121,11 @@ function setupMergeTransactionDataAndNavigate( if (!conflictFields.length) { // If there are no conflict fields, we should set mergeable data and navigate to the confirmation page setMergeTransactionKey(navigationTransactionID, mergeableData); - Navigation.navigate(ROUTES.MERGE_TRANSACTION_CONFIRMATION_PAGE.getRoute(navigationTransactionID, Navigation.getActiveRoute(), isOnSearch)); + Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MERGE_TRANSACTION_CONFIRMATION.getRoute(navigationTransactionID), basePath)); return; } - Navigation.navigate(ROUTES.MERGE_TRANSACTION_DETAILS_PAGE.getRoute(navigationTransactionID, Navigation.getActiveRoute(), isOnSearch)); + Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MERGE_TRANSACTION_DETAILS.getRoute(navigationTransactionID), basePath)); } } diff --git a/src/pages/TransactionMerge/ConfirmationPage.tsx b/src/pages/TransactionMerge/DynamicConfirmationPage.tsx similarity index 92% rename from src/pages/TransactionMerge/ConfirmationPage.tsx rename to src/pages/TransactionMerge/DynamicConfirmationPage.tsx index 7e8109a4c434..af3cb10cf3e1 100644 --- a/src/pages/TransactionMerge/ConfirmationPage.tsx +++ b/src/pages/TransactionMerge/DynamicConfirmationPage.tsx @@ -10,6 +10,7 @@ import Text from '@components/Text'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useDelegateAccountID from '@hooks/useDelegateAccountID'; +import useDynamicBackPath from '@hooks/useDynamicBackPath'; import useLocalize from '@hooks/useLocalize'; import useMergeTransactions from '@hooks/useMergeTransactions'; import useOnyx from '@hooks/useOnyx'; @@ -29,7 +30,7 @@ import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; +import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {Transaction} from '@src/types/onyx'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; @@ -40,14 +41,15 @@ import {isTrackIntentUserSelector} from '@selectors/Onboarding'; import React, {useState} from 'react'; import {View} from 'react-native'; -type ConfirmationPageProps = PlatformStackScreenProps; +type DynamicConfirmationPageProps = PlatformStackScreenProps; -function ConfirmationPage({route}: ConfirmationPageProps) { +function DynamicConfirmationPage({route}: DynamicConfirmationPageProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const [isMergingExpenses, setIsMergingExpenses] = useState(false); - const {transactionID, isOnSearch, backTo} = route.params; + const {transactionID} = route.params; + const backTo = useDynamicBackPath(DYNAMIC_ROUTES.MERGE_TRANSACTION_CONFIRMATION.path); const [mergeTransaction, mergeTransactionMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.MERGE_TRANSACTION}${getNonEmptyStringOnyxID(transactionID)}`); const {targetTransaction, sourceTransaction, targetTransactionReport, targetTransactionPolicy} = useMergeTransactions({mergeTransaction}); const [allTransactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS); @@ -108,7 +110,7 @@ function ConfirmationPage({route}: ConfirmationPageProps) { const searchReportIDToOpen = targetTransactionThreadReportID ?? reportIDToDismiss; // If we're in search (or the topmost route is search), dismiss the modal and open the expense in the RHP - if ((isOnSearch || isSearchTopmostFullScreenRoute()) && searchReportIDToOpen) { + if (isSearchTopmostFullScreenRoute() && searchReportIDToOpen) { Navigation.dismissModal(); Navigation.setNavigationActionToMicrotaskQueue(() => { Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID: searchReportIDToOpen})); @@ -126,7 +128,7 @@ function ConfirmationPage({route}: ConfirmationPageProps) { if (isLoadingOnyxValue(mergeTransactionMetadata)) { const reasonAttributes: SkeletonSpanReasonAttributes = { - context: 'TransactionMerge.ConfirmationPage', + context: 'TransactionMerge.DynamicConfirmationPage', isLoadingMergeTransaction: isLoadingOnyxValue(mergeTransactionMetadata), }; return ; @@ -134,7 +136,7 @@ function ConfirmationPage({route}: ConfirmationPageProps) { return ( @@ -171,4 +173,4 @@ function ConfirmationPage({route}: ConfirmationPageProps) { ); } -export default ConfirmationPage; +export default DynamicConfirmationPage; diff --git a/src/pages/TransactionMerge/DetailsReviewPage.tsx b/src/pages/TransactionMerge/DynamicDetailsReviewPage.tsx similarity index 91% rename from src/pages/TransactionMerge/DetailsReviewPage.tsx rename to src/pages/TransactionMerge/DynamicDetailsReviewPage.tsx index ea1cfbd92617..4bf8f45fbd53 100644 --- a/src/pages/TransactionMerge/DetailsReviewPage.tsx +++ b/src/pages/TransactionMerge/DynamicDetailsReviewPage.tsx @@ -9,6 +9,7 @@ import ScrollView from '@components/ScrollView'; import Text from '@components/Text'; import {useCurrencyListActions} from '@hooks/useCurrencyList'; +import useDynamicBackPath from '@hooks/useDynamicBackPath'; import useLocalize from '@hooks/useLocalize'; import useMergeTransactions from '@hooks/useMergeTransactions'; import useOnyx from '@hooks/useOnyx'; @@ -26,6 +27,7 @@ import { isEmptyMergeValue, } from '@libs/MergeTransactionUtils'; import type {MergeFieldKey} from '@libs/MergeTransactionUtils'; +import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {MergeTransactionNavigatorParamList} from '@libs/Navigation/types'; @@ -33,7 +35,7 @@ import type {TransactionDetails} from '@libs/ReportUtils'; import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; +import {DYNAMIC_ROUTES} from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {Transaction} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -44,13 +46,14 @@ import {View} from 'react-native'; import MergeFieldReview from './MergeFieldReview'; -type DetailsReviewPageProps = PlatformStackScreenProps; +type DynamicDetailsReviewPageProps = PlatformStackScreenProps; -function DetailsReviewPage({route}: DetailsReviewPageProps) { +function DynamicDetailsReviewPage({route}: DynamicDetailsReviewPageProps) { const {translate, localeCompare} = useLocalize(); const styles = useThemeStyles(); const {getCurrencyDecimals, convertToDisplayString} = useCurrencyListActions(); - const {transactionID, isOnSearch, backTo} = route.params; + const {transactionID} = route.params; + const backTo = useDynamicBackPath(DYNAMIC_ROUTES.MERGE_TRANSACTION_DETAILS.path); const [mergeTransaction, mergeTransactionMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.MERGE_TRANSACTION}${getNonEmptyStringOnyxID(transactionID)}`); const {targetTransaction, sourceTransaction, targetTransactionReport, sourceTransactionReport, targetTransactionPolicy, sourceTransactionPolicy} = useMergeTransactions({ @@ -151,9 +154,9 @@ function DetailsReviewPage({route}: DetailsReviewPageProps) { setHasErrors(newHasErrors); if (isEmptyObject(newHasErrors)) { - Navigation.navigate(ROUTES.MERGE_TRANSACTION_CONFIRMATION_PAGE.getRoute(transactionID, Navigation.getActiveRoute(), isOnSearch)); + Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MERGE_TRANSACTION_CONFIRMATION.getRoute(transactionID), backTo)); } - }, [mergeTransaction, conflictFields, transactionID, isOnSearch]); + }, [mergeTransaction, conflictFields, transactionID, backTo]); // Build merge fields array with all necessary information const mergeFields = useMemo( @@ -194,7 +197,7 @@ function DetailsReviewPage({route}: DetailsReviewPageProps) { if (isLoadingOnyxValue(mergeTransactionMetadata)) { const reasonAttributes: SkeletonSpanReasonAttributes = { - context: 'TransactionMerge.DetailsReviewPage', + context: 'TransactionMerge.DynamicDetailsReviewPage', isLoadingMergeTransaction: isLoadingOnyxValue(mergeTransactionMetadata), }; return ; @@ -202,7 +205,7 @@ function DetailsReviewPage({route}: DetailsReviewPageProps) { return ( @@ -247,4 +250,4 @@ function DetailsReviewPage({route}: DetailsReviewPageProps) { ); } -export default DetailsReviewPage; +export default DynamicDetailsReviewPage; diff --git a/src/pages/TransactionMerge/MergeTransactionsListPage.tsx b/src/pages/TransactionMerge/DynamicMergeTransactionsListPage.tsx similarity index 76% rename from src/pages/TransactionMerge/MergeTransactionsListPage.tsx rename to src/pages/TransactionMerge/DynamicMergeTransactionsListPage.tsx index 76cfaf2fe1c4..0d68c9f20883 100644 --- a/src/pages/TransactionMerge/MergeTransactionsListPage.tsx +++ b/src/pages/TransactionMerge/DynamicMergeTransactionsListPage.tsx @@ -3,6 +3,7 @@ import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; +import useDynamicBackPath from '@hooks/useDynamicBackPath'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -12,6 +13,7 @@ import type {MergeTransactionNavigatorParamList} from '@libs/Navigation/types'; import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan'; import ONYXKEYS from '@src/ONYXKEYS'; +import {DYNAMIC_ROUTES} from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; @@ -19,17 +21,18 @@ import React from 'react'; import MergeTransactionsListContent from './MergeTransactionsListContent'; -type MergeTransactionsListPageProps = PlatformStackScreenProps; +type DynamicMergeTransactionsListPageProps = PlatformStackScreenProps; -function MergeTransactionsListPage({route}: MergeTransactionsListPageProps) { +function DynamicMergeTransactionsListPage({route}: DynamicMergeTransactionsListPageProps) { const {translate} = useLocalize(); - const {transactionID, backTo} = route.params; + const {transactionID} = route.params; + const backTo = useDynamicBackPath(DYNAMIC_ROUTES.MERGE_TRANSACTION_LIST.path); const [mergeTransaction, mergeTransactionMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.MERGE_TRANSACTION}${transactionID}`); if (isLoadingOnyxValue(mergeTransactionMetadata)) { const reasonAttributes: SkeletonSpanReasonAttributes = { - context: 'TransactionMerge.MergeTransactionsListPage', + context: 'TransactionMerge.DynamicMergeTransactionsListPage', isLoadingMergeTransaction: isLoadingOnyxValue(mergeTransactionMetadata), }; return ; @@ -37,7 +40,7 @@ function MergeTransactionsListPage({route}: MergeTransactionsListPageProps) { return ( @@ -57,4 +60,4 @@ function MergeTransactionsListPage({route}: MergeTransactionsListPageProps) { ); } -export default MergeTransactionsListPage; +export default DynamicMergeTransactionsListPage; diff --git a/src/pages/TransactionMerge/ReceiptReviewPage.tsx b/src/pages/TransactionMerge/DynamicReceiptReviewPage.tsx similarity index 83% rename from src/pages/TransactionMerge/ReceiptReviewPage.tsx rename to src/pages/TransactionMerge/DynamicReceiptReviewPage.tsx index 3ee2da873d06..853050d7a79a 100644 --- a/src/pages/TransactionMerge/ReceiptReviewPage.tsx +++ b/src/pages/TransactionMerge/DynamicReceiptReviewPage.tsx @@ -8,6 +8,7 @@ import ScrollView from '@components/ScrollView'; import Text from '@components/Text'; import {useCurrencyListActions} from '@hooks/useCurrencyList'; +import useDynamicBackPath from '@hooks/useDynamicBackPath'; import useLocalize from '@hooks/useLocalize'; import useMergeTransactions from '@hooks/useMergeTransactions'; import useOnyx from '@hooks/useOnyx'; @@ -16,13 +17,14 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {setMergeTransactionKey} from '@libs/actions/MergeTransaction'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import {getMergeableDataAndConflictFields} from '@libs/MergeTransactionUtils'; +import createDynamicRoute from '@libs/Navigation/helpers/dynamicRoutesUtils/createDynamicRoute'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {MergeTransactionNavigatorParamList} from '@libs/Navigation/types'; import type {SkeletonSpanReasonAttributes} from '@libs/telemetry/useSkeletonSpan'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; +import {DYNAMIC_ROUTES} from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {Transaction} from '@src/types/onyx'; import type {Receipt} from '@src/types/onyx/Transaction'; @@ -33,13 +35,14 @@ import {View} from 'react-native'; import TransactionMergeReceipts from './TransactionMergeReceipts'; -type ReceiptReviewPageProps = PlatformStackScreenProps; +type DynamicReceiptReviewPageProps = PlatformStackScreenProps; -function ReceiptReviewPage({route}: ReceiptReviewPageProps) { +function DynamicReceiptReviewPage({route}: DynamicReceiptReviewPageProps) { const {translate, localeCompare} = useLocalize(); const styles = useThemeStyles(); const {getCurrencyDecimals} = useCurrencyListActions(); - const {transactionID, isOnSearch, backTo} = route.params; + const {transactionID} = route.params; + const backTo = useDynamicBackPath(DYNAMIC_ROUTES.MERGE_TRANSACTION_RECEIPT.path); const [mergeTransaction, mergeTransactionMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.MERGE_TRANSACTION}${getNonEmptyStringOnyxID(transactionID)}`); const {targetTransaction, sourceTransaction, targetTransactionPolicy, sourceTransactionPolicy} = useMergeTransactions({mergeTransaction}); @@ -67,15 +70,15 @@ function ReceiptReviewPage({route}: ReceiptReviewPageProps) { if (!conflictFields.length) { // If there are no conflict fields, we should set mergeable data and navigate to the confirmation page setMergeTransactionKey(transactionID, mergeableData); - Navigation.navigate(ROUTES.MERGE_TRANSACTION_CONFIRMATION_PAGE.getRoute(transactionID, Navigation.getActiveRoute(), isOnSearch)); + Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MERGE_TRANSACTION_CONFIRMATION.getRoute(transactionID), backTo)); return; } - Navigation.navigate(ROUTES.MERGE_TRANSACTION_DETAILS_PAGE.getRoute(transactionID, Navigation.getActiveRoute(), isOnSearch)); + Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.MERGE_TRANSACTION_DETAILS.getRoute(transactionID), backTo)); }; if (isLoadingOnyxValue(mergeTransactionMetadata)) { const reasonAttributes: SkeletonSpanReasonAttributes = { - context: 'TransactionMerge.ReceiptReviewPage', + context: 'TransactionMerge.DynamicReceiptReviewPage', isLoadingMergeTransaction: isLoadingOnyxValue(mergeTransactionMetadata), }; return ; @@ -83,7 +86,7 @@ function ReceiptReviewPage({route}: ReceiptReviewPageProps) { return ( @@ -119,4 +122,4 @@ function ReceiptReviewPage({route}: ReceiptReviewPageProps) { ); } -export default ReceiptReviewPage; +export default DynamicReceiptReviewPage; diff --git a/src/pages/TransactionMerge/MergeTransactionsListContent.tsx b/src/pages/TransactionMerge/MergeTransactionsListContent.tsx index bd299a0b1f60..f748d44f0f8a 100644 --- a/src/pages/TransactionMerge/MergeTransactionsListContent.tsx +++ b/src/pages/TransactionMerge/MergeTransactionsListContent.tsx @@ -7,6 +7,7 @@ import MergeExpensesSkeleton from '@components/Skeletons/MergeExpensesSkeleton'; import {useCurrencyListActions} from '@hooks/useCurrencyList'; import useDebouncedState from '@hooks/useDebouncedState'; +import useDynamicBackPath from '@hooks/useDynamicBackPath'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useMergeTransactions from '@hooks/useMergeTransactions'; @@ -23,6 +24,7 @@ import {getAmount, getCreated, getCurrency, getDescription, getMerchant, isExpen import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import {DYNAMIC_ROUTES} from '@src/ROUTES'; import type {MergeTransaction} from '@src/types/onyx'; import type {Errors} from '@src/types/onyx/OnyxCommon'; import type Transaction from '@src/types/onyx/Transaction'; @@ -52,6 +54,7 @@ function MergeTransactionsListContent({transactionID, mergeTransaction}: MergeTr const [transactions] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION); const {isOffline} = useNetwork(); const {convertToDisplayString, getCurrencyDecimals} = useCurrencyListActions(); + const listBackPath = useDynamicBackPath(DYNAMIC_ROUTES.MERGE_TRANSACTION_LIST.path); const eligibleTransactions = mergeTransaction?.eligibleTransactions; const {targetTransaction, sourceTransaction, targetTransactionReport, sourceTransactionReport, targetTransactionPolicy, sourceTransactionPolicy} = useMergeTransactions({ @@ -163,10 +166,16 @@ function MergeTransactionsListContent({transactionID, mergeTransaction}: MergeTr } const reports = targetTransactionReport && sourceTransactionReport ? [targetTransactionReport, sourceTransactionReport] : undefined; - setupMergeTransactionDataAndNavigate(transactionID, [targetTransaction, sourceTransaction], localeCompare, getCurrencyDecimals, reports, true, undefined, [ - targetTransactionPolicy, - sourceTransactionPolicy, - ]); + setupMergeTransactionDataAndNavigate( + transactionID, + [targetTransaction, sourceTransaction], + localeCompare, + getCurrencyDecimals, + reports, + true, + [targetTransactionPolicy, sourceTransactionPolicy], + listBackPath, + ); }; const confirmButtonOptions = { diff --git a/tests/unit/hooks/useSelectedTransactionsActions.test.ts b/tests/unit/hooks/useSelectedTransactionsActions.test.ts index c342d5671dff..6cce165e9c2d 100644 --- a/tests/unit/hooks/useSelectedTransactionsActions.test.ts +++ b/tests/unit/hooks/useSelectedTransactionsActions.test.ts @@ -959,6 +959,6 @@ describe('useSelectedTransactionsActions', () => { mergeOption?.onSelected?.(); - expect(setupMergeTransactionDataAndNavigate).toHaveBeenCalledWith(transaction.transactionID, [transaction], mockLocalCompare, mockGetCurrencyDecimals, [], false, false, undefined); + expect(setupMergeTransactionDataAndNavigate).toHaveBeenCalledWith(transaction.transactionID, [transaction], mockLocalCompare, mockGetCurrencyDecimals, [], false, undefined); }); });