From 7318cba8d376bb4c20a5ae95e01ab9aea7208eaf Mon Sep 17 00:00:00 2001 From: allgandalf Date: Wed, 23 Jul 2025 17:27:54 +0530 Subject: [PATCH 1/8] pass prop of formatPhoneNumber --- src/components/LocaleContextProvider.tsx | 4 +++- src/components/Search/index.tsx | 4 ++-- src/libs/SearchUIUtils.ts | 24 ++++++++++++++++-------- tests/unit/Search/SearchUIUtilsTest.ts | 17 +++++++++-------- tests/utils/TestHelper.ts | 7 +++++++ 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/components/LocaleContextProvider.tsx b/src/components/LocaleContextProvider.tsx index 4ef2453a6005..fc4f455a1323 100644 --- a/src/components/LocaleContextProvider.tsx +++ b/src/components/LocaleContextProvider.tsx @@ -53,6 +53,8 @@ type LocaleContextProps = { preferredLocale: Locale | undefined; }; +type FormatPhoneNumberType = LocaleContextProps['formatPhoneNumber']; + const LocaleContext = createContext({ translate: () => '', numberFormat: () => '', @@ -166,4 +168,4 @@ LocaleContextProvider.displayName = 'LocaleContextProvider'; export {LocaleContext, LocaleContextProvider}; -export type {Locale, LocaleContextProps}; +export type {Locale, LocaleContextProps, FormatPhoneNumberType}; diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 3ea88a1beeda..82c02ab2d00b 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -188,7 +188,7 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS .flatMap((filteredReportActions) => Object.values(filteredReportActions ?? {})), [reportActions], ); - const {translate} = useLocalize(); + const {translate, formatPhoneNumber} = useLocalize(); const searchListRef = useRef(null); useFocusEffect( @@ -279,7 +279,7 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS return []; } - return getSections(type, searchResults.data, searchResults.search, groupBy, exportReportActions, currentSearchKey); + return getSections(type, searchResults.data, searchResults.search, formatPhoneNumber, groupBy, exportReportActions, currentSearchKey); }, [currentSearchKey, exportReportActions, groupBy, isDataLoaded, searchResults, type]); useEffect(() => { diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 14fe4733f01e..823e8e78bee0 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -2,6 +2,7 @@ import type {TextStyle, ViewStyle} from 'react-native'; import Onyx from 'react-native-onyx'; import type {OnyxCollection} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; +import type {FormatPhoneNumberType} from '@components/LocaleContextProvider'; import DotLottieAnimations from '@components/LottieAnimations'; import type DotLottieAnimation from '@components/LottieAnimations/types'; import type {MenuItemWithLink} from '@components/MenuItemList'; @@ -52,7 +53,6 @@ import DateUtils from './DateUtils'; import {isDevelopment} from './Environment/Environment'; import interceptAnonymousUser from './interceptAnonymousUser'; import localeCompare from './LocaleCompare'; -import {formatPhoneNumber} from './LocalePhoneNumber'; import {translateLocal} from './Localize'; import Navigation from './Navigation/Navigation'; import Parser from './Parser'; @@ -466,6 +466,7 @@ function getTransactionItemCommonFormattedProperties( from: SearchPersonalDetails, to: SearchPersonalDetails, policy: SearchPolicy, + formatPhoneNumber: FormatPhoneNumberType, ): Pick { const isExpenseReport = transactionItem.reportType === CONST.REPORT.TYPE.EXPENSE; @@ -749,7 +750,12 @@ function getTransactionViolations(allViolations: OnyxCollection = {}, ): TransactionGroupListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); @@ -1213,7 +1220,7 @@ function getReportSections( const from = data.personalDetailsList?.[transactionItem.accountID]; const to = transactionItem.managerID && !shouldShowBlankTo ? (data.personalDetailsList?.[transactionItem.managerID] ?? emptyPersonalDetails) : emptyPersonalDetails; - const {formattedFrom, formattedTo, formattedTotal, formattedMerchant, date} = getTransactionItemCommonFormattedProperties(transactionItem, from, to, policy); + const {formattedFrom, formattedTo, formattedTotal, formattedMerchant, date} = getTransactionItemCommonFormattedProperties(transactionItem, from, to, policy, formatPhoneNumber); const transaction = { ...transactionItem, @@ -1289,6 +1296,7 @@ function getSections( type: SearchDataTypes, data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search'], + formatPhoneNumber: FormatPhoneNumberType, groupBy?: SearchGroupBy, reportActions: Record = {}, currentSearch: SearchKey = CONST.SEARCH.SEARCH_KEYS.EXPENSES, @@ -1297,7 +1305,7 @@ function getSections( return getReportActionsSections(data); } if (type === CONST.SEARCH.DATA_TYPES.TASK) { - return getTaskSections(data); + return getTaskSections(data, formatPhoneNumber); } if (groupBy) { @@ -1305,7 +1313,7 @@ function getSections( // eslint-disable-next-line default-case switch (groupBy) { case CONST.SEARCH.GROUP_BY.REPORTS: - return getReportSections(data, metadata, currentSearch, reportActions); + return getReportSections(data, metadata, currentSearch, formatPhoneNumber, reportActions); case CONST.SEARCH.GROUP_BY.MEMBERS: return getMemberSections(data, metadata); case CONST.SEARCH.GROUP_BY.CARDS: @@ -1313,7 +1321,7 @@ function getSections( } } - return getTransactionsSections(data, metadata, currentSearch); + return getTransactionsSections(data, metadata, currentSearch, formatPhoneNumber); } /** diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 293b67275315..d2cd76870994 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -10,6 +10,7 @@ import * as SearchUIUtils from '@src/libs/SearchUIUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; +import {formatPhoneNumber} from '../../utils/TestHelper'; import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates'; jest.mock('@src/components/ConfirmedRoute.tsx'); @@ -1204,41 +1205,41 @@ describe('SearchUIUtils', () => { describe('Test getSections', () => { it('should return getReportActionsSections result when type is CHAT', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.CHAT, searchResults.data, searchResults.search)).toStrictEqual(reportActionListItems); + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.CHAT, searchResults.data, searchResults.search, formatPhoneNumber)).toStrictEqual(reportActionListItems); }); it('should return getTransactionsSections result when groupBy is undefined', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, undefined)).toStrictEqual(transactionsListItems); + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, formatPhoneNumber, undefined)).toStrictEqual(transactionsListItems); }); it('should return getReportSections result when type is EXPENSE and groupBy is report', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( transactionReportGroupListItems, ); }); it('should return getReportSections result when type is TRIP and groupBy is report', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.TRIP, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.TRIP, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( transactionReportGroupListItems, ); }); it('should return getReportSections result when type is INVOICE and groupBy is report', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.INVOICE, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.INVOICE, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( transactionReportGroupListItems, ); }); it('should return getMemberSections result when type is EXPENSE and groupBy is member', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test }); it('should return getMemberSections result when type is TRIP and groupBy is member', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.TRIP, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.TRIP, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test }); it('should return getMemberSections result when type is INVOICE and groupBy is member', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.INVOICE, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.INVOICE, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test }); // s77rt add test for group by card diff --git a/tests/utils/TestHelper.ts b/tests/utils/TestHelper.ts index 549b3ea97851..c369e053f444 100644 --- a/tests/utils/TestHelper.ts +++ b/tests/utils/TestHelper.ts @@ -4,6 +4,7 @@ import {Linking} from 'react-native'; import Onyx from 'react-native-onyx'; import type {ConnectOptions, OnyxKey} from 'react-native-onyx/dist/types'; import type {ApiCommand, ApiRequestCommandParameters} from '@libs/API/types'; +import type {formatPhoneNumberWithCountryCode} from '@libs/LocalePhoneNumber'; import {translateLocal} from '@libs/Localize'; import Pusher from '@libs/Pusher'; import PusherConnectionManager from '@libs/PusherConnectionManager'; @@ -39,6 +40,11 @@ type FormData = { entries: () => Array<[string, string | Blob]>; }; +const countryCodeByIP = 1; +function formatPhoneNumber(phoneNumber: string) { + return formatPhoneNumberWithCountryCode(phoneNumber, countryCodeByIP); +} + function setupApp() { beforeAll(() => { Linking.setInitialURL('https://new.expensify.com/'); @@ -363,4 +369,5 @@ export { navigateToSidebarOption, getOnyxData, getNavigateToChatHintRegex, + formatPhoneNumber, }; From a179fdbf1ad65bea0f775ba4672fde06bee0c55c Mon Sep 17 00:00:00 2001 From: allgandalf Date: Wed, 23 Jul 2025 17:31:30 +0530 Subject: [PATCH 2/8] fix esLint --- src/components/Search/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 82c02ab2d00b..9c40198233da 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -280,7 +280,7 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS } return getSections(type, searchResults.data, searchResults.search, formatPhoneNumber, groupBy, exportReportActions, currentSearchKey); - }, [currentSearchKey, exportReportActions, groupBy, isDataLoaded, searchResults, type]); + }, [currentSearchKey, exportReportActions, groupBy, isDataLoaded, searchResults, type, formatPhoneNumber]); useEffect(() => { /** We only want to display the skeleton for the status filters the first time we load them for a specific data type */ From aa73fbf4c36ed2578e28d6dd266f29ebabc5f902 Mon Sep 17 00:00:00 2001 From: allgandalf Date: Wed, 23 Jul 2025 17:33:10 +0530 Subject: [PATCH 3/8] fix test import --- tests/utils/TestHelper.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/utils/TestHelper.ts b/tests/utils/TestHelper.ts index c369e053f444..7018087e9f10 100644 --- a/tests/utils/TestHelper.ts +++ b/tests/utils/TestHelper.ts @@ -4,7 +4,7 @@ import {Linking} from 'react-native'; import Onyx from 'react-native-onyx'; import type {ConnectOptions, OnyxKey} from 'react-native-onyx/dist/types'; import type {ApiCommand, ApiRequestCommandParameters} from '@libs/API/types'; -import type {formatPhoneNumberWithCountryCode} from '@libs/LocalePhoneNumber'; +import {formatPhoneNumberWithCountryCode} from '@libs/LocalePhoneNumber'; import {translateLocal} from '@libs/Localize'; import Pusher from '@libs/Pusher'; import PusherConnectionManager from '@libs/PusherConnectionManager'; From ba8032b83b844606749e80e88024f87bb32aef21 Mon Sep 17 00:00:00 2001 From: allgandalf Date: Wed, 23 Jul 2025 19:45:48 +0530 Subject: [PATCH 4/8] fix unused imports --- src/components/LocaleContextProvider.tsx | 4 +--- src/libs/SearchUIUtils.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/LocaleContextProvider.tsx b/src/components/LocaleContextProvider.tsx index fc4f455a1323..4ef2453a6005 100644 --- a/src/components/LocaleContextProvider.tsx +++ b/src/components/LocaleContextProvider.tsx @@ -53,8 +53,6 @@ type LocaleContextProps = { preferredLocale: Locale | undefined; }; -type FormatPhoneNumberType = LocaleContextProps['formatPhoneNumber']; - const LocaleContext = createContext({ translate: () => '', numberFormat: () => '', @@ -168,4 +166,4 @@ LocaleContextProvider.displayName = 'LocaleContextProvider'; export {LocaleContext, LocaleContextProvider}; -export type {Locale, LocaleContextProps, FormatPhoneNumberType}; +export type {Locale, LocaleContextProps}; diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 823e8e78bee0..003eaf792442 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -2,7 +2,7 @@ import type {TextStyle, ViewStyle} from 'react-native'; import Onyx from 'react-native-onyx'; import type {OnyxCollection} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; -import type {FormatPhoneNumberType} from '@components/LocaleContextProvider'; +import type {LocaleContextProps} from '@components/LocaleContextProvider'; import DotLottieAnimations from '@components/LottieAnimations'; import type DotLottieAnimation from '@components/LottieAnimations/types'; import type {MenuItemWithLink} from '@components/MenuItemList'; @@ -466,7 +466,7 @@ function getTransactionItemCommonFormattedProperties( from: SearchPersonalDetails, to: SearchPersonalDetails, policy: SearchPolicy, - formatPhoneNumber: FormatPhoneNumberType, + formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], ): Pick { const isExpenseReport = transactionItem.reportType === CONST.REPORT.TYPE.EXPENSE; @@ -754,7 +754,7 @@ function getTransactionsSections( data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search'], currentSearch: SearchKey, - formatPhoneNumber: FormatPhoneNumberType, + formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], ): TransactionListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); const doesDataContainAPastYearTransaction = shouldShowYear(data); @@ -1047,7 +1047,7 @@ function getAction( * * Do not use directly, use only via `getSections()` facade. */ -function getTaskSections(data: OnyxTypes.SearchResults['data'], formatPhoneNumber: FormatPhoneNumberType): TaskListItemType[] { +function getTaskSections(data: OnyxTypes.SearchResults['data'], formatPhoneNumber: LocaleContextProps['formatPhoneNumber']): TaskListItemType[] { return ( Object.keys(data) .filter(isReportEntry) @@ -1171,7 +1171,7 @@ function getReportSections( data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search'], currentSearch: SearchKey, - formatPhoneNumber: FormatPhoneNumberType, + formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], reportActions: Record = {}, ): TransactionGroupListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); @@ -1296,7 +1296,7 @@ function getSections( type: SearchDataTypes, data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search'], - formatPhoneNumber: FormatPhoneNumberType, + formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], groupBy?: SearchGroupBy, reportActions: Record = {}, currentSearch: SearchKey = CONST.SEARCH.SEARCH_KEYS.EXPENSES, From 1f5b38319383098abed67a5634dfa59e0caf157d Mon Sep 17 00:00:00 2001 From: allgandalf Date: Wed, 23 Jul 2025 17:27:54 +0530 Subject: [PATCH 5/8] pass prop of formatPhoneNumber --- src/components/LocaleContextProvider.tsx | 4 +++- src/components/Search/index.tsx | 4 ++-- src/libs/SearchUIUtils.ts | 24 ++++++++++++++++-------- tests/unit/Search/SearchUIUtilsTest.ts | 17 +++++++++-------- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/components/LocaleContextProvider.tsx b/src/components/LocaleContextProvider.tsx index 4ef2453a6005..fc4f455a1323 100644 --- a/src/components/LocaleContextProvider.tsx +++ b/src/components/LocaleContextProvider.tsx @@ -53,6 +53,8 @@ type LocaleContextProps = { preferredLocale: Locale | undefined; }; +type FormatPhoneNumberType = LocaleContextProps['formatPhoneNumber']; + const LocaleContext = createContext({ translate: () => '', numberFormat: () => '', @@ -166,4 +168,4 @@ LocaleContextProvider.displayName = 'LocaleContextProvider'; export {LocaleContext, LocaleContextProvider}; -export type {Locale, LocaleContextProps}; +export type {Locale, LocaleContextProps, FormatPhoneNumberType}; diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 3ea88a1beeda..82c02ab2d00b 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -188,7 +188,7 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS .flatMap((filteredReportActions) => Object.values(filteredReportActions ?? {})), [reportActions], ); - const {translate} = useLocalize(); + const {translate, formatPhoneNumber} = useLocalize(); const searchListRef = useRef(null); useFocusEffect( @@ -279,7 +279,7 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS return []; } - return getSections(type, searchResults.data, searchResults.search, groupBy, exportReportActions, currentSearchKey); + return getSections(type, searchResults.data, searchResults.search, formatPhoneNumber, groupBy, exportReportActions, currentSearchKey); }, [currentSearchKey, exportReportActions, groupBy, isDataLoaded, searchResults, type]); useEffect(() => { diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 14fe4733f01e..823e8e78bee0 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -2,6 +2,7 @@ import type {TextStyle, ViewStyle} from 'react-native'; import Onyx from 'react-native-onyx'; import type {OnyxCollection} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; +import type {FormatPhoneNumberType} from '@components/LocaleContextProvider'; import DotLottieAnimations from '@components/LottieAnimations'; import type DotLottieAnimation from '@components/LottieAnimations/types'; import type {MenuItemWithLink} from '@components/MenuItemList'; @@ -52,7 +53,6 @@ import DateUtils from './DateUtils'; import {isDevelopment} from './Environment/Environment'; import interceptAnonymousUser from './interceptAnonymousUser'; import localeCompare from './LocaleCompare'; -import {formatPhoneNumber} from './LocalePhoneNumber'; import {translateLocal} from './Localize'; import Navigation from './Navigation/Navigation'; import Parser from './Parser'; @@ -466,6 +466,7 @@ function getTransactionItemCommonFormattedProperties( from: SearchPersonalDetails, to: SearchPersonalDetails, policy: SearchPolicy, + formatPhoneNumber: FormatPhoneNumberType, ): Pick { const isExpenseReport = transactionItem.reportType === CONST.REPORT.TYPE.EXPENSE; @@ -749,7 +750,12 @@ function getTransactionViolations(allViolations: OnyxCollection = {}, ): TransactionGroupListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); @@ -1213,7 +1220,7 @@ function getReportSections( const from = data.personalDetailsList?.[transactionItem.accountID]; const to = transactionItem.managerID && !shouldShowBlankTo ? (data.personalDetailsList?.[transactionItem.managerID] ?? emptyPersonalDetails) : emptyPersonalDetails; - const {formattedFrom, formattedTo, formattedTotal, formattedMerchant, date} = getTransactionItemCommonFormattedProperties(transactionItem, from, to, policy); + const {formattedFrom, formattedTo, formattedTotal, formattedMerchant, date} = getTransactionItemCommonFormattedProperties(transactionItem, from, to, policy, formatPhoneNumber); const transaction = { ...transactionItem, @@ -1289,6 +1296,7 @@ function getSections( type: SearchDataTypes, data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search'], + formatPhoneNumber: FormatPhoneNumberType, groupBy?: SearchGroupBy, reportActions: Record = {}, currentSearch: SearchKey = CONST.SEARCH.SEARCH_KEYS.EXPENSES, @@ -1297,7 +1305,7 @@ function getSections( return getReportActionsSections(data); } if (type === CONST.SEARCH.DATA_TYPES.TASK) { - return getTaskSections(data); + return getTaskSections(data, formatPhoneNumber); } if (groupBy) { @@ -1305,7 +1313,7 @@ function getSections( // eslint-disable-next-line default-case switch (groupBy) { case CONST.SEARCH.GROUP_BY.REPORTS: - return getReportSections(data, metadata, currentSearch, reportActions); + return getReportSections(data, metadata, currentSearch, formatPhoneNumber, reportActions); case CONST.SEARCH.GROUP_BY.MEMBERS: return getMemberSections(data, metadata); case CONST.SEARCH.GROUP_BY.CARDS: @@ -1313,7 +1321,7 @@ function getSections( } } - return getTransactionsSections(data, metadata, currentSearch); + return getTransactionsSections(data, metadata, currentSearch, formatPhoneNumber); } /** diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index 293b67275315..d2cd76870994 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -10,6 +10,7 @@ import * as SearchUIUtils from '@src/libs/SearchUIUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; +import {formatPhoneNumber} from '../../utils/TestHelper'; import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates'; jest.mock('@src/components/ConfirmedRoute.tsx'); @@ -1204,41 +1205,41 @@ describe('SearchUIUtils', () => { describe('Test getSections', () => { it('should return getReportActionsSections result when type is CHAT', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.CHAT, searchResults.data, searchResults.search)).toStrictEqual(reportActionListItems); + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.CHAT, searchResults.data, searchResults.search, formatPhoneNumber)).toStrictEqual(reportActionListItems); }); it('should return getTransactionsSections result when groupBy is undefined', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, undefined)).toStrictEqual(transactionsListItems); + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, formatPhoneNumber, undefined)).toStrictEqual(transactionsListItems); }); it('should return getReportSections result when type is EXPENSE and groupBy is report', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( transactionReportGroupListItems, ); }); it('should return getReportSections result when type is TRIP and groupBy is report', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.TRIP, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.TRIP, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( transactionReportGroupListItems, ); }); it('should return getReportSections result when type is INVOICE and groupBy is report', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.INVOICE, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.INVOICE, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.REPORTS)).toStrictEqual( transactionReportGroupListItems, ); }); it('should return getMemberSections result when type is EXPENSE and groupBy is member', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.EXPENSE, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test }); it('should return getMemberSections result when type is TRIP and groupBy is member', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.TRIP, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.TRIP, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test }); it('should return getMemberSections result when type is INVOICE and groupBy is member', () => { - expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.INVOICE, searchResults.data, searchResults.search, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test + expect(SearchUIUtils.getSections(CONST.SEARCH.DATA_TYPES.INVOICE, searchResults.data, searchResults.search, formatPhoneNumber, CONST.SEARCH.GROUP_BY.MEMBERS)).toStrictEqual([]); // s77rt update test }); // s77rt add test for group by card From 7fde5d53974e8dbc31a6eac8bc51f5a7ea599f1b Mon Sep 17 00:00:00 2001 From: allgandalf Date: Wed, 23 Jul 2025 17:31:30 +0530 Subject: [PATCH 6/8] fix esLint --- src/components/Search/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 82c02ab2d00b..9c40198233da 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -280,7 +280,7 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS } return getSections(type, searchResults.data, searchResults.search, formatPhoneNumber, groupBy, exportReportActions, currentSearchKey); - }, [currentSearchKey, exportReportActions, groupBy, isDataLoaded, searchResults, type]); + }, [currentSearchKey, exportReportActions, groupBy, isDataLoaded, searchResults, type, formatPhoneNumber]); useEffect(() => { /** We only want to display the skeleton for the status filters the first time we load them for a specific data type */ From 48963b188736113258441b191b1604f65dc4bce0 Mon Sep 17 00:00:00 2001 From: allgandalf Date: Wed, 23 Jul 2025 19:45:48 +0530 Subject: [PATCH 7/8] fix unused imports --- src/components/LocaleContextProvider.tsx | 4 +--- src/libs/SearchUIUtils.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/LocaleContextProvider.tsx b/src/components/LocaleContextProvider.tsx index fc4f455a1323..4ef2453a6005 100644 --- a/src/components/LocaleContextProvider.tsx +++ b/src/components/LocaleContextProvider.tsx @@ -53,8 +53,6 @@ type LocaleContextProps = { preferredLocale: Locale | undefined; }; -type FormatPhoneNumberType = LocaleContextProps['formatPhoneNumber']; - const LocaleContext = createContext({ translate: () => '', numberFormat: () => '', @@ -168,4 +166,4 @@ LocaleContextProvider.displayName = 'LocaleContextProvider'; export {LocaleContext, LocaleContextProvider}; -export type {Locale, LocaleContextProps, FormatPhoneNumberType}; +export type {Locale, LocaleContextProps}; diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index 823e8e78bee0..003eaf792442 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -2,7 +2,7 @@ import type {TextStyle, ViewStyle} from 'react-native'; import Onyx from 'react-native-onyx'; import type {OnyxCollection} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; -import type {FormatPhoneNumberType} from '@components/LocaleContextProvider'; +import type {LocaleContextProps} from '@components/LocaleContextProvider'; import DotLottieAnimations from '@components/LottieAnimations'; import type DotLottieAnimation from '@components/LottieAnimations/types'; import type {MenuItemWithLink} from '@components/MenuItemList'; @@ -466,7 +466,7 @@ function getTransactionItemCommonFormattedProperties( from: SearchPersonalDetails, to: SearchPersonalDetails, policy: SearchPolicy, - formatPhoneNumber: FormatPhoneNumberType, + formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], ): Pick { const isExpenseReport = transactionItem.reportType === CONST.REPORT.TYPE.EXPENSE; @@ -754,7 +754,7 @@ function getTransactionsSections( data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search'], currentSearch: SearchKey, - formatPhoneNumber: FormatPhoneNumberType, + formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], ): TransactionListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); const doesDataContainAPastYearTransaction = shouldShowYear(data); @@ -1047,7 +1047,7 @@ function getAction( * * Do not use directly, use only via `getSections()` facade. */ -function getTaskSections(data: OnyxTypes.SearchResults['data'], formatPhoneNumber: FormatPhoneNumberType): TaskListItemType[] { +function getTaskSections(data: OnyxTypes.SearchResults['data'], formatPhoneNumber: LocaleContextProps['formatPhoneNumber']): TaskListItemType[] { return ( Object.keys(data) .filter(isReportEntry) @@ -1171,7 +1171,7 @@ function getReportSections( data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search'], currentSearch: SearchKey, - formatPhoneNumber: FormatPhoneNumberType, + formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], reportActions: Record = {}, ): TransactionGroupListItemType[] { const shouldShowMerchant = getShouldShowMerchant(data); @@ -1296,7 +1296,7 @@ function getSections( type: SearchDataTypes, data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search'], - formatPhoneNumber: FormatPhoneNumberType, + formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], groupBy?: SearchGroupBy, reportActions: Record = {}, currentSearch: SearchKey = CONST.SEARCH.SEARCH_KEYS.EXPENSES, From 3169616974ef193126c2992952401f66bc2e20af Mon Sep 17 00:00:00 2001 From: allgandalf Date: Tue, 5 Aug 2025 12:24:22 +0530 Subject: [PATCH 8/8] fix failing tests --- src/components/Search/index.tsx | 2 +- src/libs/SearchUIUtils.ts | 7 +++++-- tests/unit/Search/SearchUIUtilsTest.ts | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 073e6d3be6bd..707c33a6ec05 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -332,7 +332,7 @@ function Search({queryJSON, searchResults, onSearchListScroll, contentContainerS if (groupBy && (isChat || isTask)) { return []; } - + return getSections(type, searchResults.data, searchResults.search, formatPhoneNumber, groupBy, exportReportActions, searchKey, archivedReportsIdSet); }, [searchKey, exportReportActions, groupBy, isDataLoaded, searchResults, type, archivedReportsIdSet, formatPhoneNumber]); diff --git a/src/libs/SearchUIUtils.ts b/src/libs/SearchUIUtils.ts index bc3da05a6cea..555c16827b60 100644 --- a/src/libs/SearchUIUtils.ts +++ b/src/libs/SearchUIUtils.ts @@ -53,7 +53,6 @@ import {convertToDisplayString} from './CurrencyUtils'; import DateUtils from './DateUtils'; import {isDevelopment} from './Environment/Environment'; import interceptAnonymousUser from './interceptAnonymousUser'; -import {formatPhoneNumber} from './LocalePhoneNumber'; import {translateLocal} from './Localize'; import Navigation from './Navigation/Navigation'; import Parser from './Parser'; @@ -1031,7 +1030,11 @@ function getAction( * * Do not use directly, use only via `getSections()` facade. */ -function getTaskSections(data: OnyxTypes.SearchResults['data'], formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], archivedReportsIDList?: ArchivedReportsIDSet): TaskListItemType[] { +function getTaskSections( + data: OnyxTypes.SearchResults['data'], + formatPhoneNumber: LocaleContextProps['formatPhoneNumber'], + archivedReportsIDList?: ArchivedReportsIDSet, +): TaskListItemType[] { return ( Object.keys(data) .filter(isReportEntry) diff --git a/tests/unit/Search/SearchUIUtilsTest.ts b/tests/unit/Search/SearchUIUtilsTest.ts index f406403fbd15..e00f072fab42 100644 --- a/tests/unit/Search/SearchUIUtilsTest.ts +++ b/tests/unit/Search/SearchUIUtilsTest.ts @@ -10,7 +10,7 @@ import * as SearchUIUtils from '@src/libs/SearchUIUtils'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; import type {SearchDataTypes} from '@src/types/onyx/SearchResults'; -import {localeCompare, formatPhoneNumber} from '../../utils/TestHelper'; +import {formatPhoneNumber, localeCompare} from '../../utils/TestHelper'; import waitForBatchedUpdates from '../../utils/waitForBatchedUpdates'; jest.mock('@src/components/ConfirmedRoute.tsx');