diff --git a/src/components/Search.tsx b/src/components/Search.tsx index 28c3ae5fdc4b..3d295e72c09e 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -8,6 +8,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as SearchActions from '@libs/actions/Search'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import Log from '@libs/Log'; +import * as ReportUtils from '@libs/ReportUtils'; import * as SearchUtils from '@libs/SearchUtils'; import type {SearchColumnType, SortOrder} from '@libs/SearchUtils'; import Navigation from '@navigation/Navigation'; @@ -34,9 +35,9 @@ type SearchProps = { const sortableSearchTabs: SearchQuery[] = [CONST.TAB_SEARCH.ALL]; -function isReportListItemType(item: TransactionListItemType | ReportListItemType): item is ReportListItemType { - const reportListItem = item as ReportListItemType; - return reportListItem.transactions !== undefined; +function isTransactionListItemType(item: TransactionListItemType | ReportListItemType): item is TransactionListItemType { + const transactionListItem = item as TransactionListItemType; + return transactionListItem.transactionID !== undefined; } function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { @@ -76,11 +77,19 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { return ; } - const openReport = (reportID?: string) => { + const openReport = (item: TransactionListItemType | ReportListItemType) => { + let reportID = isTransactionListItemType(item) ? item.transactionThreadReportID : item.reportID; + if (!reportID) { return; } + // If we're trying to open a legacy transaction without a transaction thread, let's create the thread and navigate the user + if (isTransactionListItemType(item) && reportID === '0' && item.moneyRequestReportActionID) { + reportID = ReportUtils.generateReportID(); + SearchActions.createTransactionThread(hash, item.transactionID, reportID, item.moneyRequestReportActionID); + } + Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(query, reportID)); }; @@ -137,10 +146,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { updateCellsBatchingPeriod={200} ListItem={ListItem} sections={[{data: sortedData, isDisabled: false}]} - onSelectRow={(item) => { - const reportID = isReportListItemType(item) ? item.reportID : item.transactionThreadReportID; - openReport(reportID); - }} + onSelectRow={(item) => openReport(item)} shouldDebounceRowSelect shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()} listHeaderWrapperStyle={[styles.ph9, styles.pv3, styles.pb5]} diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 43f3e2697e8a..bf94de9c52b2 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -4,6 +4,16 @@ import * as API from '@libs/API'; import type {SearchParams} from '@libs/API/parameters'; import {READ_COMMANDS} from '@libs/API/types'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {SearchTransaction} from '@src/types/onyx/SearchResults'; +import * as Report from './Report'; + +let currentUserEmail: string; +Onyx.connect({ + key: ONYXKEYS.SESSION, + callback: (val) => { + currentUserEmail = val?.email ?? ''; + }, +}); function search({hash, query, policyIDs, offset, sortBy, sortOrder}: SearchParams) { const optimisticData: OnyxUpdate[] = [ @@ -32,7 +42,23 @@ function search({hash, query, policyIDs, offset, sortBy, sortOrder}: SearchParam API.read(READ_COMMANDS.SEARCH, {hash, query, offset, policyIDs, sortBy, sortOrder}, {optimisticData, finallyData}); } -export { - // eslint-disable-next-line import/prefer-default-export - search, -}; + +/** + * It's possible that we return legacy transactions that don't have a transaction thread created yet. + * In that case, when users select the search result row, we need to create the transaction thread on the fly and update the search result with the new transactionThreadReport + */ +function createTransactionThread(hash: number, transactionID: string, reportID: string, moneyRequestReportActionID: string) { + Report.openReport(reportID, '', [currentUserEmail], {}, moneyRequestReportActionID); + + const onyxUpdate: Record>> = { + data: { + [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: { + transactionThreadReportID: reportID, + }, + }, + }; + + Onyx.merge(`${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, onyxUpdate); +} + +export {search, createTransactionThread}; diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index c7d63e95fd3d..5189a125db9c 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -151,6 +151,9 @@ type SearchTransaction = { /** The modified MCC Group associated with the transaction */ modifiedMCCGroup?: ValueOf; + + /** The ID of the money request reportAction associated with the transaction */ + moneyRequestReportActionID?: string; }; type SearchAccountDetails = Partial;