From 8d0212a3d4b9f16d191c127353f6a6b3a3a077c1 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 13 Mar 2026 14:25:21 +0700 Subject: [PATCH 1/8] feat: Support partial approval from Reports page --- src/components/Search/SearchList/index.tsx | 7 +++ src/components/Search/index.tsx | 59 ++++++++++++++++++- .../Search/ExpenseReportListItem.tsx | 3 + .../SelectionListWithSections/types.ts | 8 +++ src/libs/SearchUIUtils.ts | 7 +-- src/libs/actions/Search.ts | 9 ++- 6 files changed, 83 insertions(+), 10 deletions(-) diff --git a/src/components/Search/SearchList/index.tsx b/src/components/Search/SearchList/index.tsx index a203e900083a..47ef14e1c2a1 100644 --- a/src/components/Search/SearchList/index.tsx +++ b/src/components/Search/SearchList/index.tsx @@ -54,6 +54,7 @@ import type {TransactionPreviewData} from '@userActions/Search'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {Transaction, TransactionViolations} from '@src/types/onyx'; +import type {HoldMenuCallback} from '..'; import BaseSearchList from './BaseSearchList'; const easing = Easing.bezier(0.76, 0.0, 0.24, 1.0); @@ -129,6 +130,9 @@ type SearchListProps = Pick, 'onScroll' | 'conten /** Callback to fire when DEW modal should be opened */ onDEWModalOpen?: () => void; + /** Callback to fire when hold menu should be opened */ + onHoldMenuOpen?: HoldMenuCallback; + /** Whether the DEW beta flag is enabled */ isDEWBetaEnabled?: boolean; @@ -221,6 +225,7 @@ function SearchList({ violations, customCardNames, onDEWModalOpen, + onHoldMenuOpen, isDEWBetaEnabled, selectedTransactions, hasLoadedAllTransactions, @@ -446,6 +451,7 @@ function SearchList({ customCardNames={customCardNames} onFocus={onFocus} newTransactionID={newTransactionID} + onHoldMenuOpen={onHoldMenuOpen} /> ); @@ -479,6 +485,7 @@ function SearchList({ lastPaymentMethod, personalPolicyID, customCardNames, + onHoldMenuOpen, ], ); diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index e3e062a0c98a..b1585f55d33d 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -8,6 +8,8 @@ import Animated, {FadeIn, FadeOut, useAnimatedStyle, useSharedValue, withTiming} import FullPageErrorView from '@components/BlockingViews/FullPageErrorView'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import {ModalActions} from '@components/Modal/Global/ModalContext'; +import type {ActionHandledType} from '@components/ProcessMoneyReportHoldMenu'; +import ProcessMoneyReportHoldMenu from '@components/ProcessMoneyReportHoldMenu'; import SearchTableHeader from '@components/SelectionListWithSections/SearchTableHeader'; import type { ReportActionListItemType, @@ -42,7 +44,7 @@ import Log from '@libs/Log'; import isSearchTopmostFullScreenRoute from '@libs/Navigation/helpers/isSearchTopmostFullScreenRoute'; import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types'; import {isSplitAction} from '@libs/ReportSecondaryActionUtils'; -import {canEditFieldOfMoneyRequest, canHoldUnholdReportAction, canRejectReportAction, isOneTransactionReport, selectFilteredReportActions} from '@libs/ReportUtils'; +import {canEditFieldOfMoneyRequest, canHoldUnholdReportAction, canRejectReportAction, getNonHeldAndFullAmount, isOneTransactionReport, selectFilteredReportActions} from '@libs/ReportUtils'; import {buildCannedSearchQuery, buildSearchQueryString} from '@libs/SearchQueryUtils'; import { createAndOpenSearchTransactionThread, @@ -76,7 +78,8 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import {columnsSelector} from '@src/selectors/AdvancedSearchFiltersForm'; -import type {OutstandingReportsByPolicyIDDerivedValue, SaveSearch, Transaction} from '@src/types/onyx'; +import type {OutstandingReportsByPolicyIDDerivedValue, Report, SaveSearch, Transaction} from '@src/types/onyx'; +import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type SearchResults from '@src/types/onyx/SearchResults'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import arraysEqual from '@src/utils/arraysEqual'; @@ -98,6 +101,8 @@ type SearchProps = { onDEWModalOpen?: () => void; }; +type HoldMenuCallback = (item: TransactionReportGroupListItemType, requestType: ActionHandledType, paymentType?: PaymentMethodType) => void; + function mapTransactionItemToSelectedEntry( item: TransactionListItemType, itemTransaction: OnyxEntry, @@ -227,6 +232,18 @@ function Search({ const navigation = useNavigation>(); const isFocused = useIsFocused(); const {markReportIDAsExpense} = useWideRHPActions(); + const [isHoldMenuVisible, setIsHoldMenuVisible] = useState(false); + const [holdMenuParams, setHoldMenuParams] = useState<{ + chatReport: OnyxEntry; + fullAmount: string; + moneyRequestReport: OnyxEntry; + transactionCount: number; + nonHeldAmount: string; + requestType: ActionHandledType; + paymentType?: PaymentMethodType; + hasValidNonHeldAmount: boolean; + hasNoneHeldExpenses: boolean; + } | null>(null); const { currentSearchHash, @@ -286,6 +303,27 @@ function Search({ selector: savedSearchSelector, }); + const handleHoldMenuOpen = useCallback( + (item: TransactionReportGroupListItemType, requestType: ActionHandledType, paymentType?: PaymentMethodType) => { + const chatReport = searchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${item.parentReportID}`]; + const moneyRequestReport = searchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`]; + const {nonHeldAmount, fullAmount, hasValidNonHeldAmount} = getNonHeldAndFullAmount(moneyRequestReport, item.allActions?.includes(CONST.SEARCH.ACTION_TYPES.PAY) ?? false); + setHoldMenuParams({ + chatReport, + moneyRequestReport, + transactionCount: item.transactionCount ?? 0, + fullAmount, + requestType, + paymentType, + nonHeldAmount, + hasValidNonHeldAmount, + hasNoneHeldExpenses: item.transactions.some((t) => !isOnHold(t)), + }); + setIsHoldMenuVisible(true); + }, + [searchResults?.data], + ); + const handleDEWModalOpen = useCallback(() => { if (onDEWModalOpen) { onDEWModalOpen(); @@ -1467,7 +1505,22 @@ function Search({ newTransactions={newTransactions} hasLoadedAllTransactions={hasLoadedAllTransactions} customCardNames={customCardNames} + onHoldMenuOpen={handleHoldMenuOpen} /> + {isHoldMenuVisible && !!holdMenuParams && ( + setIsHoldMenuVisible(false)} + chatReport={holdMenuParams.chatReport} + fullAmount={holdMenuParams.fullAmount} + moneyRequestReport={holdMenuParams.moneyRequestReport} + transactionCount={holdMenuParams.transactionCount} + hasNonHeldExpenses={holdMenuParams?.hasNoneHeldExpenses} + nonHeldAmount={holdMenuParams.hasNoneHeldExpenses && holdMenuParams.hasValidNonHeldAmount ? holdMenuParams.nonHeldAmount : undefined} + requestType={holdMenuParams.requestType} + paymentType={holdMenuParams.paymentType} + /> + )} ); @@ -1475,7 +1528,7 @@ function Search({ Search.displayName = 'Search'; -export type {SearchProps}; +export type {SearchProps, HoldMenuCallback}; const WrappedSearch = Sentry.withProfiler(Search) as typeof Search; WrappedSearch.displayName = 'Search'; diff --git a/src/components/SelectionListWithSections/Search/ExpenseReportListItem.tsx b/src/components/SelectionListWithSections/Search/ExpenseReportListItem.tsx index b3b44b0286e0..d9b626190758 100644 --- a/src/components/SelectionListWithSections/Search/ExpenseReportListItem.tsx +++ b/src/components/SelectionListWithSections/Search/ExpenseReportListItem.tsx @@ -44,6 +44,7 @@ function ExpenseReportListItem({ shouldSyncFocus, onCheckboxPress, onDEWModalOpen, + onHoldMenuOpen, isDEWBetaEnabled, lastPaymentMethod, personalPolicyID, @@ -135,6 +136,7 @@ function ExpenseReportListItem({ isDelegateAccessRestricted, onDelegateAccessRestricted: showDelegateNoAccessModal, personalPolicyID, + onHoldMenuOpen, }); }, [ currentSearchHash, @@ -149,6 +151,7 @@ function ExpenseReportListItem({ isDEWBetaEnabled, isDelegateAccessRestricted, showDelegateNoAccessModal, + onHoldMenuOpen, ]); const handleCheckboxPress = useCallback(() => { diff --git a/src/components/SelectionListWithSections/types.ts b/src/components/SelectionListWithSections/types.ts index d82358af3448..c224493d8c6a 100644 --- a/src/components/SelectionListWithSections/types.ts +++ b/src/components/SelectionListWithSections/types.ts @@ -18,6 +18,7 @@ import type { import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {AnimatedStyle} from 'react-native-reanimated'; import type {ValueOf} from 'type-fest'; +import type {HoldMenuCallback} from '@components/Search'; import type {SearchRouterItem} from '@components/Search/SearchAutocompleteList'; import type {SearchColumnType, SearchGroupBy, SearchQueryJSON} from '@components/Search/types'; import type {ForwardedFSClassProps} from '@libs/Fullstory/types'; @@ -690,6 +691,8 @@ type TransactionListItemProps = ListItemProps & { customCardNames?: Record; /** Callback to fire when DEW modal should be opened */ onDEWModalOpen?: () => void; + /** Callback to fire when hold menu should be opened */ + onHoldMenuOpen?: HoldMenuCallback; /** Whether the DEW beta flag is enabled */ isDEWBetaEnabled?: boolean; /** The last payment method used per policy */ @@ -719,6 +722,9 @@ type ExpenseReportListItemProps = ListItemProps & /** Callback to fire when DEW modal should be opened */ onDEWModalOpen?: () => void; + /** Callback to fire when hold menu should be opened */ + onHoldMenuOpen?: HoldMenuCallback; + /** Whether the DEW beta flag is enabled */ isDEWBetaEnabled?: boolean; @@ -739,6 +745,8 @@ type TransactionGroupListItemProps = ListItemProps | undefined; /** Callback to fire when DEW modal should be opened */ onDEWModalOpen?: () => void; + /** Callback to fire when hold menu should be opened */ + onHoldMenuOpen?: HoldMenuCallback; /** Whether the DEW beta flag is enabled */ isDEWBetaEnabled?: boolean; /** The last payment method used per policy */ diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 31907d214b8e..c2b4467a47b7 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -1988,12 +1988,7 @@ function getActions( const isAllowedToApproveExpenseReport = isAllowedToApproveExpenseReportUtils(report, submitToAccountID, policy); // We're not supporting approve partial amount on search page now - if ( - canApproveIOU(report, policy, reportMetadata, allReportTransactions) && - isAllowedToApproveExpenseReport && - !hasOnlyPendingCardOrScanningTransactions && - !hasHeldExpenses(report.reportID, allReportTransactions) - ) { + if (canApproveIOU(report, policy, reportMetadata, allReportTransactions) && isAllowedToApproveExpenseReport && !hasOnlyPendingCardOrScanningTransactions) { allActions.push(CONST.SEARCH.ACTION_TYPES.APPROVE); } diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 7054ed988356..f35ccabe6fc0 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -7,6 +7,7 @@ import type {FormOnyxValues} from '@components/Form/types'; import type {ContinueActionParams, PaymentMethod, PaymentMethodType} from '@components/KYCWall/types'; import type {LocaleContextProps, LocalizedTranslate} from '@components/LocaleContextProvider'; import type {PopoverMenuItem} from '@components/PopoverMenu'; +import type {HoldMenuCallback} from '@components/Search'; import type {BankAccountMenuItem, BulkPaySelectionData, PaymentData, SearchQueryJSON, SelectedReports, SelectedTransactionInfo, SelectedTransactions} from '@components/Search/types'; import type {TransactionListItemType, TransactionReportGroupListItemType} from '@components/SelectionListWithSections/types'; import * as API from '@libs/API'; @@ -98,6 +99,7 @@ type HandleActionButtonPressParams = { lastPaymentMethod: OnyxEntry; currentSearchKey?: SearchKey; onDEWModalOpen?: () => void; + onHoldMenuOpen?: HoldMenuCallback; isDEWBetaEnabled?: boolean; isDelegateAccessRestricted?: boolean; onDelegateAccessRestricted?: () => void; @@ -129,6 +131,7 @@ function handleActionButtonPress({ lastPaymentMethod, currentSearchKey, onDEWModalOpen, + onHoldMenuOpen, isDEWBetaEnabled, isDelegateAccessRestricted, onDelegateAccessRestricted, @@ -139,7 +142,7 @@ function handleActionButtonPress({ const allReportTransactions = (isTransactionGroupListItemType(item) ? item.transactions : [item]) as Transaction[]; const hasHeldExpense = hasHeldExpenses('', allReportTransactions); - if (hasHeldExpense && item.action !== CONST.SEARCH.ACTION_TYPES.SUBMIT) { + if (hasHeldExpense && item.action !== CONST.SEARCH.ACTION_TYPES.SUBMIT && item.action !== CONST.SEARCH.ACTION_TYPES.APPROVE) { goToItem(); return; } @@ -169,6 +172,10 @@ function handleActionButtonPress({ onDEWModalOpen?.(); return; } + if (hasHeldExpense) { + onHoldMenuOpen?.(item as TransactionReportGroupListItemType, CONST.IOU.REPORT_ACTION_TYPE.APPROVE); + return; + } approveMoneyRequestOnSearch(hash, item.reportID ? [item.reportID] : [], currentSearchKey); return; case CONST.SEARCH.ACTION_TYPES.SUBMIT: { From 2b784e87658491b7d6aa0a7f61ac2726dd7f6f18 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 13 Mar 2026 14:36:41 +0700 Subject: [PATCH 2/8] update test --- tests/unit/Search/handleActionButtonPressTest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/Search/handleActionButtonPressTest.ts b/tests/unit/Search/handleActionButtonPressTest.ts index 44a9c55d3e53..dfb6ec6259a2 100644 --- a/tests/unit/Search/handleActionButtonPressTest.ts +++ b/tests/unit/Search/handleActionButtonPressTest.ts @@ -315,7 +315,7 @@ describe('handleActionButtonPress', () => { const snapshotReport = mockSnapshotForItem?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${mockReportItemWithHold.reportID}`] ?? {}; const snapshotPolicy = mockSnapshotForItem?.data?.[`${ONYXKEYS.COLLECTION.POLICY}${mockReportItemWithHold.policyID}`] ?? {}; - test('Should navigate to item when report has one transaction on hold', () => { + test('Should not navigate to item when report has one transaction on hold and action is approve', () => { const goToItem = jest.fn(() => {}); handleActionButtonPress({ hash: searchHash, @@ -326,7 +326,7 @@ describe('handleActionButtonPress', () => { lastPaymentMethod: mockLastPaymentMethod, personalPolicyID: undefined, }); - expect(goToItem).toHaveBeenCalledTimes(1); + expect(goToItem).not.toHaveBeenCalled(); }); test('Should not navigate to item when the hold is removed', () => { From 63ee984b8a07db8545b1f605f8798f65e417ba3d Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 18 Mar 2026 13:52:54 +0700 Subject: [PATCH 3/8] update holdMenuParams to a ref --- src/components/Search/index.tsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 051ddd582676..4f0f2c3d430e 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -1567,18 +1567,18 @@ function Search({ customCardNames={customCardNames} onHoldMenuOpen={handleHoldMenuOpen} /> - {isHoldMenuVisible && !!holdMenuParams && ( + {isHoldMenuVisible && !!holdMenuParams.current && ( setIsHoldMenuVisible(false)} - chatReport={holdMenuParams.chatReport} - fullAmount={holdMenuParams.fullAmount} - moneyRequestReport={holdMenuParams.moneyRequestReport} - transactionCount={holdMenuParams.transactionCount} - hasNonHeldExpenses={holdMenuParams?.hasNoneHeldExpenses} - nonHeldAmount={holdMenuParams.hasNoneHeldExpenses && holdMenuParams.hasValidNonHeldAmount ? holdMenuParams.nonHeldAmount : undefined} - requestType={holdMenuParams.requestType} - paymentType={holdMenuParams.paymentType} + chatReport={holdMenuParams.current.chatReport} + fullAmount={holdMenuParams.current.fullAmount} + moneyRequestReport={holdMenuParams.current.moneyRequestReport} + transactionCount={holdMenuParams.current.transactionCount} + hasNonHeldExpenses={holdMenuParams.current?.hasNoneHeldExpenses} + nonHeldAmount={holdMenuParams.current.hasNoneHeldExpenses && holdMenuParams.current.hasValidNonHeldAmount ? holdMenuParams.current.nonHeldAmount : undefined} + requestType={holdMenuParams.current.requestType} + paymentType={holdMenuParams.current.paymentType} /> )} From b19bbafde1c4ac335f087d073d6d9f2f1ea26683 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 25 Mar 2026 15:48:25 +0700 Subject: [PATCH 4/8] add unit test --- .../unit/Search/handleActionButtonPressTest.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/unit/Search/handleActionButtonPressTest.ts b/tests/unit/Search/handleActionButtonPressTest.ts index 1625685003ad..39843f7c088b 100644 --- a/tests/unit/Search/handleActionButtonPressTest.ts +++ b/tests/unit/Search/handleActionButtonPressTest.ts @@ -330,6 +330,23 @@ describe('handleActionButtonPress', () => { expect(goToItem).not.toHaveBeenCalled(); }); + test('Should open the hold menu when the report has one transaction on hold and action is approve', () => { + const onHoldMenuOpen = jest.fn(); + handleActionButtonPress({ + hash: searchHash, + item: mockReportItemWithHold, + goToItem: jest.fn(), + snapshotReport: snapshotReport as Report, + snapshotPolicy: snapshotPolicy as Policy, + lastPaymentMethod: mockLastPaymentMethod, + personalPolicyID: undefined, + userBillingGraceEndPeriods: undefined, + onHoldMenuOpen, + }); + + expect(onHoldMenuOpen).toHaveBeenCalledWith(mockReportItemWithHold, CONST.IOU.REPORT_ACTION_TYPE.APPROVE); + }); + test('Should not navigate to item when the hold is removed', () => { const goToItem = jest.fn(() => {}); handleActionButtonPress({ From f2a300e49fce6ce9677b8eb38779ec80ff00ead3 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 25 Mar 2026 15:59:51 +0700 Subject: [PATCH 5/8] goToItem when onHoldMenuOpen callback is undefined --- src/libs/actions/Search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index bc0205cee307..16f04442f548 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -149,7 +149,7 @@ function handleActionButtonPress({ const allReportTransactions = (isTransactionGroupListItemType(item) ? item.transactions : [item]) as Transaction[]; const hasHeldExpense = hasHeldExpenses('', allReportTransactions); - if (hasHeldExpense && item.action !== CONST.SEARCH.ACTION_TYPES.SUBMIT && item.action !== CONST.SEARCH.ACTION_TYPES.APPROVE) { + if (hasHeldExpense && item.action !== CONST.SEARCH.ACTION_TYPES.SUBMIT && (item.action !== CONST.SEARCH.ACTION_TYPES.APPROVE || !onHoldMenuOpen)) { goToItem(); return; } From 100c4d48a9c2fa83dc828472a2c5c79536dc1dd6 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 25 Mar 2026 16:15:46 +0700 Subject: [PATCH 6/8] update test --- tests/unit/Search/handleActionButtonPressTest.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/Search/handleActionButtonPressTest.ts b/tests/unit/Search/handleActionButtonPressTest.ts index 39843f7c088b..a729c51c5fff 100644 --- a/tests/unit/Search/handleActionButtonPressTest.ts +++ b/tests/unit/Search/handleActionButtonPressTest.ts @@ -326,6 +326,7 @@ describe('handleActionButtonPress', () => { lastPaymentMethod: mockLastPaymentMethod, personalPolicyID: undefined, userBillingGraceEndPeriods: undefined, + onHoldMenuOpen: jest.fn(), }); expect(goToItem).not.toHaveBeenCalled(); }); From 6c99580182d401ec3b5c0c3fc6b6a02a5fb21522 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 29 Apr 2026 14:46:57 +0700 Subject: [PATCH 7/8] fix ts --- tests/unit/Search/handleActionButtonPressTest.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/unit/Search/handleActionButtonPressTest.ts b/tests/unit/Search/handleActionButtonPressTest.ts index e39460f946e4..4742cd6478c7 100644 --- a/tests/unit/Search/handleActionButtonPressTest.ts +++ b/tests/unit/Search/handleActionButtonPressTest.ts @@ -343,7 +343,9 @@ describe('handleActionButtonPress', () => { snapshotPolicy: snapshotPolicy as Policy, lastPaymentMethod: mockLastPaymentMethod, personalPolicyID: undefined, - userBillingGraceEndPeriods: undefined, + userBillingGracePeriodEnds: undefined, + ownerBillingGracePeriodEnd: undefined, + amountOwed: undefined, onHoldMenuOpen, }); From 07e8c4ee9fdf347923e6f0ab768c001a5bd6bb1e Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 5 May 2026 10:32:24 +0700 Subject: [PATCH 8/8] fix eslint --- src/components/Search/index.tsx | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 46793b8045a3..d988ff78333d 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -300,7 +300,7 @@ function Search({ const navigation = useNavigation>(); const isFocused = useIsFocused(); const [isHoldMenuVisible, setIsHoldMenuVisible] = useState(false); - const holdMenuParams = useRef<{ + const [holdMenuParams, setHoldMenuParams] = useState<{ chatReport: OnyxEntry; fullAmount: string; moneyRequestReport: OnyxEntry; @@ -376,7 +376,7 @@ function Search({ const chatReport = searchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${item.parentReportID}`]; const moneyRequestReport = searchResults?.data?.[`${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`]; const {nonHeldAmount, fullAmount, hasValidNonHeldAmount} = getNonHeldAndFullAmount(moneyRequestReport, item.allActions?.includes(CONST.SEARCH.ACTION_TYPES.PAY) ?? false); - holdMenuParams.current = { + setHoldMenuParams({ chatReport, moneyRequestReport, transactionCount: item.transactionCount ?? 0, @@ -386,7 +386,7 @@ function Search({ nonHeldAmount, hasValidNonHeldAmount, hasNoneHeldExpenses: item.transactions.some((t) => !isOnHold(t)), - }; + }); setIsHoldMenuVisible(true); }, [searchResults?.data], @@ -1773,18 +1773,18 @@ function Search({ nonPersonalAndWorkspaceCards={nonPersonalAndWorkspaceCards} isActionColumnWide={isTask || hasDeletedTransaction} /> - {isHoldMenuVisible && !!holdMenuParams.current && ( + {isHoldMenuVisible && !!holdMenuParams && ( setIsHoldMenuVisible(false)} - chatReport={holdMenuParams.current.chatReport} - fullAmount={holdMenuParams.current.fullAmount} - moneyRequestReport={holdMenuParams.current.moneyRequestReport} - transactionCount={holdMenuParams.current.transactionCount} - hasNonHeldExpenses={holdMenuParams.current?.hasNoneHeldExpenses} - nonHeldAmount={holdMenuParams.current.hasNoneHeldExpenses && holdMenuParams.current.hasValidNonHeldAmount ? holdMenuParams.current.nonHeldAmount : undefined} - requestType={holdMenuParams.current.requestType} - paymentType={holdMenuParams.current.paymentType} + chatReport={holdMenuParams.chatReport} + fullAmount={holdMenuParams.fullAmount} + moneyRequestReport={holdMenuParams.moneyRequestReport} + transactionCount={holdMenuParams.transactionCount} + hasNonHeldExpenses={holdMenuParams?.hasNoneHeldExpenses} + nonHeldAmount={holdMenuParams.hasNoneHeldExpenses && holdMenuParams.hasValidNonHeldAmount ? holdMenuParams.nonHeldAmount : undefined} + requestType={holdMenuParams.requestType} + paymentType={holdMenuParams.paymentType} /> )}