diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 2b959ba4ddb..dadbf88f20b 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -383,9 +383,13 @@ const ROUTES = { }, }, MONEY_REQUEST_HOLD_REASON: { - route: ':type/edit/reason/:transactionID?', - getRoute: (type: ValueOf, transactionID: string, reportID: string, backTo: string) => - `${type}/edit/reason/${transactionID}?backTo=${backTo}&reportID=${reportID}` as const, + route: ':type/edit/reason/:transactionID?/:searchHash?', + getRoute: (type: ValueOf, transactionID: string, reportID: string, backTo: string, searchHash?: number) => { + const route = searchHash + ? (`${type}/edit/reason/${transactionID}/${searchHash}/?backTo=${backTo}&reportID=${reportID}` as const) + : (`${type}/edit/reason/${transactionID}/?backTo=${backTo}&reportID=${reportID}` as const); + return route; + }, }, MONEY_REQUEST_CREATE: { route: ':action/:iouType/start/:transactionID/:reportID', diff --git a/src/components/PromotedActionsBar.tsx b/src/components/PromotedActionsBar.tsx index ee940fe2cf1..4b5977fde19 100644 --- a/src/components/PromotedActionsBar.tsx +++ b/src/components/PromotedActionsBar.tsx @@ -37,6 +37,7 @@ type PromotedActionsType = Record P reportID?: string; isDelegateAccessRestricted: boolean; setIsNoDelegateAccessMenuVisible: (isVisible: boolean) => void; + currentSearchHash?: number; }) => PromotedAction; }; @@ -78,7 +79,7 @@ const PromotedActions = { } }, }), - hold: ({isTextHold, reportAction, reportID, isDelegateAccessRestricted, setIsNoDelegateAccessMenuVisible}) => ({ + hold: ({isTextHold, reportAction, reportID, isDelegateAccessRestricted, setIsNoDelegateAccessMenuVisible, currentSearchHash}) => ({ key: CONST.PROMOTED_ACTIONS.HOLD, icon: Expensicons.Stopwatch, text: Localize.translateLocal(`iou.${isTextHold ? 'hold' : 'unhold'}`), @@ -99,7 +100,7 @@ const PromotedActions = { return; } - ReportUtils.changeMoneyRequestHoldStatus(reportAction, ROUTES.SEARCH_REPORT.getRoute(targetedReportID)); + ReportUtils.changeMoneyRequestHoldStatus(reportAction, ROUTES.SEARCH_REPORT.getRoute(targetedReportID), currentSearchHash); }, }), } satisfies PromotedActionsType; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 584d5d09b68..3cac7d09ad6 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -3136,7 +3136,7 @@ function canHoldUnholdReportAction(reportAction: OnyxInputOrEntry) return {canHoldRequest, canUnholdRequest}; } -const changeMoneyRequestHoldStatus = (reportAction: OnyxEntry, backTo?: string): void => { +const changeMoneyRequestHoldStatus = (reportAction: OnyxEntry, backTo?: string, searchHash?: number): void => { if (!ReportActionsUtils.isMoneyRequestAction(reportAction)) { return; } @@ -3153,11 +3153,13 @@ const changeMoneyRequestHoldStatus = (reportAction: OnyxEntry, bac const policy = allPolicies?.[`${ONYXKEYS.COLLECTION.POLICY}${moneyRequestReport.policyID}`] ?? null; if (isOnHold) { - IOU.unholdRequest(transactionID, reportAction.childReportID ?? ''); + IOU.unholdRequest(transactionID, reportAction.childReportID ?? '', searchHash); } else { const activeRoute = encodeURIComponent(Navigation.getActiveRouteWithoutParams()); - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - Navigation.navigate(ROUTES.MONEY_REQUEST_HOLD_REASON.getRoute(policy?.type ?? CONST.POLICY.TYPE.PERSONAL, transactionID, reportAction.childReportID ?? '', backTo || activeRoute)); + Navigation.navigate( + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + ROUTES.MONEY_REQUEST_HOLD_REASON.getRoute(policy?.type ?? CONST.POLICY.TYPE.PERSONAL, transactionID, reportAction.childReportID ?? '', backTo || activeRoute, searchHash), + ); } }; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index c422313a194..bc553ea86d7 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -65,6 +65,7 @@ import type {ErrorFields, Errors} from '@src/types/onyx/OnyxCommon'; import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type ReportAction from '@src/types/onyx/ReportAction'; import type {OnyxData} from '@src/types/onyx/Request'; +import type {SearchTransaction} from '@src/types/onyx/SearchResults'; import type {Comment, Receipt, ReceiptSource, Routes, SplitShares, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import * as CachedPDFPaths from './CachedPDFPaths'; @@ -7856,7 +7857,7 @@ function adjustRemainingSplitShares(transaction: NonNullable>>, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${searchHash}`, + value: { + data: { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: { + canHold: true, + canUnhold: false, + }, + }, + } as Record>>, + }); + } + API.write( 'HoldRequest', { @@ -7928,7 +7957,7 @@ function putOnHold(transactionID: string, comment: string, reportID: string) { /** * Remove expense from HOLD */ -function unholdRequest(transactionID: string, reportID: string) { +function unholdRequest(transactionID: string, reportID: string, searchHash?: number) { const createdReportAction = ReportUtils.buildOptimisticUnHoldReportAction(); const transactionViolations = allTransactionViolations[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transactionID}`]; @@ -7986,6 +8015,34 @@ function unholdRequest(transactionID: string, reportID: string) { }, ]; + // If we are unholding from the search page, we optimistically update the snapshot data that search uses so that it is kept in sync + if (searchHash) { + optimisticData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${searchHash}`, + value: { + data: { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: { + canHold: true, + canUnhold: false, + }, + }, + } as Record>>, + }); + failureData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${searchHash}`, + value: { + data: { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: { + canHold: false, + canUnhold: true, + }, + }, + } as Record>>, + }); + } + API.write( 'UnHoldRequest', { diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 66c61b134ae..bae2b8382f3 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -22,6 +22,7 @@ import PromotedActionsBar, {PromotedActions} from '@components/PromotedActionsBa import RoomHeaderAvatars from '@components/RoomHeaderAvatars'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; +import {useSearchContext} from '@components/Search/SearchContext'; import Text from '@components/Text'; import useDelegateUserDetails from '@hooks/useDelegateUserDetails'; import useLocalize from '@hooks/useLocalize'; @@ -87,6 +88,7 @@ function ReportDetailsPage({policies, report, route}: ReportDetailsPageProps) { const [parentReportNameValuePairs] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_NAME_VALUE_PAIRS}${report?.parentReportID || '-1'}`); const {reportActions} = usePaginatedReportActions(report.reportID || '-1'); /* eslint-enable @typescript-eslint/prefer-nullish-coalescing */ + const {currentSearchHash} = useSearchContext(); const transactionThreadReportID = useMemo( () => ReportActionsUtils.getOneTransactionThreadReportID(report.reportID, reportActions ?? [], isOffline), @@ -571,6 +573,7 @@ function ReportDetailsPage({policies, report, route}: ReportDetailsPageProps) { reportID: transactionThreadReportID ? report.reportID : moneyRequestAction?.childReportID ?? '-1', isDelegateAccessRestricted, setIsNoDelegateAccessMenuVisible, + currentSearchHash, }), ); } @@ -582,7 +585,18 @@ function ReportDetailsPage({policies, report, route}: ReportDetailsPageProps) { result.push(PromotedActions.share(report, backTo)); return result; - }, [report, moneyRequestAction, canJoin, isExpenseReport, shouldShowHoldAction, canHoldUnholdReportAction.canHoldRequest, transactionThreadReportID, isDelegateAccessRestricted, backTo]); + }, [ + report, + moneyRequestAction, + currentSearchHash, + canJoin, + isExpenseReport, + shouldShowHoldAction, + canHoldUnholdReportAction.canHoldRequest, + transactionThreadReportID, + isDelegateAccessRestricted, + backTo, + ]); const nameSectionExpenseIOU = ( diff --git a/src/pages/iou/HoldReasonPage.tsx b/src/pages/iou/HoldReasonPage.tsx index 82f29acf7d1..7523a0932c4 100644 --- a/src/pages/iou/HoldReasonPage.tsx +++ b/src/pages/iou/HoldReasonPage.tsx @@ -24,6 +24,8 @@ type HoldReasonPageRouteParams = { /** Link to previous page */ backTo: Route; + + searchHash?: number; }; type HoldReasonPageProps = { @@ -34,7 +36,7 @@ type HoldReasonPageProps = { function HoldReasonPage({route}: HoldReasonPageProps) { const {translate} = useLocalize(); - const {transactionID, reportID, backTo} = route.params; + const {transactionID, reportID, backTo, searchHash} = route.params; const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID || -1}`); @@ -51,7 +53,7 @@ function HoldReasonPage({route}: HoldReasonPageProps) { return; } - IOU.putOnHold(transactionID, values.comment, reportID); + IOU.putOnHold(transactionID, values.comment, reportID, searchHash); Navigation.navigate(backTo); };