From 17d2bb742d3eaf89b4cee45031a79c6fb9bc95f3 Mon Sep 17 00:00:00 2001 From: DylanDylann Date: Tue, 5 May 2026 16:29:28 +0700 Subject: [PATCH] refactor: extract NavigationHelpers.ts from IOU/index.ts Extracts post-expense-creation navigation helpers (dismissModalAndOpenReportInInboxTab, highlightTransactionOnSearchRouteIfNeeded, handleNavigateAfterExpenseCreate) into a dedicated module to reduce the size of IOU/index.ts. Function bodies are byte-identical to their pre-move state on main, with the single required translation of direct allTransactions reads to getAllTransactions() calls (needed because allTransactions is module-private to index.ts). Part of Issue #72804 (break up src/libs/actions/IOU/). --- src/libs/actions/IOU/NavigationHelpers.ts | 52 ++++++++++++++++++++++ src/libs/actions/IOU/PerDiem.ts | 3 +- src/libs/actions/IOU/SendInvoice.ts | 11 +---- src/libs/actions/IOU/Split.ts | 4 +- src/libs/actions/IOU/TrackExpense.ts | 3 +- src/libs/actions/IOU/index.ts | 53 +---------------------- tests/actions/IOUTest.ts | 2 +- 7 files changed, 59 insertions(+), 69 deletions(-) create mode 100644 src/libs/actions/IOU/NavigationHelpers.ts diff --git a/src/libs/actions/IOU/NavigationHelpers.ts b/src/libs/actions/IOU/NavigationHelpers.ts new file mode 100644 index 000000000000..c7bd0ee8fb65 --- /dev/null +++ b/src/libs/actions/IOU/NavigationHelpers.ts @@ -0,0 +1,52 @@ +import sharedDismissModalAndOpenReportInInboxTab from '@libs/Navigation/helpers/dismissModalAndOpenReportInInboxTab'; +import isReportTopmostSplitNavigator from '@libs/Navigation/helpers/isReportTopmostSplitNavigator'; +import navigateAfterExpenseCreate from '@libs/Navigation/helpers/navigateAfterExpenseCreate'; +import {mergeTransactionIdsHighlightOnSearchRoute} from '@userActions/Transaction'; +import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; +import {getAllTransactions} from './index'; + +/** + * @private + * After finishing the action in RHP from the Inbox tab, besides dismissing the modal, we should open the report. + * If the action is done from the report RHP, then we just want to dismiss the money request flow screens. + * It is a helper function used only in this file. + */ +function dismissModalAndOpenReportInInboxTab(reportID?: string, isInvoice?: boolean) { + const hasMultipleTransactions = Object.values(getAllTransactions()).filter((transaction) => transaction?.reportID === reportID).length > 0; + sharedDismissModalAndOpenReportInInboxTab(reportID, isInvoice, hasMultipleTransactions); +} + +/** + * Marks a transaction for highlight on the Search page when the expense was created + * from the global create button and the user is not on the Inbox tab. + */ +function highlightTransactionOnSearchRouteIfNeeded(isFromGlobalCreate: boolean | undefined, transactionID: string | undefined, dataType: SearchDataTypes) { + if (!isFromGlobalCreate || isReportTopmostSplitNavigator() || !transactionID) { + return; + } + mergeTransactionIdsHighlightOnSearchRoute(dataType, {[transactionID]: true}); +} + +/** + * Helper to navigate after an expense is created in order to standardize the post‑creation experience + * when creating an expense from the global create button. + * If the expense is created from the global create button then: + * - If it is created on the inbox tab, it will open the chat report containing that expense. + * - If it is created elsewhere, it will navigate to Reports > Expense and highlight the newly created expense. + */ +function handleNavigateAfterExpenseCreate({ + activeReportID, + transactionID, + isFromGlobalCreate, + isInvoice, +}: { + activeReportID?: string; + transactionID?: string; + isFromGlobalCreate?: boolean; + isInvoice?: boolean; +}) { + const hasMultipleTransactions = Object.values(getAllTransactions()).filter((transaction) => transaction?.reportID === activeReportID).length > 0; + navigateAfterExpenseCreate({activeReportID, transactionID, isFromGlobalCreate, isInvoice, hasMultipleTransactions}); +} + +export {dismissModalAndOpenReportInInboxTab, handleNavigateAfterExpenseCreate, highlightTransactionOnSearchRouteIfNeeded}; diff --git a/src/libs/actions/IOU/PerDiem.ts b/src/libs/actions/IOU/PerDiem.ts index b418278a599e..30d6c669c5bc 100644 --- a/src/libs/actions/IOU/PerDiem.ts +++ b/src/libs/actions/IOU/PerDiem.ts @@ -52,16 +52,15 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject'; import { buildMinimalTransactionForFormula, buildOnyxDataForMoneyRequest, - dismissModalAndOpenReportInInboxTab, getAllPersonalDetails, getAllReports, getPolicyTags, getReportPreviewAction, - highlightTransactionOnSearchRouteIfNeeded, mergePolicyRecentlyUsedCategories, mergePolicyRecentlyUsedCurrencies, } from '.'; import type {BaseTransactionParams, MoneyRequestInformation, RequestMoneyParticipantParams} from './index'; +import {dismissModalAndOpenReportInInboxTab, highlightTransactionOnSearchRouteIfNeeded} from './NavigationHelpers'; import type BasePolicyParams from './types/BasePolicyParams'; function removeSubrate(transaction: OnyxEntry, currentIndex: string) { diff --git a/src/libs/actions/IOU/SendInvoice.ts b/src/libs/actions/IOU/SendInvoice.ts index 9d256530a4df..1265a8379eb0 100644 --- a/src/libs/actions/IOU/SendInvoice.ts +++ b/src/libs/actions/IOU/SendInvoice.ts @@ -35,15 +35,8 @@ import type {InvoiceReceiver, InvoiceReceiverType} from '@src/types/onyx/Report' import type {OnyxData} from '@src/types/onyx/Request'; import type {Receipt} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import { - getAllPersonalDetails, - getReceiptError, - getSearchOnyxUpdate, - handleNavigateAfterExpenseCreate, - highlightTransactionOnSearchRouteIfNeeded, - mergePolicyRecentlyUsedCategories, - mergePolicyRecentlyUsedCurrencies, -} from '.'; +import {getAllPersonalDetails, getReceiptError, getSearchOnyxUpdate, mergePolicyRecentlyUsedCategories, mergePolicyRecentlyUsedCurrencies} from '.'; +import {handleNavigateAfterExpenseCreate, highlightTransactionOnSearchRouteIfNeeded} from './NavigationHelpers'; import type BasePolicyParams from './types/BasePolicyParams'; type SendInvoiceInformation = { diff --git a/src/libs/actions/IOU/Split.ts b/src/libs/actions/IOU/Split.ts index c1b83adfe9ab..773af0196114 100644 --- a/src/libs/actions/IOU/Split.ts +++ b/src/libs/actions/IOU/Split.ts @@ -69,7 +69,6 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject'; import { buildMinimalTransactionForFormula, buildOnyxDataForMoneyRequest, - dismissModalAndOpenReportInInboxTab, getAllPersonalDetails, getAllReports, getAllTransactionDrafts, @@ -80,12 +79,11 @@ import { getReceiptError, getReportPreviewAction, getUserAccountID, - handleNavigateAfterExpenseCreate, - highlightTransactionOnSearchRouteIfNeeded, mergePolicyRecentlyUsedCategories, mergePolicyRecentlyUsedCurrencies, } from './index'; import type {BuildOnyxDataForMoneyRequestKeys, OneOnOneIOUReport, StartSplitBilActionParams} from './index'; +import {dismissModalAndOpenReportInInboxTab, handleNavigateAfterExpenseCreate, highlightTransactionOnSearchRouteIfNeeded} from './NavigationHelpers'; import type BasePolicyParams from './types/BasePolicyParams'; import type BaseTransactionParams from './types/BaseTransactionParams'; diff --git a/src/libs/actions/IOU/TrackExpense.ts b/src/libs/actions/IOU/TrackExpense.ts index 2d7c78e7fa4f..78a19c92c5ca 100644 --- a/src/libs/actions/IOU/TrackExpense.ts +++ b/src/libs/actions/IOU/TrackExpense.ts @@ -117,9 +117,8 @@ import { getReportPreviewAction, getSearchOnyxUpdate, getTransactionWithPreservedLocalReceiptSource, - handleNavigateAfterExpenseCreate, - highlightTransactionOnSearchRouteIfNeeded, } from './index'; +import {handleNavigateAfterExpenseCreate, highlightTransactionOnSearchRouteIfNeeded} from './NavigationHelpers'; import type BasePolicyParams from './types/BasePolicyParams'; import type {CreateTrackExpenseParams} from './types/CreateTrackExpenseParams'; import type { diff --git a/src/libs/actions/IOU/index.ts b/src/libs/actions/IOU/index.ts index 13acd104071b..0f95c6d04a28 100644 --- a/src/libs/actions/IOU/index.ts +++ b/src/libs/actions/IOU/index.ts @@ -15,9 +15,6 @@ import {formatCurrentUserToAttendee, updateIOUOwnerAndTotal} from '@libs/IOUUtil import {formatPhoneNumber} from '@libs/LocalePhoneNumber'; import * as Localize from '@libs/Localize'; import Log from '@libs/Log'; -import sharedDismissModalAndOpenReportInInboxTab from '@libs/Navigation/helpers/dismissModalAndOpenReportInInboxTab'; -import isReportTopmostSplitNavigator from '@libs/Navigation/helpers/isReportTopmostSplitNavigator'; -import navigateAfterExpenseCreate from '@libs/Navigation/helpers/navigateAfterExpenseCreate'; import Navigation from '@libs/Navigation/Navigation'; import {buildNextStepNew, buildOptimisticNextStep} from '@libs/NextStepUtils'; import * as NumberUtils from '@libs/NumberUtils'; @@ -74,7 +71,6 @@ import { } from '@libs/TransactionUtils'; import ViolationsUtils from '@libs/Violations/ViolationsUtils'; import {buildOptimisticPolicyRecentlyUsedTags} from '@userActions/Policy/Tag'; -import {mergeTransactionIdsHighlightOnSearchRoute} from '@userActions/Transaction'; import {getRemoveDraftTransactionsByIDsData, removeDraftTransactionsByIDs} from '@userActions/TransactionEdit'; import type {IOUAction, IOUActionParams} from '@src/CONST'; import CONST from '@src/CONST'; @@ -89,7 +85,7 @@ import type RecentlyUsedTags from '@src/types/onyx/RecentlyUsedTags'; import type {ReportNextStep} from '@src/types/onyx/Report'; import type ReportAction from '@src/types/onyx/ReportAction'; import type {OnyxData} from '@src/types/onyx/Request'; -import type {SearchDataTypes, SearchResultDataType} from '@src/types/onyx/SearchResults'; +import type {SearchResultDataType} from '@src/types/onyx/SearchResults'; import type {Comment, Receipt, TransactionChanges, TransactionCustomUnit, WaypointCollection} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type BasePolicyParams from './types/BasePolicyParams'; @@ -528,50 +524,6 @@ function getMoneyRequestPolicyTags({ return getPolicyTagsData(iouReportPolicyID) ?? {}; } -/** - * @private - * After finishing the action in RHP from the Inbox tab, besides dismissing the modal, we should open the report. - * If the action is done from the report RHP, then we just want to dismiss the money request flow screens. - * It is a helper function used only in this file. - */ -function dismissModalAndOpenReportInInboxTab(reportID?: string, isInvoice?: boolean) { - const hasMultipleTransactions = Object.values(allTransactions).filter((transaction) => transaction?.reportID === reportID).length > 0; - sharedDismissModalAndOpenReportInInboxTab(reportID, isInvoice, hasMultipleTransactions); -} - -/** - * Marks a transaction for highlight on the Search page when the expense was created - * from the global create button and the user is not on the Inbox tab. - */ -function highlightTransactionOnSearchRouteIfNeeded(isFromGlobalCreate: boolean | undefined, transactionID: string | undefined, dataType: SearchDataTypes) { - if (!isFromGlobalCreate || isReportTopmostSplitNavigator() || !transactionID) { - return; - } - mergeTransactionIdsHighlightOnSearchRoute(dataType, {[transactionID]: true}); -} - -/** - * Helper to navigate after an expense is created in order to standardize the post‑creation experience - * when creating an expense from the global create button. - * If the expense is created from the global create button then: - * - If it is created on the inbox tab, it will open the chat report containing that expense. - * - If it is created elsewhere, it will navigate to Reports > Expense and highlight the newly created expense. - */ -function handleNavigateAfterExpenseCreate({ - activeReportID, - transactionID, - isFromGlobalCreate, - isInvoice, -}: { - activeReportID?: string; - transactionID?: string; - isFromGlobalCreate?: boolean; - isInvoice?: boolean; -}) { - const hasMultipleTransactions = Object.values(allTransactions).filter((transaction) => transaction?.reportID === activeReportID).length > 0; - navigateAfterExpenseCreate({activeReportID, transactionID, isFromGlobalCreate, isInvoice, hasMultipleTransactions}); -} - /** * Build a minimal transaction record for formula computation in buildOptimisticExpenseReport. * This allows formulas like {report:startdate}, {report:expensescount} to work correctly. @@ -2724,7 +2676,6 @@ export { createDraftTransaction, getIOURequestPolicyID, initMoneyRequest, - dismissModalAndOpenReportInInboxTab, resetDraftTransactionsCustomUnit, setCustomUnitRateID, setGPSTransactionDraftData, @@ -2782,12 +2733,10 @@ export { getMoneyRequestPolicyTags, setMoneyRequestTimeRate, setMoneyRequestTimeCount, - handleNavigateAfterExpenseCreate, buildMinimalTransactionForFormula, buildOnyxDataForMoneyRequest, getMoneyRequestInformation, getTransactionWithPreservedLocalReceiptSource, - highlightTransactionOnSearchRouteIfNeeded, }; export type { GPSPoint as GpsPoint, diff --git a/tests/actions/IOUTest.ts b/tests/actions/IOUTest.ts index 64d052648c2c..8ada78106d6b 100644 --- a/tests/actions/IOUTest.ts +++ b/tests/actions/IOUTest.ts @@ -9,7 +9,6 @@ import useOnyx from '@hooks/useOnyx'; import {clearAllRelatedReportActionErrors} from '@libs/actions/ClearReportActionErrors'; import { calculateDiffAmount, - handleNavigateAfterExpenseCreate, initMoneyRequest, resetDraftTransactionsCustomUnit, setMoneyRequestAmount, @@ -24,6 +23,7 @@ import { shouldOptimisticallyUpdateSearch, } from '@libs/actions/IOU'; import {putOnHold} from '@libs/actions/IOU/Hold'; +import {handleNavigateAfterExpenseCreate} from '@libs/actions/IOU/NavigationHelpers'; import {completeSplitBill, splitBill, startSplitBill} from '@libs/actions/IOU/Split'; import {updateSplitTransactionsFromSplitExpensesFlow} from '@libs/actions/IOU/SplitTransactionUpdate'; import {requestMoney, trackExpense} from '@libs/actions/IOU/TrackExpense';