From 383ded64c2f4be5d3f7a5a8f998bb27442acef20 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Thu, 6 Nov 2025 00:04:23 +0100 Subject: [PATCH 01/17] deprecate SearchTransaction --- src/types/onyx/SearchResults.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index 9a35938014855..c8dd0d146f5bf 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -218,7 +218,10 @@ type SearchReportAction = { reportName: string; }; -/** Model of transaction search result */ +/** Model of transaction search result + * + * @deprecated - Use Transaction instead + */ type SearchTransaction = { /** The ID of the transaction */ transactionID: string; @@ -469,6 +472,7 @@ type SearchResults = { search: SearchResultsInfo; /** Search results data */ + // eslint-disable-next-line @typescript-eslint/no-deprecated data: PrefixedRecord & Record> & PrefixedRecord> & @@ -492,6 +496,7 @@ export type { ListItemType, ListItemDataType, SearchTask, + // eslint-disable-next-line @typescript-eslint/no-deprecated SearchTransaction, SearchTransactionType, SearchTransactionAction, From cd7f607ef0d14cb400c2c958b63db9c051683613 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Thu, 6 Nov 2025 00:21:41 +0100 Subject: [PATCH 02/17] remove SearchTransaction > isActionLoading --- .../SelectionListWithSections/types.ts | 4 ++++ src/libs/SearchUIUtils.ts | 21 ++++++++++++++++--- src/types/onyx/SearchResults.ts | 3 --- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/components/SelectionListWithSections/types.ts b/src/components/SelectionListWithSections/types.ts index 1e3db7880ca56..dbc49986d1977 100644 --- a/src/components/SelectionListWithSections/types.ts +++ b/src/components/SelectionListWithSections/types.ts @@ -243,6 +243,7 @@ type ListItem = { }; type TransactionListItemType = ListItem & + // eslint-disable-next-line @typescript-eslint/no-deprecated SearchTransaction & { /** Report to which the transaction belongs */ report: Report | undefined; @@ -309,6 +310,9 @@ type TransactionListItemType = ListItem & /** The available actions that can be performed for the transaction */ allActions: SearchTransactionAction[]; + + /** Whether the action is loading */ + isActionLoading?: boolean; }; type ReportActionListItemType = ListItem & diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 089b26a4ab320..aae4d999e886c 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -615,6 +615,7 @@ function getSuggestedSearchesVisibility( * Returns a list of properties that are common to every Search ListItem */ function getTransactionItemCommonFormattedProperties( + // eslint-disable-next-line @typescript-eslint/no-deprecated transactionItem: SearchTransaction, from: SearchPersonalDetails, to: SearchPersonalDetails, @@ -763,12 +764,14 @@ function isAmountTooLong(amount: number, maxLength = 8): boolean { return Math.abs(amount).toString().length >= maxLength; } +// eslint-disable-next-line @typescript-eslint/no-deprecated function isTransactionAmountTooLong(transactionItem: TransactionListItemType | SearchTransaction | OnyxTypes.Transaction) { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const amount = Math.abs(transactionItem.modifiedAmount || transactionItem.amount); return isAmountTooLong(amount); } +// eslint-disable-next-line @typescript-eslint/no-deprecated function isTransactionTaxAmountTooLong(transactionItem: TransactionListItemType | SearchTransaction | OnyxTypes.Transaction) { const reportType = (transactionItem as TransactionListItemType)?.reportType; const isFromExpenseReport = reportType === CONST.REPORT.TYPE.EXPENSE; @@ -783,6 +786,7 @@ function getWideAmountIndicators(data: TransactionListItemType[] | TransactionGr let isAmountWide = false; let isTaxAmountWide = false; + // eslint-disable-next-line @typescript-eslint/no-deprecated const processTransaction = (transaction: TransactionListItemType | SearchTransaction) => { isAmountWide ||= isTransactionAmountTooLong(transaction); isTaxAmountWide ||= isTransactionTaxAmountTooLong(transaction); @@ -906,6 +910,7 @@ function getIOUReportName(data: OnyxTypes.SearchResults['data'], reportItem: Tra function getTransactionViolations( allViolations: OnyxCollection, + // eslint-disable-next-line @typescript-eslint/no-deprecated transaction: SearchTransaction, currentUserEmail: string, ): OnyxTypes.TransactionViolation[] { @@ -1037,10 +1042,15 @@ function getTransactionsSections( * Retrieves all transactions associated with a specific report ID from the search data. */ +// eslint-disable-next-line @typescript-eslint/no-deprecated function getTransactionsForReport(data: OnyxTypes.SearchResults['data'], reportID: string): SearchTransaction[] { - return Object.entries(data) - .filter(([key, value]) => isTransactionEntry(key) && (value as SearchTransaction)?.reportID === reportID) - .map(([, value]) => value as SearchTransaction); + return ( + Object.entries(data) + // eslint-disable-next-line @typescript-eslint/no-deprecated + .filter(([key, value]) => isTransactionEntry(key) && (value as SearchTransaction)?.reportID === reportID) + // eslint-disable-next-line @typescript-eslint/no-deprecated + .map(([, value]) => value as SearchTransaction) + ); } /** @@ -1132,6 +1142,7 @@ function getActions( } const allActions: SearchTransactionAction[] = []; + // eslint-disable-next-line @typescript-eslint/no-deprecated let allReportTransactions: SearchTransaction[]; if (isReportEntry(key)) { allReportTransactions = getTransactionsForReport(data, report.reportID); @@ -1806,6 +1817,7 @@ function isSearchResultsEmpty(searchResults: SearchResults, groupBy?: SearchGrou return !Object.keys(searchResults?.data).some( (key) => key.startsWith(ONYXKEYS.COLLECTION.TRANSACTION) && + // eslint-disable-next-line @typescript-eslint/no-deprecated (searchResults?.data[key as keyof typeof searchResults.data] as SearchTransaction)?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, ); } @@ -2303,6 +2315,7 @@ function getColumnsToShow( [CONST.SEARCH.TABLE_COLUMNS.TITLE]: true, }; + // eslint-disable-next-line @typescript-eslint/no-deprecated const updateColumns = (transaction: OnyxTypes.Transaction | SearchTransaction) => { const merchant = transaction.modifiedMerchant ? transaction.modifiedMerchant : (transaction.merchant ?? ''); if ((merchant !== '' && merchant !== CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT) || isScanning(transaction)) { @@ -2330,11 +2343,13 @@ function getColumnsToShow( // Handle From&To columns that are only shown in the Reports page // if From or To differ from current user in any transaction, show the columns + // eslint-disable-next-line @typescript-eslint/no-deprecated const accountID = (transaction as SearchTransaction).accountID; if (accountID !== currentAccountID) { columns[CONST.REPORT.TRANSACTION_LIST.COLUMNS.FROM] = true; } + // eslint-disable-next-line @typescript-eslint/no-deprecated const managerID = (transaction as SearchTransaction).managerID; if (managerID && managerID !== currentAccountID && !columns[CONST.REPORT.TRANSACTION_LIST.COLUMNS.TO]) { const report = (data as OnyxTypes.SearchResults['data'])[`${ONYXKEYS.COLLECTION.REPORT}${transaction.reportID}`]; diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index c8dd0d146f5bf..9923f8e20b2f7 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -337,9 +337,6 @@ type SearchTransaction = { /** Whether the transaction report has only a single transaction */ isFromOneTransactionReport?: boolean; - /** Whether the action is loading */ - isActionLoading?: boolean; - /** Whether the transaction has violations or errors */ errors?: OnyxCommon.Errors; From 534df38c921ad723b6f35c356fe3209d742139d1 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Thu, 6 Nov 2025 00:38:53 +0100 Subject: [PATCH 03/17] remove isActionLoading use in tests --- tests/unit/Search/SearchUIUtilsTest.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 473d884feb134..c32a2844d783e 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -410,7 +410,6 @@ const searchResults: OnyxTypes.SearchResults = { moneyRequestReportActionID: '789', errors: undefined, filename: undefined, - isActionLoading: false, convertedAmount: -5000, convertedCurrency: 'USD', }, @@ -454,7 +453,6 @@ const searchResults: OnyxTypes.SearchResults = { pendingAction: undefined, errors: undefined, filename: undefined, - isActionLoading: false, convertedAmount: -5000, convertedCurrency: 'USD', }, @@ -498,7 +496,6 @@ const searchResults: OnyxTypes.SearchResults = { pendingAction: undefined, errors: undefined, filename: undefined, - isActionLoading: false, hasViolation: undefined, convertedAmount: -5000, convertedCurrency: 'USD', @@ -542,7 +539,6 @@ const searchResults: OnyxTypes.SearchResults = { pendingAction: undefined, errors: undefined, filename: undefined, - isActionLoading: false, hasViolation: undefined, convertedAmount: -5000, convertedCurrency: 'USD', @@ -852,7 +848,6 @@ const transactionsListItems = [ moneyRequestReportActionID: '789', errors: undefined, filename: undefined, - isActionLoading: false, hasViolation: false, violations: [], convertedAmount: -5000, @@ -921,7 +916,6 @@ const transactionsListItems = [ pendingAction: undefined, errors: undefined, filename: undefined, - isActionLoading: false, hasViolation: true, violations: [ { @@ -995,7 +989,6 @@ const transactionsListItems = [ pendingAction: undefined, errors: undefined, filename: undefined, - isActionLoading: false, hasViolation: undefined, violations: [], convertedAmount: -5000, @@ -1064,7 +1057,6 @@ const transactionsListItems = [ pendingAction: undefined, errors: undefined, filename: undefined, - isActionLoading: false, hasViolation: undefined, violations: [], convertedAmount: -5000, @@ -1171,7 +1163,6 @@ const transactionReportGroupListItems = [ moneyRequestReportActionID: '789', errors: undefined, filename: undefined, - isActionLoading: false, violations: [], convertedAmount: -5000, convertedCurrency: 'USD', @@ -1284,7 +1275,6 @@ const transactionReportGroupListItems = [ pendingAction: undefined, errors: undefined, filename: undefined, - isActionLoading: false, convertedAmount: -5000, convertedCurrency: 'USD', }, From 481caafbfe3bfea275e371d1f196632dc2dc0b5b Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Thu, 6 Nov 2025 00:46:11 +0100 Subject: [PATCH 04/17] remove isActionLoading from TransactionListItemType --- src/components/SelectionListWithSections/types.ts | 3 --- src/libs/SearchUIUtils.ts | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/SelectionListWithSections/types.ts b/src/components/SelectionListWithSections/types.ts index dbc49986d1977..1a0e22d34d4f2 100644 --- a/src/components/SelectionListWithSections/types.ts +++ b/src/components/SelectionListWithSections/types.ts @@ -310,9 +310,6 @@ type TransactionListItemType = ListItem & /** The available actions that can be performed for the transaction */ allActions: SearchTransactionAction[]; - - /** Whether the action is loading */ - isActionLoading?: boolean; }; type ReportActionListItemType = ListItem & diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index aae4d999e886c..e37ed6fa6a2ef 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -981,6 +981,8 @@ function getTransactionsSections( const report = data[`${ONYXKEYS.COLLECTION.REPORT}${transactionItem.reportID}`]; let shouldShow = true; + + // isActionLoading is coming from onyx, should we move this to transactions_metadata? if (queryJSON && !transactionItem.isActionLoading) { if (queryJSON.type === CONST.SEARCH.DATA_TYPES.EXPENSE) { const status = queryJSON.status; From 1ea269c1ed3719b20e1b0688193413e792dba23c Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sat, 15 Nov 2025 22:47:19 +0100 Subject: [PATCH 05/17] deprecate SearchTransaction --- src/types/onyx/SearchResults.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/types/onyx/SearchResults.ts b/src/types/onyx/SearchResults.ts index 619171ef0ae6e..dbee8217a38f2 100644 --- a/src/types/onyx/SearchResults.ts +++ b/src/types/onyx/SearchResults.ts @@ -156,7 +156,10 @@ type SearchReport = { pendingAction?: OnyxCommon.PendingAction; }; -/** Model of transaction search result */ +/** Model of transaction search result + * + * @deprecated - Use Transaction instead + */ type SearchTransaction = { /** The ID of the transaction */ transactionID: string; From b957136399f2d12f9f2a2a504b11f236ab8cfc79 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sat, 15 Nov 2025 22:48:05 +0100 Subject: [PATCH 06/17] better type --- src/selectors/ReportMetaData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/selectors/ReportMetaData.ts b/src/selectors/ReportMetaData.ts index 5d05a2bbb43b5..8bd9dd983e150 100644 --- a/src/selectors/ReportMetaData.ts +++ b/src/selectors/ReportMetaData.ts @@ -1,7 +1,7 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import type {ReportMetadata} from '@src/types/onyx'; -const isActionLoadingSelector = (reportMetadata: OnyxEntry | undefined) => reportMetadata?.isActionLoading ?? false; +const isActionLoadingSelector = (reportMetadata: OnyxEntry) => reportMetadata?.isActionLoading ?? false; const isActionLoadingSetSelector = (all: OnyxCollection): ReadonlySet => { const ids = new Set(); From 3687c4dd2b7d51640623d10e3770ad8ab817bae5 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sat, 15 Nov 2025 22:56:50 +0100 Subject: [PATCH 07/17] add transaction metadata --- src/ONYXKEYS.ts | 2 ++ src/types/onyx/TransactionMetadata.ts | 7 +++++++ src/types/onyx/index.ts | 2 ++ 3 files changed, 11 insertions(+) create mode 100644 src/types/onyx/TransactionMetadata.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 22af17fee262f..e58b6c7de1005 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -648,6 +648,7 @@ const ONYXKEYS = { TRANSACTION: 'transactions_', TRANSACTION_VIOLATIONS: 'transactionViolations_', TRANSACTION_DRAFT: 'transactionsDraft_', + TRANSACTION_METADATA: 'transactionMetadata_', SKIP_CONFIRMATION: 'skipConfirmation_', TRANSACTION_BACKUP: 'transactionsBackup_', SPLIT_TRANSACTION_DRAFT: 'splitTransactionDraft_', @@ -1068,6 +1069,7 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.SECURITY_GROUP]: OnyxTypes.SecurityGroup; [ONYXKEYS.COLLECTION.TRANSACTION]: OnyxTypes.Transaction; [ONYXKEYS.COLLECTION.TRANSACTION_DRAFT]: OnyxTypes.Transaction; + [ONYXKEYS.COLLECTION.TRANSACTION_METADATA]: OnyxTypes.TransactionMetadata; [ONYXKEYS.COLLECTION.SKIP_CONFIRMATION]: boolean; [ONYXKEYS.COLLECTION.TRANSACTION_BACKUP]: OnyxTypes.Transaction; [ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS]: OnyxTypes.TransactionViolations; diff --git a/src/types/onyx/TransactionMetadata.ts b/src/types/onyx/TransactionMetadata.ts new file mode 100644 index 0000000000000..dfbfade983bae --- /dev/null +++ b/src/types/onyx/TransactionMetadata.ts @@ -0,0 +1,7 @@ +/** Model of transaction metadata */ +type TransactionMetadata = { + /** Whether an action is loading */ + isActionLoading?: boolean; +}; + +export default TransactionMetadata; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 4fd8c653057d7..34642e55f982d 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -112,6 +112,7 @@ import type StripeCustomerID from './StripeCustomerID'; import type SupportalPermissionDenied from './SupportalPermissionDenied'; import type Task from './Task'; import type Transaction from './Transaction'; +import type TransactionMetadata from './TransactionMetadata'; import type {TransactionViolation, ViolationName} from './TransactionViolation'; import type TransactionViolations from './TransactionViolation'; import type TravelProvisioning from './TravelProvisioning'; @@ -286,4 +287,5 @@ export type { BillingReceiptDetails, ExportTemplate, HybridApp, + TransactionMetadata, }; From b63740a4e088fc04f75c0b9dce0040c58d372979 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sun, 16 Nov 2025 00:11:48 +0100 Subject: [PATCH 08/17] Revert "add transaction metadata" This reverts commit 3687c4dd2b7d51640623d10e3770ad8ab817bae5. --- src/ONYXKEYS.ts | 2 -- src/types/onyx/TransactionMetadata.ts | 7 ------- src/types/onyx/index.ts | 2 -- 3 files changed, 11 deletions(-) delete mode 100644 src/types/onyx/TransactionMetadata.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index e58b6c7de1005..22af17fee262f 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -648,7 +648,6 @@ const ONYXKEYS = { TRANSACTION: 'transactions_', TRANSACTION_VIOLATIONS: 'transactionViolations_', TRANSACTION_DRAFT: 'transactionsDraft_', - TRANSACTION_METADATA: 'transactionMetadata_', SKIP_CONFIRMATION: 'skipConfirmation_', TRANSACTION_BACKUP: 'transactionsBackup_', SPLIT_TRANSACTION_DRAFT: 'splitTransactionDraft_', @@ -1069,7 +1068,6 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.SECURITY_GROUP]: OnyxTypes.SecurityGroup; [ONYXKEYS.COLLECTION.TRANSACTION]: OnyxTypes.Transaction; [ONYXKEYS.COLLECTION.TRANSACTION_DRAFT]: OnyxTypes.Transaction; - [ONYXKEYS.COLLECTION.TRANSACTION_METADATA]: OnyxTypes.TransactionMetadata; [ONYXKEYS.COLLECTION.SKIP_CONFIRMATION]: boolean; [ONYXKEYS.COLLECTION.TRANSACTION_BACKUP]: OnyxTypes.Transaction; [ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS]: OnyxTypes.TransactionViolations; diff --git a/src/types/onyx/TransactionMetadata.ts b/src/types/onyx/TransactionMetadata.ts deleted file mode 100644 index dfbfade983bae..0000000000000 --- a/src/types/onyx/TransactionMetadata.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** Model of transaction metadata */ -type TransactionMetadata = { - /** Whether an action is loading */ - isActionLoading?: boolean; -}; - -export default TransactionMetadata; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 34642e55f982d..4fd8c653057d7 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -112,7 +112,6 @@ import type StripeCustomerID from './StripeCustomerID'; import type SupportalPermissionDenied from './SupportalPermissionDenied'; import type Task from './Task'; import type Transaction from './Transaction'; -import type TransactionMetadata from './TransactionMetadata'; import type {TransactionViolation, ViolationName} from './TransactionViolation'; import type TransactionViolations from './TransactionViolation'; import type TravelProvisioning from './TravelProvisioning'; @@ -287,5 +286,4 @@ export type { BillingReceiptDetails, ExportTemplate, HybridApp, - TransactionMetadata, }; From 2253f7a29bf5551bcd020c90771a524c3901ba25 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sun, 16 Nov 2025 01:31:43 +0100 Subject: [PATCH 09/17] clean up search actions --- src/libs/actions/Search.ts | 321 +++++++++++++++++--------------- src/pages/Search/SearchPage.tsx | 10 +- 2 files changed, 179 insertions(+), 152 deletions(-) diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index d1e831c6a9ebc..45a2e54b02652 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -98,14 +98,14 @@ function handleActionButtonPress( onDEWModalOpen?.(); return; } - approveMoneyRequestOnSearch(hash, [item.reportID], transactionID, currentSearchKey); + approveMoneyRequestOnSearch(hash, [item.reportID], currentSearchKey); return; case CONST.SEARCH.ACTION_TYPES.SUBMIT: { if (hasDynamicExternalWorkflow(snapshotPolicy)) { onDEWModalOpen?.(); return; } - submitMoneyRequestOnSearch(hash, [item], [snapshotPolicy], transactionID, currentSearchKey); + submitMoneyRequestOnSearch(hash, [item], [snapshotPolicy], currentSearchKey); return; } case CONST.SEARCH.ACTION_TYPES.EXPORT_TO_ACCOUNTING: { @@ -192,16 +192,15 @@ function getPayActionCallback( } const amount = Math.abs((snapshotReport?.total ?? 0) - (snapshotReport?.nonReimbursableTotal ?? 0)); - const transactionID = isTransactionListItemType(item) ? [item.transactionID] : undefined; if (lastPolicyPaymentMethod === CONST.IOU.PAYMENT_TYPE.ELSEWHERE) { - payMoneyRequestOnSearch(hash, [{reportID: item.reportID, amount, paymentType: lastPolicyPaymentMethod}], transactionID, currentSearchKey); + payMoneyRequestOnSearch(hash, [{reportID: item.reportID, amount, paymentType: lastPolicyPaymentMethod}], currentSearchKey); return; } const hasVBBA = !!snapshotPolicy?.achAccount?.bankAccountID; if (hasVBBA) { - payMoneyRequestOnSearch(hash, [{reportID: item.reportID, amount, paymentType: lastPolicyPaymentMethod}], transactionID, currentSearchKey); + payMoneyRequestOnSearch(hash, [{reportID: item.reportID, amount, paymentType: lastPolicyPaymentMethod}], currentSearchKey); return; } @@ -452,45 +451,48 @@ function holdMoneyRequestOnSearch(hash: number, transactionIDList: string[], com } // eslint-disable-next-line @typescript-eslint/no-deprecated -function submitMoneyRequestOnSearch(hash: number, reportList: SearchReport[], policy: Policy[], transactionIDList?: string[], currentSearchKey?: SearchKey) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - const createOnyxData = (update: Partial | Partial | null, shouldRemoveReportFromView = false): OnyxUpdate[] => { - // eslint-disable-next-line @typescript-eslint/no-deprecated - let data: Partial | Partial | undefined; - - if (transactionIDList) { - data = Object.fromEntries(transactionIDList.map((transactionID) => [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, update])) as Partial; - } else if (shouldRemoveReportFromView) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - data = Object.fromEntries(reportList.map((report) => [`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, null])) as Partial; - } +function submitMoneyRequestOnSearch(hash: number, reportList: SearchReport[], policy: Policy[], currentSearchKey?: SearchKey) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT_METADATA, + value: Object.fromEntries(reportList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {isActionLoading: true}])), + }, + ]; - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, - value: { - data, - }, + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT_METADATA, + value: Object.fromEntries(reportList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {isActionLoading: false}])), + }, + ]; + + // If we are on the 'Submit' suggested search, remove the report from the view once the action is taken, don't wait for the view to be re-fetched via Search + if (currentSearchKey === CONST.SEARCH.SEARCH_KEYS.SUBMIT) { + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, + value: { + data: Object.fromEntries(reportList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, null])), }, - ]; - reportList.forEach((report) => { - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${report.reportID}`, - value: { - ...update, - }, - }); }); + } - return optimisticData; - }; - - const optimisticData: OnyxUpdate[] = createOnyxData({isActionLoading: true}); - const failureData: OnyxUpdate[] = createOnyxData({isActionLoading: false}); - // If we are on the 'Submit' suggested search, remove the report from the view once the action is taken, don't wait for the view to be re-fetched via Search - const successData: OnyxUpdate[] = currentSearchKey === CONST.SEARCH.SEARCH_KEYS.SUBMIT ? createOnyxData({isActionLoading: false}, true) : createOnyxData({isActionLoading: false}); + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT_METADATA, + value: Object.fromEntries(reportList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {isActionLoading: false}])), + }, + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT, + value: Object.fromEntries( + reportList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}]), + ), + }, + ]; // eslint-disable-next-line @typescript-eslint/no-deprecated const report = (reportList.at(0) ?? {}) as SearchReport; @@ -505,48 +507,49 @@ function submitMoneyRequestOnSearch(hash: number, reportList: SearchReport[], po API.write(WRITE_COMMANDS.SUBMIT_REPORT, parameters, {optimisticData, successData, failureData}); } -function approveMoneyRequestOnSearch(hash: number, reportIDList: string[], transactionIDList?: string[], currentSearchKey?: SearchKey) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - const createOnyxData = (update: Partial | Partial | null, shouldRemoveReportFromView = false): OnyxUpdate[] => { - // eslint-disable-next-line @typescript-eslint/no-deprecated - let data: Partial | Partial | undefined; - - if (transactionIDList) { - data = Object.fromEntries(transactionIDList.map((transactionID) => [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, update])) as Partial; - } else if (shouldRemoveReportFromView) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - data = Object.fromEntries(reportIDList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, null])) as Partial; - } - - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, - value: { - data, - }, - }, - ]; - reportIDList.forEach((reportID) => { - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, - value: { - ...update, - }, - }); - }); - - return optimisticData; - }; +function approveMoneyRequestOnSearch(hash: number, reportIDList: string[], currentSearchKey?: SearchKey) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT_METADATA, + value: Object.fromEntries(reportIDList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {isActionLoading: true}])), + }, + ]; - const optimisticData: OnyxUpdate[] = createOnyxData({isActionLoading: true}); - const failureData: OnyxUpdate[] = createOnyxData({isActionLoading: false, errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}); + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT_METADATA, + value: Object.fromEntries(reportIDList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {isActionLoading: false}])), + }, + ]; // If we are on the 'Approve', `Unapproved cash` or the `Unapproved company cards` suggested search, remove the report from the view once the action is taken, don't wait for the view to be re-fetched via Search const approveActionSuggestedSearches: Partial = [CONST.SEARCH.SEARCH_KEYS.APPROVE, CONST.SEARCH.SEARCH_KEYS.UNAPPROVED_CASH, CONST.SEARCH.SEARCH_KEYS.UNAPPROVED_CARD]; + if (approveActionSuggestedSearches.includes(currentSearchKey)) { + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, + value: { + data: Object.fromEntries(reportIDList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, null])), + }, + }); + } - const successData: OnyxUpdate[] = approveActionSuggestedSearches.includes(currentSearchKey) ? createOnyxData({isActionLoading: false}, true) : createOnyxData({isActionLoading: false}); + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT_METADATA, + value: Object.fromEntries(reportIDList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {isActionLoading: false}])), + }, + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT, + value: Object.fromEntries( + reportIDList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}]), + ), + }, + ]; playSound(SOUNDS.SUCCESS); API.write(WRITE_COMMANDS.APPROVE_MONEY_REQUEST_ON_SEARCH, {hash, reportIDList}, {optimisticData, failureData, successData}); @@ -557,42 +560,68 @@ function exportToIntegrationOnSearch(hash: number, reportID: string, connectionN const successAction: OptimisticExportIntegrationAction = {...optimisticAction, pendingAction: null}; const optimisticReportActionID = optimisticAction.reportActionID; - const createOnyxData = (update: Partial | null, reportAction?: OptimisticExportIntegrationAction | null, shouldRemoveReportFromView = false): OnyxUpdate[] => { - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, - value: { - ...update, - }, + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, + value: {isActionLoading: true}, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticReportActionID]: optimisticAction, }, - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, - value: { - [optimisticReportActionID]: reportAction, - }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, + value: {isActionLoading: false}, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticReportActionID]: successAction, }, - ]; - if (shouldRemoveReportFromView) { - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, - value: { - data: { - [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]: null, - }, - }, - }); - } - return optimisticData; - }; + }, + ]; - const optimisticData: OnyxUpdate[] = createOnyxData({isActionLoading: true}, optimisticAction); - const failureData: OnyxUpdate[] = createOnyxData({errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), isActionLoading: false}, null); // If we are on the 'Export' suggested search, remove the report from the view once the action is taken, don't wait for the view to be re-fetched via Search - const successData: OnyxUpdate[] = - currentSearchKey === CONST.SEARCH.SEARCH_KEYS.EXPORT ? createOnyxData({isActionLoading: false}, successAction, true) : createOnyxData({isActionLoading: false}, successAction); + if (currentSearchKey === CONST.SEARCH.SEARCH_KEYS.EXPORT) { + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, + value: { + data: { + [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]: null, + }, + }, + }); + } + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, + value: {isActionLoading: false}, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportID}`, + value: { + [optimisticReportActionID]: null, + }, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, + value: {errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, + }, + ]; const params = { reportIDList: reportID, @@ -606,46 +635,48 @@ function exportToIntegrationOnSearch(hash: number, reportID: string, connectionN API.write(WRITE_COMMANDS.REPORT_EXPORT, params, {optimisticData, failureData, successData}); } -function payMoneyRequestOnSearch(hash: number, paymentData: PaymentData[], transactionIDList?: string[], currentSearchKey?: SearchKey) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - const createOnyxData = (update: Partial | Partial | null, shouldRemoveReportFromView = false): OnyxUpdate[] => { - // eslint-disable-next-line @typescript-eslint/no-deprecated - let data: Partial | Partial | undefined; - - if (transactionIDList) { - data = Object.fromEntries(transactionIDList.map((transactionID) => [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, update])) as Partial; - } else if (shouldRemoveReportFromView) { - // eslint-disable-next-line @typescript-eslint/no-deprecated - data = Object.fromEntries(paymentData.map((item) => [`${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`, null])) as Partial; - } +function payMoneyRequestOnSearch(hash: number, paymentData: PaymentData[], currentSearchKey?: SearchKey) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT_METADATA, + value: Object.fromEntries(paymentData.map((item) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${item.reportID}`, {isActionLoading: true}])), + }, + ]; - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, - value: { - data, - }, - }, - ]; + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT_METADATA, + value: Object.fromEntries(paymentData.map((item) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${item.reportID}`, {isActionLoading: false}])), + }, + ]; - paymentData.forEach((item) => { - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_METADATA}${item.reportID}`, - value: { - ...update, - }, - }); + // If we are on the 'Pay' suggested search, remove the report from the view once the action is taken, don't wait for the view to be re-fetched via Search + if (currentSearchKey === CONST.SEARCH.SEARCH_KEYS.PAY) { + successData.push({ + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, + value: { + data: Object.fromEntries(paymentData.map((item) => [`${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`, null])), + }, }); + } - return optimisticData; - }; - - const optimisticData: OnyxUpdate[] = createOnyxData({isActionLoading: true}); - const failureData: OnyxUpdate[] = createOnyxData({isActionLoading: false, errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}); - // If we are on the 'Pay' suggested search, remove the report from the view once the action is taken, don't wait for the view to be re-fetched via Search - const successData: OnyxUpdate[] = currentSearchKey === CONST.SEARCH.SEARCH_KEYS.PAY ? createOnyxData({isActionLoading: false}, true) : createOnyxData({isActionLoading: false}); + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT_METADATA, + value: Object.fromEntries(paymentData.map((item) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${item.reportID}`, {isActionLoading: false}])), + }, + { + onyxMethod: Onyx.METHOD.MERGE_COLLECTION, + key: ONYXKEYS.COLLECTION.REPORT, + value: Object.fromEntries( + paymentData.map((item) => [`${ONYXKEYS.COLLECTION.REPORT}${item.reportID}`, {errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}]), + ), + }, + ]; // eslint-disable-next-line rulesdir/no-api-side-effects-method API.makeRequestWithSideEffects( diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index 964212e7a1621..445c3df89c17f 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -285,7 +285,7 @@ function SearchPage({route}: SearchPageProps) { })) ) as PaymentData[]; - payMoneyRequestOnSearch(hash, paymentData, transactionIDList); + payMoneyRequestOnSearch(hash, paymentData); // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => { clearSelectedTransactions(); @@ -419,11 +419,10 @@ function SearchPage({route}: SearchPageProps) { return; } - const transactionIDList = selectedReports.length ? undefined : Object.keys(selectedTransactions); const reportIDList = !selectedReports.length ? Object.values(selectedTransactions).map((transaction) => transaction.reportID) : (selectedReports?.filter((report) => !!report).map((report) => report.reportID) ?? []); - approveMoneyRequestOnSearch(hash, reportIDList, transactionIDList); + approveMoneyRequestOnSearch(hash, reportIDList); // eslint-disable-next-line @typescript-eslint/no-deprecated InteractionManager.runAfterInteractions(() => { clearSelectedTransactions(); @@ -456,10 +455,7 @@ function SearchPage({route}: SearchPageProps) { itemList.forEach((item) => { const policy = policies?.[`${ONYXKEYS.COLLECTION.POLICY}${item.policyID}`]; if (policy) { - const reportTransactionIDs = selectedReports.length - ? undefined - : Object.keys(selectedTransactions).filter((id) => selectedTransactions[id].reportID === item.reportID); - submitMoneyRequestOnSearch(hash, [item], [policy], reportTransactionIDs); + submitMoneyRequestOnSearch(hash, [item], [policy]); } }); clearSelectedTransactions(); From 9fc6ecf8cedfe8fa8273022b9c610f05aac8e1a8 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sun, 16 Nov 2025 02:06:10 +0100 Subject: [PATCH 10/17] fix isActionLoading logic --- .../Search/TransactionListItem.tsx | 2 +- .../Search/UserInfoAndActionButtonRow.tsx | 3 +-- src/libs/SearchUIUtils.ts | 11 +++++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/SelectionListWithSections/Search/TransactionListItem.tsx b/src/components/SelectionListWithSections/Search/TransactionListItem.tsx index 18fb5d8c8f89b..159c83b73522f 100644 --- a/src/components/SelectionListWithSections/Search/TransactionListItem.tsx +++ b/src/components/SelectionListWithSections/Search/TransactionListItem.tsx @@ -179,7 +179,7 @@ function TransactionListItem({ onCheckboxPress={handleCheckboxPress} shouldUseNarrowLayout={!isLargeScreenWidth} columns={columns} - isActionLoading={isLoading ?? transactionItem.isActionLoading ?? isActionLoading} + isActionLoading={isLoading ?? isActionLoading} isSelected={!!transactionItem.isSelected} dateColumnSize={dateColumnSize} amountColumnSize={amountColumnSize} diff --git a/src/components/SelectionListWithSections/Search/UserInfoAndActionButtonRow.tsx b/src/components/SelectionListWithSections/Search/UserInfoAndActionButtonRow.tsx index eba0588ee621a..4d514f30a1fb1 100644 --- a/src/components/SelectionListWithSections/Search/UserInfoAndActionButtonRow.tsx +++ b/src/components/SelectionListWithSections/Search/UserInfoAndActionButtonRow.tsx @@ -37,7 +37,6 @@ function UserInfoAndActionButtonRow({ const participantFromDisplayName = item?.from?.displayName ?? item?.from?.login ?? translate('common.hidden'); const participantToDisplayName = item?.to?.displayName ?? item?.to?.login ?? translate('common.hidden'); const shouldShowToRecipient = hasFromSender && hasToRecipient && !!item?.to?.accountID && !!isCorrectSearchUserName(participantToDisplayName); - const isLoading = 'isActionLoading' in item ? item?.isActionLoading : isActionLoading; return ( | undefined, ): TransactionListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); const doesDataContainAPastYearTransaction = shouldShowYear(data); @@ -1018,8 +1019,8 @@ function getTransactionsSections( let shouldShow = true; - // isActionLoading is coming from onyx, should we move this to transactions_metadata? - if (queryJSON && !transactionItem.isActionLoading) { + const isActionLoading = isActionLoadingSet?.has(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${transactionItem.reportID}`); + if (queryJSON && !isActionLoading) { if (queryJSON.type === CONST.SEARCH.DATA_TYPES.EXPENSE) { const status = queryJSON.status; if (Array.isArray(status)) { @@ -1538,7 +1539,9 @@ function getReportSections( const actions = reportActions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${reportItem.reportID}`]; let shouldShow = true; - if (queryJSON && isActionLoadingSet?.has(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportItem.reportID}`)) { + + const isActionLoading = isActionLoadingSet?.has(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportItem.reportID}`); + if (queryJSON && !isActionLoading) { if (queryJSON.type === CONST.SEARCH.DATA_TYPES.EXPENSE) { const status = queryJSON.status; @@ -1789,7 +1792,7 @@ function getSections({ } } - return getTransactionsSections(data, currentSearch, currentAccountID, currentUserEmail, formatPhoneNumber); + return getTransactionsSections(data, currentSearch, currentAccountID, currentUserEmail, formatPhoneNumber, isActionLoadingSet); } /** From 28b80d41468190873b659ac921376db569ce60d4 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sun, 16 Nov 2025 02:33:25 +0100 Subject: [PATCH 11/17] fix tests --- tests/unit/Search/SearchUIUtilsTest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 159a67a73cf50..eea6bd2156276 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -1808,7 +1808,7 @@ describe('SearchUIUtils', () => { expect(distanceTransaction).toBeDefined(); expect(distanceTransaction?.iouRequestType).toBe(CONST.IOU.REQUEST_TYPE.DISTANCE); - const expectedPropertyCount = 53; + const expectedPropertyCount = 52; expect(Object.keys(distanceTransaction ?? {}).length).toBe(expectedPropertyCount); }); @@ -1842,7 +1842,7 @@ describe('SearchUIUtils', () => { expect(distanceTransaction).toBeDefined(); expect(distanceTransaction?.iouRequestType).toBe(CONST.IOU.REQUEST_TYPE.DISTANCE); - const expectedPropertyCount = 53; + const expectedPropertyCount = 52; expect(Object.keys(distanceTransaction ?? {}).length).toBe(expectedPropertyCount); }); From e22450cafc2cdf16b3b54681f489ee7a21559e5b Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sun, 16 Nov 2025 03:02:12 +0100 Subject: [PATCH 12/17] lint --- src/libs/SearchUIUtils.ts | 2 ++ src/libs/actions/Search.ts | 15 +++++++++------ src/pages/Search/SearchPage.tsx | 1 - 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 09307c6d87544..6145d5e02c4f8 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -2476,6 +2476,7 @@ function getColumnsToShow( }; const reportActionsByTransactionIDMap = Array.isArray(data) ? undefined : createReportActionsByTransactionIDMap(data); + // eslint-disable-next-line @typescript-eslint/no-deprecated const updateColumns = (transaction: OnyxTypes.Transaction | SearchTransaction) => { const merchant = transaction.modifiedMerchant ? transaction.modifiedMerchant : (transaction.merchant ?? ''); if ((merchant !== '' && merchant !== CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT) || isScanning(transaction)) { @@ -2514,6 +2515,7 @@ function getColumnsToShow( columns[CONST.REPORT.TRANSACTION_LIST.COLUMNS.FROM] = true; } + // eslint-disable-next-line @typescript-eslint/no-deprecated const toFieldValue = getToFieldValueForTransaction(transaction as SearchTransaction, report, data.personalDetailsList, reportAction); if (toFieldValue.accountID && toFieldValue.accountID !== currentAccountID && !columns[CONST.REPORT.TRANSACTION_LIST.COLUMNS.TO]) { columns[CONST.REPORT.TRANSACTION_LIST.COLUMNS.TO] = !!report && !isOpenReport(report); diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 45a2e54b02652..41eea5586722e 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -41,7 +41,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import {FILTER_KEYS} from '@src/types/form/SearchAdvancedFiltersForm'; import type {SearchAdvancedFiltersForm} from '@src/types/form/SearchAdvancedFiltersForm'; -import type {ExportTemplate, LastPaymentMethod, LastPaymentMethodType, Policy, ReportAction, ReportActions, ReportMetadata, Transaction} from '@src/types/onyx'; +import type {ExportTemplate, LastPaymentMethod, LastPaymentMethodType, Policy, ReportAction, ReportActions, Transaction} from '@src/types/onyx'; import type {PaymentInformation} from '@src/types/onyx/LastPaymentMethod'; import type {ConnectionName} from '@src/types/onyx/Policy'; import type {SearchReport, SearchTransaction} from '@src/types/onyx/SearchResults'; @@ -80,7 +80,7 @@ function handleActionButtonPress( ) { // The transactionIDList is needed to handle actions taken on `status:""` where transactions on single expense reports can be approved/paid. // We need the transactionID to display the loading indicator for that list item's action. - const transactionID = isTransactionListItemType(item) ? [item.transactionID] : undefined; + // eslint-disable-next-line @typescript-eslint/no-deprecated const allReportTransactions = (isTransactionGroupListItemType(item) ? item.transactions : [item]) as SearchTransaction[]; const hasHeldExpense = hasHeldExpenses('', allReportTransactions); @@ -418,6 +418,7 @@ function search({ * 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 updateSearchResultsWithTransactionThreadReportID(hash: number, transactionID: string, reportID: string) { + // eslint-disable-next-line @typescript-eslint/no-deprecated const onyxUpdate: Record>> = { data: { [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`]: { @@ -456,7 +457,7 @@ function submitMoneyRequestOnSearch(hash: number, reportList: SearchReport[], po { onyxMethod: Onyx.METHOD.MERGE_COLLECTION, key: ONYXKEYS.COLLECTION.REPORT_METADATA, - value: Object.fromEntries(reportList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {isActionLoading: true}])), + value: Object.fromEntries(reportList.map((report) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID}`, {isActionLoading: true}])), }, ]; @@ -464,7 +465,7 @@ function submitMoneyRequestOnSearch(hash: number, reportList: SearchReport[], po { onyxMethod: Onyx.METHOD.MERGE_COLLECTION, key: ONYXKEYS.COLLECTION.REPORT_METADATA, - value: Object.fromEntries(reportList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {isActionLoading: false}])), + value: Object.fromEntries(reportList.map((report) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID}`, {isActionLoading: false}])), }, ]; @@ -474,7 +475,7 @@ function submitMoneyRequestOnSearch(hash: number, reportList: SearchReport[], po onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.SNAPSHOT}${hash}`, value: { - data: Object.fromEntries(reportList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, null])), + data: Object.fromEntries(reportList.map((report) => [`${ONYXKEYS.COLLECTION.REPORT}${report?.reportID}`, null])), }, }); } @@ -483,7 +484,7 @@ function submitMoneyRequestOnSearch(hash: number, reportList: SearchReport[], po { onyxMethod: Onyx.METHOD.MERGE_COLLECTION, key: ONYXKEYS.COLLECTION.REPORT_METADATA, - value: Object.fromEntries(reportList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {isActionLoading: false}])), + value: Object.fromEntries(reportList.map((report) => [`${ONYXKEYS.COLLECTION.REPORT_METADATA}${report?.reportID}`, {isActionLoading: false}])), }, { onyxMethod: Onyx.METHOD.MERGE_COLLECTION, @@ -717,6 +718,7 @@ function deleteMoneyRequestOnSearch(hash: number, transactionIDList: string[], c value: { data: Object.fromEntries( transactionIDList.map((transactionID) => [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}]), + // eslint-disable-next-line @typescript-eslint/no-deprecated ) as Partial, search: { ...(currentMetadata ?? {}), @@ -733,6 +735,7 @@ function deleteMoneyRequestOnSearch(hash: number, transactionIDList: string[], c value: { data: Object.fromEntries( transactionIDList.map((transactionID) => [`${ONYXKEYS.COLLECTION.TRANSACTION}${transactionID}`, {pendingAction: null}]), + // eslint-disable-next-line @typescript-eslint/no-deprecated ) as Partial, search: currentMetadata, }, diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index 445c3df89c17f..500d137d61ce0 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -200,7 +200,6 @@ function SearchPage({route}: SearchPageProps) { } const activeRoute = Navigation.getActiveRoute(); - const transactionIDList = selectedReports.length ? undefined : Object.keys(selectedTransactions); const selectedOptions = selectedReports.length ? selectedReports : Object.values(selectedTransactions); for (const item of selectedOptions) { From a59f6fa4ed44597a2f8fe877361a34d093491dd7 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sun, 16 Nov 2025 03:22:55 +0100 Subject: [PATCH 13/17] lint --- src/libs/actions/Search.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Search.ts b/src/libs/actions/Search.ts index 41eea5586722e..524700e121e0a 100644 --- a/src/libs/actions/Search.ts +++ b/src/libs/actions/Search.ts @@ -33,7 +33,7 @@ import { isIOUReport as isIOUReportUtil, } from '@libs/ReportUtils'; import type {SearchKey} from '@libs/SearchUIUtils'; -import {isTransactionGroupListItemType, isTransactionListItemType} from '@libs/SearchUIUtils'; +import {isTransactionGroupListItemType} from '@libs/SearchUIUtils'; import playSound, {SOUNDS} from '@libs/Sound'; import {shouldRestrictUserBillableActions} from '@libs/SubscriptionUtils'; import CONST from '@src/CONST'; @@ -490,7 +490,7 @@ function submitMoneyRequestOnSearch(hash: number, reportList: SearchReport[], po onyxMethod: Onyx.METHOD.MERGE_COLLECTION, key: ONYXKEYS.COLLECTION.REPORT, value: Object.fromEntries( - reportList.map((reportID) => [`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}]), + reportList.map((report) => [`${ONYXKEYS.COLLECTION.REPORT}${report?.reportID}`, {errors: getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}]), ), }, ]; From 59a8bff9d5c022e3004efe919b79167c52387df5 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Sun, 16 Nov 2025 03:41:35 +0100 Subject: [PATCH 14/17] lint --- src/components/PopoverMenu.tsx | 3 +- src/pages/Search/SearchPage.tsx | 45 +++++++++++++++++--------- tests/unit/Search/SearchUIUtilsTest.ts | 1 + 3 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/components/PopoverMenu.tsx b/src/components/PopoverMenu.tsx index 9c89f275a2f56..0e06b7db66461 100644 --- a/src/components/PopoverMenu.tsx +++ b/src/components/PopoverMenu.tsx @@ -20,6 +20,7 @@ import CONST from '@src/CONST'; import type {AnchorPosition} from '@src/styles'; import type {PendingAction} from '@src/types/onyx/OnyxCommon'; import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; +import type IconAsset from '@src/types/utils/IconAsset'; import FocusableMenuItem from './FocusableMenuItem'; import FocusTrapForModal from './FocusTrap/FocusTrapForModal'; import * as Expensicons from './Icon/Expensicons'; @@ -58,7 +59,7 @@ type PopoverMenuItem = MenuItemProps & { pendingAction?: PendingAction; - rightIcon?: React.FC; + rightIcon?: IconAsset; key?: string; diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index 500d137d61ce0..c246617fb613f 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -8,7 +8,6 @@ import DecisionModal from '@components/DecisionModal'; import DragAndDropConsumer from '@components/DragAndDrop/Consumer'; import DragAndDropProvider from '@components/DragAndDrop/Provider'; import DropZoneUI from '@components/DropZone/DropZoneUI'; -import * as Expensicons from '@components/Icon/Expensicons'; import type {PaymentMethodType} from '@components/KYCWall/types'; import type {PopoverMenuItem} from '@components/PopoverMenu'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -24,6 +23,7 @@ import {usePlaybackContext} from '@components/VideoPlayerContexts/PlaybackContex import useBulkPayOptions from '@hooks/useBulkPayOptions'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useFilesValidation from '@hooks/useFilesValidation'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useMobileSelectionMode from '@hooks/useMobileSelectionMode'; import useNetwork from '@hooks/useNetwork'; @@ -118,6 +118,19 @@ function SearchPage({route}: SearchPageProps) { const queryJSON = useMemo(() => buildSearchQueryJSON(route.params.q), [route.params.q]); const {saveScrollOffset} = useContext(ScrollOffsetContext); const activeAdminPolicies = getActiveAdminWorkspaces(policies, currentUserPersonalDetails?.accountID.toString()).sort((a, b) => localeCompare(a.name || '', b.name || '')); + const expensifyIcons = useMemoizedLazyExpensifyIcons([ + 'Export', + 'Table', + 'DocumentMerge', + 'Send', + 'Trashcan', + 'ThumbsUp', + 'ArrowRight', + 'Stopwatch', + 'Exclamation', + 'SmartScan', + 'MoneyBag', + ] as const); // eslint-disable-next-line rulesdir/no-default-id-values const [currentSearchResults] = useOnyx(`${ONYXKEYS.COLLECTION.SNAPSHOT}${queryJSON?.hash ?? CONST.DEFAULT_NUMBER_ID}`, {canBeMissing: true}); @@ -307,7 +320,7 @@ function SearchPage({route}: SearchPageProps) { const exportOptions: PopoverMenuItem[] = [ { text: translate('export.basicExport'), - icon: Expensicons.Table, + icon: expensifyIcons.Table, onSelected: () => { if (isOffline) { setIsOfflineModalVisible(true); @@ -354,7 +367,7 @@ function SearchPage({route}: SearchPageProps) { for (const template of exportTemplates) { exportOptions.push({ text: template.name, - icon: Expensicons.Table, + icon: expensifyIcons.Table, description: template.description, onSelected: () => { beginExportWithTemplate(template.templateName, template.type, template.policyID); @@ -368,8 +381,8 @@ function SearchPage({route}: SearchPageProps) { }; const exportButtonOption: DropdownOption & Pick = { - icon: Expensicons.Export, - rightIcon: Expensicons.ArrowRight, + icon: expensifyIcons.Export, + rightIcon: expensifyIcons.ArrowRight, text: translate('common.export'), backButtonText: translate('common.export'), value: CONST.SEARCH.BULK_ACTION_TYPES.EXPORT, @@ -394,7 +407,7 @@ function SearchPage({route}: SearchPageProps) { if (shouldShowApproveOption) { options.push({ - icon: Expensicons.ThumbsUp, + icon: expensifyIcons.ThumbsUp, text: translate('search.bulkActions.approve'), value: CONST.SEARCH.BULK_ACTION_TYPES.APPROVE, shouldCloseModalOnSelect: true, @@ -439,7 +452,7 @@ function SearchPage({route}: SearchPageProps) { if (shouldShowSubmitOption) { options.push({ - icon: Expensicons.Send, + icon: expensifyIcons.Send, text: translate('common.submit'), value: CONST.SEARCH.BULK_ACTION_TYPES.SUBMIT, shouldCloseModalOnSelect: true, @@ -467,9 +480,9 @@ function SearchPage({route}: SearchPageProps) { if (shouldShowPayOption) { const payButtonOption = { - icon: Expensicons.MoneyBag, + icon: expensifyIcons.MoneyBag, text: translate('search.bulkActions.pay'), - rightIcon: isFirstTimePayment ? Expensicons.ArrowRight : undefined, + rightIcon: isFirstTimePayment ? expensifyIcons.ArrowRight : undefined, value: CONST.SEARCH.BULK_ACTION_TYPES.PAY, shouldCloseModalOnSelect: true, subMenuItems: isFirstTimePayment ? bulkPayButtonOptions : undefined, @@ -484,7 +497,7 @@ function SearchPage({route}: SearchPageProps) { if (shouldShowHoldOption) { options.push({ - icon: Expensicons.Stopwatch, + icon: expensifyIcons.Stopwatch, text: translate('search.bulkActions.hold'), value: CONST.SEARCH.BULK_ACTION_TYPES.HOLD, shouldCloseModalOnSelect: true, @@ -503,7 +516,7 @@ function SearchPage({route}: SearchPageProps) { if (shouldShowUnholdOption) { options.push({ - icon: Expensicons.Stopwatch, + icon: expensifyIcons.Stopwatch, text: translate('search.bulkActions.unhold'), value: CONST.SEARCH.BULK_ACTION_TYPES.UNHOLD, shouldCloseModalOnSelect: true, @@ -546,7 +559,7 @@ function SearchPage({route}: SearchPageProps) { if (canAllTransactionsBeMoved && !hasMultipleOwners) { options.push({ text: translate('iou.moveExpenses', {count: selectedTransactionsKeys.length}), - icon: Expensicons.DocumentMerge, + icon: expensifyIcons.DocumentMerge, value: CONST.SEARCH.BULK_ACTION_TYPES.CHANGE_REPORT, shouldCloseModalOnSelect: true, onSelected: () => Navigation.navigate(ROUTES.MOVE_TRANSACTIONS_SEARCH_RHP), @@ -557,7 +570,7 @@ function SearchPage({route}: SearchPageProps) { if (shouldShowDeleteOption) { options.push({ - icon: Expensicons.Trashcan, + icon: expensifyIcons.Trashcan, text: translate('search.bulkActions.delete'), value: CONST.SEARCH.BULK_ACTION_TYPES.DELETE, shouldCloseModalOnSelect: true, @@ -587,7 +600,7 @@ function SearchPage({route}: SearchPageProps) { }; options.push({ - icon: Expensicons.Exclamation, + icon: expensifyIcons.Exclamation, text: translate('search.bulkActions.noOptionsAvailable'), value: undefined, ...emptyOptionStyle, @@ -816,7 +829,7 @@ function SearchPage({route}: SearchPageProps) { /> Date: Sun, 16 Nov 2025 03:47:37 +0100 Subject: [PATCH 15/17] lint --- src/components/PopoverMenu.tsx | 6 +++--- src/pages/Search/SearchPage.tsx | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/PopoverMenu.tsx b/src/components/PopoverMenu.tsx index 0e06b7db66461..08b8dbad2358b 100644 --- a/src/components/PopoverMenu.tsx +++ b/src/components/PopoverMenu.tsx @@ -4,9 +4,9 @@ import type {ReactNode, RefObject} from 'react'; import React, {useCallback, useLayoutEffect, useMemo, useState} from 'react'; import {StyleSheet, View} from 'react-native'; import type {GestureResponderEvent, LayoutChangeEvent, StyleProp, TextStyle, ViewStyle} from 'react-native'; -import type {SvgProps} from 'react-native-svg'; import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import usePrevious from '@hooks/usePrevious'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useStyleUtils from '@hooks/useStyleUtils'; @@ -23,7 +23,6 @@ import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; import type IconAsset from '@src/types/utils/IconAsset'; import FocusableMenuItem from './FocusableMenuItem'; import FocusTrapForModal from './FocusTrap/FocusTrapForModal'; -import * as Expensicons from './Icon/Expensicons'; import type {MenuItemProps} from './MenuItem'; import MenuItem from './MenuItem'; import type ReanimatedModalProps from './Modal/ReanimatedModal/types'; @@ -297,6 +296,7 @@ function BasePopoverMenu({ const platform = getPlatform(); const isWebOrDesktop = platform === CONST.PLATFORM.WEB || platform === CONST.PLATFORM.DESKTOP; const [focusedIndex, setFocusedIndex] = useArrowKeyFocusManager({initialFocusedIndex: currentMenuItemsFocusedIndex, maxIndex: currentMenuItems.length - 1, isActive: isVisible}); + const expensifyIcons = useMemoizedLazyExpensifyIcons(['BackArrow'] as const); const prevMenuItems = usePrevious(menuItems); @@ -349,7 +349,7 @@ function BasePopoverMenu({ return ( (isHovered ? theme.iconHovered : theme.icon)} style={hasBackButtonText ? styles.pv0 : undefined} additionalIconStyles={[{width: variables.iconSizeSmall, height: variables.iconSizeSmall}, styles.opacitySemiTransparent, styles.mr1]} diff --git a/src/pages/Search/SearchPage.tsx b/src/pages/Search/SearchPage.tsx index c246617fb613f..9f2c5783441e6 100644 --- a/src/pages/Search/SearchPage.tsx +++ b/src/pages/Search/SearchPage.tsx @@ -633,6 +633,7 @@ function SearchPage({route}: SearchPageProps) { selectedPolicyIDs, selectedReportIDs, selectedTransactionReportIDs, + expensifyIcons, ]); const handleDeleteExpenses = () => { From 92c12437e8f85b8fe797e3e602d683dba031a99f Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 18 Nov 2025 20:04:08 +0100 Subject: [PATCH 16/17] fix test --- tests/unit/Search/SearchUIUtilsTest.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 98ffc36d253ce..1cc162b2b3d93 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -1795,7 +1795,7 @@ describe('SearchUIUtils', () => { expect(distanceTransaction).toBeDefined(); expect(distanceTransaction?.iouRequestType).toBe(CONST.IOU.REQUEST_TYPE.DISTANCE); - const expectedPropertyCount = 52; + const expectedPropertyCount = 51; expect(Object.keys(distanceTransaction ?? {}).length).toBe(expectedPropertyCount); }); @@ -1829,7 +1829,7 @@ describe('SearchUIUtils', () => { expect(distanceTransaction).toBeDefined(); expect(distanceTransaction?.iouRequestType).toBe(CONST.IOU.REQUEST_TYPE.DISTANCE); - const expectedPropertyCount = 52; + const expectedPropertyCount = 51; expect(Object.keys(distanceTransaction ?? {}).length).toBe(expectedPropertyCount); }); From 6d5608989e2127814065c6d56d289f6ef5a24097 Mon Sep 17 00:00:00 2001 From: Abdelhafidh Belalia <16493223+s77rt@users.noreply.github.com> Date: Tue, 18 Nov 2025 20:04:49 +0100 Subject: [PATCH 17/17] lint --- src/libs/SearchUIUtils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index be9148570791a..e359bbca79a77 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -2449,6 +2449,7 @@ function getColumnsToShow( }; const {moneyRequestReportActionsByTransactionID} = Array.isArray(data) ? {} : createReportActionsLookupMaps(data); + // eslint-disable-next-line @typescript-eslint/no-deprecated const updateColumns = (transaction: OnyxTypes.Transaction | SearchTransaction) => { const merchant = transaction.modifiedMerchant ? transaction.modifiedMerchant : (transaction.merchant ?? ''); if ((merchant !== '' && merchant !== CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT) || isScanning(transaction)) {