From c0905f63e2a92841d784151497d1f4155aefded9 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Wed, 20 Aug 2025 08:46:10 +0200 Subject: [PATCH 1/5] ref: user new appendCountryCodeWithCountryCode method in getSearchValueForPhoneOrEmail --- .../WorkspaceMembersSelectionList.tsx | 7 +++++-- src/libs/LoginUtils.ts | 2 +- src/libs/OptionsListUtils.ts | 6 +++--- src/pages/InviteReportParticipantsPage.tsx | 5 +++-- .../BaseOnboardingWorkspaceInvite.tsx | 3 ++- src/pages/workspace/WorkspaceInvitePage.tsx | 5 +++-- .../companyCards/assignCard/AssigneeStep.tsx | 5 +++-- .../expensifyCard/issueNew/AssigneeStep.tsx | 5 +++-- .../workflows/WorkspaceWorkflowsPayerPage.tsx | 7 +++++-- ...orkspaceWorkflowsApprovalsApproverPage.tsx | 20 +++++++++++-------- ...paceWorkflowsApprovalsExpensesFromPage.tsx | 14 ++++++++----- 11 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/components/WorkspaceMembersSelectionList.tsx b/src/components/WorkspaceMembersSelectionList.tsx index 73c85b71ed9b..18e4f435508c 100644 --- a/src/components/WorkspaceMembersSelectionList.tsx +++ b/src/components/WorkspaceMembersSelectionList.tsx @@ -2,6 +2,7 @@ import React, {useMemo} from 'react'; import type {SectionListData} from 'react-native'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; import usePolicy from '@hooks/usePolicy'; import useScreenWrapperTransitionStatus from '@hooks/useScreenWrapperTransitionStatus'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; @@ -10,6 +11,7 @@ import {getMemberAccountIDsForWorkspace} from '@libs/PolicyUtils'; import tokenizedSearch from '@libs/tokenizedSearch'; import MemberRightIcon from '@pages/workspace/MemberRightIcon'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; import type {Icon} from '@src/types/onyx/OnyxCommon'; import {FallbackAvatar} from './Icon/Expensicons'; import {usePersonalDetails} from './OnyxListItemProvider'; @@ -40,6 +42,7 @@ function WorkspaceMembersSelectionList({policyID, selectedApprover, setApprover} const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); const personalDetails = usePersonalDetails(); const policy = usePolicy(policyID); + const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const sections: ApproverSection[] = useMemo(() => { const approvers: SelectionListApprover[] = []; @@ -78,7 +81,7 @@ function WorkspaceMembersSelectionList({policyID, selectedApprover, setApprover} approvers.push(...availableApprovers); } - const filteredApprovers = tokenizedSearch(approvers, getSearchValueForPhoneOrEmail(debouncedSearchTerm), (approver) => [approver.text ?? '', approver.login ?? '']); + const filteredApprovers = tokenizedSearch(approvers, getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode), (approver) => [approver.text ?? '', approver.login ?? '']); return [ { @@ -87,7 +90,7 @@ function WorkspaceMembersSelectionList({policyID, selectedApprover, setApprover} shouldShow: true, }, ]; - }, [debouncedSearchTerm, personalDetails, policy?.employeeList, policy?.owner, selectedApprover, localeCompare]); + }, [policy?.employeeList, policy?.owner, debouncedSearchTerm, countryCode, localeCompare, personalDetails, selectedApprover]); const handleOnSelectRow = (approver: SelectionListApprover) => { setApprover(approver.login); diff --git a/src/libs/LoginUtils.ts b/src/libs/LoginUtils.ts index 919d1f1c7c97..c53e05b93d44 100644 --- a/src/libs/LoginUtils.ts +++ b/src/libs/LoginUtils.ts @@ -55,7 +55,7 @@ function appendCountryCode(phone: string): string { * * TODO: Remove this function after completing Onyx.connect deprecation (issue #66329) */ -function appendCountryCodeWithCountryCode(phone: string, countryCode: string): string { +function appendCountryCodeWithCountryCode(phone: string, countryCode: number): string { if (phone.startsWith('+')) { return phone; } diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index ec39d1e12ed0..baa9fa140be3 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -42,7 +42,7 @@ import filterArrayByMatch from './filterArrayByMatch'; import {isReportMessageAttachment} from './isReportMessageAttachment'; import {formatPhoneNumber} from './LocalePhoneNumber'; import {translateLocal} from './Localize'; -import {appendCountryCode, getPhoneNumberWithoutSpecialChars} from './LoginUtils'; +import {appendCountryCode, appendCountryCodeWithCountryCode, getPhoneNumberWithoutSpecialChars} from './LoginUtils'; import {MaxHeap} from './MaxHeap'; import {MinHeap} from './MinHeap'; import ModifiedExpenseMessage from './ModifiedExpenseMessage'; @@ -1200,8 +1200,8 @@ function isMakingLastRequiredTagListOptional(policy: Policy | undefined, policyT return false; } -function getSearchValueForPhoneOrEmail(searchTerm: string) { - const parsedPhoneNumber = parsePhoneNumber(appendCountryCode(Str.removeSMSDomain(searchTerm))); +function getSearchValueForPhoneOrEmail(searchTerm: string, countryCode: OnyxEntry) { + const parsedPhoneNumber = parsePhoneNumber(appendCountryCodeWithCountryCode(Str.removeSMSDomain(searchTerm), countryCode ?? 1)); return parsedPhoneNumber.possible ? (parsedPhoneNumber.number?.e164 ?? '') : searchTerm.toLowerCase(); } diff --git a/src/pages/InviteReportParticipantsPage.tsx b/src/pages/InviteReportParticipantsPage.tsx index bbe83f58ee16..616687fb307d 100644 --- a/src/pages/InviteReportParticipantsPage.tsx +++ b/src/pages/InviteReportParticipantsPage.tsx @@ -50,6 +50,7 @@ type Sections = Array>>; function InviteReportParticipantsPage({betas, report, didScreenTransitionEnd}: InviteReportParticipantsPageProps) { const route = useRoute>(); + const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const {options, areOptionsInitialized} = useOptionsList({ shouldInitialize: didScreenTransitionEnd, }); @@ -117,7 +118,7 @@ function InviteReportParticipantsPage({betas, report, didScreenTransitionEnd}: I // Filter all options that is a part of the search term or in the personal details let filterSelectedOptions = selectedOptions; if (debouncedSearchTerm !== '') { - const processedSearchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm); + const processedSearchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode); filterSelectedOptions = tokenizedSearch(selectedOptions, processedSearchValue, (option) => [option.text ?? '', option.login ?? '']).filter((option) => { const accountID = option?.accountID; const isOptionInPersonalDetails = inviteOptions.personalDetails.some((personalDetail) => accountID && personalDetail?.accountID === accountID); @@ -158,7 +159,7 @@ function InviteReportParticipantsPage({betas, report, didScreenTransitionEnd}: I } return sectionsArr; - }, [areOptionsInitialized, selectedOptions, debouncedSearchTerm, inviteOptions.recentReports, inviteOptions.personalDetails, inviteOptions.userToInvite, translate]); + }, [areOptionsInitialized, selectedOptions, debouncedSearchTerm, inviteOptions.recentReports, inviteOptions.personalDetails, inviteOptions.userToInvite, translate, countryCode]); const toggleOption = useCallback( (option: MemberForList) => { diff --git a/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx b/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx index ec8e3df2eaeb..a5881fff53e1 100644 --- a/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx +++ b/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx @@ -58,6 +58,7 @@ function BaseOnboardingWorkspaceInvite({shouldUseNativeStyles}: BaseOnboardingWo const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false); const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {canBeMissing: true, initWithStoredValues: false}); const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: false}); + const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const session = useSession(); const {isBetaEnabled} = usePermissions(); @@ -164,7 +165,7 @@ function BaseOnboardingWorkspaceInvite({shouldUseNativeStyles}: BaseOnboardingWo const accountID = option.accountID; const isOptionInPersonalDetails = Object.values(personalDetails).some((personalDetail) => personalDetail.accountID === accountID); - const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm); + const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode); const isPartOfSearchTerm = !!option.text?.toLowerCase().includes(searchValue) || !!option.login?.toLowerCase().includes(searchValue); return isPartOfSearchTerm || isOptionInPersonalDetails; diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index fa8647289204..f22269293518 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -55,6 +55,7 @@ function WorkspaceInvitePage({route, policy}: WorkspaceInvitePageProps) { const [usersToInvite, setUsersToInvite] = useState([]); const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false); const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false}); + const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const firstRenderRef = useRef(true); const [betas] = useOnyx(ONYXKEYS.BETAS); const [invitedEmailsToAccountIDsDraft] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT}${route.params.policyID.toString()}`); @@ -177,7 +178,7 @@ function WorkspaceInvitePage({route, policy}: WorkspaceInvitePageProps) { const accountID = option.accountID; const isOptionInPersonalDetails = Object.values(personalDetails).some((personalDetail) => personalDetail.accountID === accountID); - const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm); + const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode); const isPartOfSearchTerm = !!option.text?.toLowerCase().includes(searchValue) || !!option.login?.toLowerCase().includes(searchValue); return isPartOfSearchTerm || isOptionInPersonalDetails; @@ -214,7 +215,7 @@ function WorkspaceInvitePage({route, policy}: WorkspaceInvitePageProps) { }); return sectionsArr; - }, [areOptionsInitialized, selectedOptions, debouncedSearchTerm, personalDetails, translate, usersToInvite]); + }, [areOptionsInitialized, selectedOptions, debouncedSearchTerm, personalDetails, translate, usersToInvite, countryCode]); const toggleOption = (option: MemberForList) => { clearErrors(route.params.policyID); diff --git a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx index f8445d2a9f5b..7bcfef00d7e7 100644 --- a/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx +++ b/src/pages/workspace/companyCards/assignCard/AssigneeStep.tsx @@ -43,6 +43,7 @@ function AssigneeStep({policy, feed}: AssigneeStepProps) { const {isOffline} = useNetwork(); const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD, {canBeMissing: true}); const [workspaceCardFeeds] = useOnyx(ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST, {canBeMissing: false}); + const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const [list] = useCardsList(policy?.id, feed); const [cardFeeds] = useCardFeeds(policy?.id); const filteredCardList = getFilteredCardList(list, cardFeeds?.settings?.oAuthAccountDetails?.[feed], workspaceCardFeeds); @@ -153,7 +154,7 @@ function AssigneeStep({policy, feed}: AssigneeStepProps) { ]; } - const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm).toLowerCase(); + const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode).toLowerCase(); const filteredOptions = tokenizedSearch(membersDetails, searchValue, (option) => [option.text ?? '', option.alternateText ?? '']); return [ @@ -163,7 +164,7 @@ function AssigneeStep({policy, feed}: AssigneeStepProps) { shouldShow: true, }, ]; - }, [membersDetails, debouncedSearchTerm]); + }, [membersDetails, debouncedSearchTerm, countryCode]); const headerMessage = useMemo(() => { const searchValue = debouncedSearchTerm.trim().toLowerCase(); diff --git a/src/pages/workspace/expensifyCard/issueNew/AssigneeStep.tsx b/src/pages/workspace/expensifyCard/issueNew/AssigneeStep.tsx index 8e8a9874b14d..8b1e20ac7da8 100644 --- a/src/pages/workspace/expensifyCard/issueNew/AssigneeStep.tsx +++ b/src/pages/workspace/expensifyCard/issueNew/AssigneeStep.tsx @@ -41,6 +41,7 @@ function AssigneeStep({policy, stepNames, startStepIndex}: AssigneeStepProps) { const {isOffline} = useNetwork(); const policyID = policy?.id; const [issueNewCard] = useOnyx(`${ONYXKEYS.COLLECTION.ISSUE_NEW_EXPENSIFY_CARD}${policyID}`, {canBeMissing: true}); + const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const isEditing = issueNewCard?.isEditing; @@ -120,7 +121,7 @@ function AssigneeStep({policy, stepNames, startStepIndex}: AssigneeStepProps) { ]; } - const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm).toLowerCase(); + const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode).toLowerCase(); const filteredOptions = tokenizedSearch(membersDetails, searchValue, (option) => [option.text ?? '', option.alternateText ?? '']); return [ @@ -130,7 +131,7 @@ function AssigneeStep({policy, stepNames, startStepIndex}: AssigneeStepProps) { shouldShow: true, }, ]; - }, [membersDetails, debouncedSearchTerm]); + }, [debouncedSearchTerm, countryCode, membersDetails]); const headerMessage = useMemo(() => { const searchValue = debouncedSearchTerm.trim().toLowerCase(); diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx index 379aef8bc4e0..205dd3a960d3 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerPage.tsx @@ -11,6 +11,7 @@ import type {ListItem, Section} from '@components/SelectionList/types'; import UserListItem from '@components/SelectionList/UserListItem'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; +import useOnyx from '@hooks/useOnyx'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -24,6 +25,7 @@ import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullsc import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading'; import {setWorkspacePayer} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; import type {PersonalDetailsList, PolicyEmployee} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -43,6 +45,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR const {translate, formatPhoneNumber} = useLocalize(); const policyName = policy?.name ?? ''; const {isOffline} = useNetwork(); + const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const [searchTerm, setSearchTerm] = useState(''); @@ -110,7 +113,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR const sectionsArray: MembersSection[] = []; if (searchTerm !== '') { - const searchValue = getSearchValueForPhoneOrEmail(searchTerm); + const searchValue = getSearchValueForPhoneOrEmail(searchTerm, countryCode); const filteredOptions = tokenizedSearch([...formattedPolicyAdmins, ...formattedAuthorizedPayer], searchValue, (option) => [option.text ?? '', option.login ?? '']); return [ @@ -133,7 +136,7 @@ function WorkspaceWorkflowsPayerPage({route, policy, personalDetails, isLoadingR shouldShow: true, }); return sectionsArray; - }, [formattedPolicyAdmins, formattedAuthorizedPayer, translate, searchTerm]); + }, [searchTerm, formattedAuthorizedPayer, translate, formattedPolicyAdmins, countryCode]); const headerMessage = useMemo( () => (searchTerm && !sections.at(0)?.data.length ? translate('common.noResultsFound') : ''), diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx index b360f8942099..dd7194c999cf 100644 --- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx +++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsApproverPage.tsx @@ -58,6 +58,7 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); const [approvalWorkflow, approvalWorkflowMetadata] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true}); const isApprovalWorkflowLoading = isLoadingOnyxValue(approvalWorkflowMetadata); + const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const [selectedApproverEmail, setSelectedApproverEmail] = useState(undefined); const [allApprovers, setAllApprovers] = useState([]); const shouldShowTextInput = allApprovers?.length >= CONST.STANDARD_LIST_ITEM_LIMIT; @@ -142,7 +143,9 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa } const filteredApprovers = - debouncedSearchTerm !== '' ? tokenizedSearch(approvers, getSearchValueForPhoneOrEmail(debouncedSearchTerm), (option) => [option.text ?? '', option.login ?? '']) : approvers; + debouncedSearchTerm !== '' + ? tokenizedSearch(approvers, getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode), (option) => [option.text ?? '', option.login ?? '']) + : approvers; const data = sortAlphabetically(filteredApprovers, 'text', localeCompare); return [ @@ -154,18 +157,19 @@ function WorkspaceWorkflowsApprovalsApproverPage({policy, personalDetails, isLoa ]; }, [ isApprovalWorkflowLoading, + employeeList, + debouncedSearchTerm, + countryCode, + localeCompare, + policy?.preventSelfApproval, + policy?.owner, + membersEmail, approversFromWorkflow, + selectedApproverEmail, isDefault, approverIndex, - debouncedSearchTerm, defaultApprover, personalDetails, - employeeList, - selectedApproverEmail, - membersEmail, - policy?.preventSelfApproval, - policy?.owner, - localeCompare, ]); const shouldShowListEmptyContent = !debouncedSearchTerm && !!approvalWorkflow && !sections.at(0)?.data.length && !isApprovalWorkflowLoading; diff --git a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage.tsx b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage.tsx index 4540d7202330..999da9b466b9 100644 --- a/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage.tsx +++ b/src/pages/workspace/workflows/approvals/WorkspaceWorkflowsApprovalsExpensesFromPage.tsx @@ -60,6 +60,7 @@ function WorkspaceWorkflowsApprovalsExpensesFromPage({policy, isLoadingReportDat const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); const [approvalWorkflow, approvalWorkflowResults] = useOnyx(ONYXKEYS.APPROVAL_WORKFLOW, {canBeMissing: true}); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: false}); + const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const isLoadingApprovalWorkflow = isLoadingOnyxValue(approvalWorkflowResults); const [selectedMembers, setSelectedMembers] = useState([]); @@ -137,7 +138,9 @@ function WorkspaceWorkflowsApprovalsExpensesFromPage({policy, isLoadingReportDat } const filteredMembers = - debouncedSearchTerm !== '' ? tokenizedSearch(members, getSearchValueForPhoneOrEmail(debouncedSearchTerm), (option) => [option.text ?? '', option.login ?? '']) : members; + debouncedSearchTerm !== '' + ? tokenizedSearch(members, getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode), (option) => [option.text ?? '', option.login ?? '']) + : members; return [ { @@ -147,15 +150,16 @@ function WorkspaceWorkflowsApprovalsExpensesFromPage({policy, isLoadingReportDat }, ]; }, [ + selectedMembers, approvalWorkflow?.availableMembers, debouncedSearchTerm, - policy?.preventSelfApproval, + countryCode, + localeCompare, policy?.employeeList, policy?.owner, - selectedMembers, - approversEmail, + policy?.preventSelfApproval, personalDetailLogins, - localeCompare, + approversEmail, ]); const goBack = useCallback(() => { From 27429a6a293a22712779e94134f9f7836788694b Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Thu, 21 Aug 2025 07:28:37 +0200 Subject: [PATCH 2/5] fix lint --- .../BaseOnboardingWorkspaceInvite.tsx | 2 +- src/pages/workspace/WorkspaceInvitePage.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx b/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx index a5881fff53e1..a79ab3faeb52 100644 --- a/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx +++ b/src/pages/OnboardingWorkspaceInvite/BaseOnboardingWorkspaceInvite.tsx @@ -203,7 +203,7 @@ function BaseOnboardingWorkspaceInvite({shouldUseNativeStyles}: BaseOnboardingWo }); return sectionsArr; - }, [areOptionsInitialized, selectedOptions, debouncedSearchTerm, personalDetails, translate, usersToInvite]); + }, [areOptionsInitialized, selectedOptions, debouncedSearchTerm, personalDetails, translate, usersToInvite, countryCode]); const toggleOption = (option: MemberForList) => { const isOptionInList = selectedOptions.some((selectedOption) => selectedOption.login === option.login); diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index f22269293518..86463dd27de0 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -54,11 +54,11 @@ function WorkspaceInvitePage({route, policy}: WorkspaceInvitePageProps) { const [personalDetails, setPersonalDetails] = useState([]); const [usersToInvite, setUsersToInvite] = useState([]); const [didScreenTransitionEnd, setDidScreenTransitionEnd] = useState(false); - const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false}); + const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true}); const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const firstRenderRef = useRef(true); - const [betas] = useOnyx(ONYXKEYS.BETAS); - const [invitedEmailsToAccountIDsDraft] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT}${route.params.policyID.toString()}`); + const [betas] = useOnyx(ONYXKEYS.BETAS, {canBeMissing: false}); + const [invitedEmailsToAccountIDsDraft] = useOnyx(`${ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT}${route.params.policyID.toString()}`, {canBeMissing: true}); const openWorkspaceInvitePage = () => { const policyMemberEmailsToAccountIDs = getMemberAccountIDsForWorkspace(policy?.employeeList); From d3408b85d9f94974a950ad02f58f36f21cf3d4af Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Thu, 28 Aug 2025 22:34:47 +0300 Subject: [PATCH 3/5] add unit tests --- tests/unit/OptionsListUtilsTest.tsx | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/unit/OptionsListUtilsTest.tsx b/tests/unit/OptionsListUtilsTest.tsx index c11a39a589a1..efb3d921736c 100644 --- a/tests/unit/OptionsListUtilsTest.tsx +++ b/tests/unit/OptionsListUtilsTest.tsx @@ -19,6 +19,7 @@ import { getLastActorDisplayName, getMemberInviteOptions, getSearchOptions, + getSearchValueForPhoneOrEmail, getShareDestinationOptions, getShareLogOptions, getValidOptions, @@ -2051,4 +2052,30 @@ describe('OptionsListUtils', () => { expect(sortedOptions.at(0)?.text).toBe('Single'); }); }); + describe('getSearchValueForPhoneOrEmail', () => { + it('should return E164 format for valid phone number', () => { + const result = getSearchValueForPhoneOrEmail('+1 (234) 567-8901', 1); + expect(result).toBe('+12345678901'); + }); + + it('should return E164 format for valid international phone number', () => { + const result = getSearchValueForPhoneOrEmail('+44 20 8759 9036', 44); + expect(result).toBe('+442087599036'); + }); + + it('should return lowercase for email address', () => { + const result = getSearchValueForPhoneOrEmail('Test@Example.COM', 1); + expect(result).toBe('test@example.com'); + }); + + it('should handle SMS domain removal for valid phone number', () => { + const result = getSearchValueForPhoneOrEmail('+12345678901@expensify.sms', 1); + expect(result).toBe('+12345678901'); + }); + + it('should return empty string for empty input', () => { + const result = getSearchValueForPhoneOrEmail('', 1); + expect(result).toBe(''); + }); + }); }); From fdf0973867ec3634239a479c4a2d3394388fcf2d Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Fri, 29 Aug 2025 08:37:13 +0300 Subject: [PATCH 4/5] fix typecheck --- .../receiptPartners/InviteReceiptPartnerPolicyPage.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pages/workspace/receiptPartners/InviteReceiptPartnerPolicyPage.tsx b/src/pages/workspace/receiptPartners/InviteReceiptPartnerPolicyPage.tsx index bac660795878..dcb9ef7f75a6 100644 --- a/src/pages/workspace/receiptPartners/InviteReceiptPartnerPolicyPage.tsx +++ b/src/pages/workspace/receiptPartners/InviteReceiptPartnerPolicyPage.tsx @@ -10,6 +10,7 @@ import Text from '@components/Text'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; +import useOnyx from '@hooks/useOnyx'; import usePolicy from '@hooks/usePolicy'; import useThemeStyles from '@hooks/useThemeStyles'; import {clearErrors, inviteWorkspaceEmployeesToUber} from '@libs/actions/Policy/Policy'; @@ -24,6 +25,7 @@ import tokenizedSearch from '@libs/tokenizedSearch'; import type {WorkspaceSplitNavigatorParamList} from '@navigation/types'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; type InviteReceiptPartnerPolicyPageProps = PlatformStackScreenProps; @@ -35,6 +37,7 @@ function InviteReceiptPartnerPolicyPage({route}: InviteReceiptPartnerPolicyPageP const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(''); const [selectedOptions, setSelectedOptions] = useState([]); const [isInvitationSent, setIsInvitationSent] = useState(false); + const [countryCode] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false}); const policyID = route.params?.policyID; const policy = usePolicy(policyID); @@ -90,14 +93,14 @@ function InviteReceiptPartnerPolicyPage({route}: InviteReceiptPartnerPolicyPageP // Apply search filter if there's a search term if (debouncedSearchTerm) { - const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm).toLowerCase(); + const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode).toLowerCase(); membersToDisplay = tokenizedSearch(workspaceMembers, searchValue, (option) => [option.text ?? '', option.alternateText ?? '']); } // Filter to show selected members first, then apply search filter to selected members let filterSelectedOptions = selectedOptions; if (debouncedSearchTerm !== '') { - const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm).toLowerCase(); + const searchValue = getSearchValueForPhoneOrEmail(debouncedSearchTerm, countryCode).toLowerCase(); filterSelectedOptions = selectedOptions.filter((option) => { const isPartOfSearchTerm = !!option.text?.toLowerCase().includes(searchValue) || !!option.login?.toLowerCase().includes(searchValue); return isPartOfSearchTerm; From af832c8c24a16b3fe0bd19e121fdeb74b3169ce5 Mon Sep 17 00:00:00 2001 From: kubabutkiewicz Date: Tue, 2 Sep 2025 10:03:24 +0300 Subject: [PATCH 5/5] added missing import --- src/libs/OptionsListUtils/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/OptionsListUtils/index.ts b/src/libs/OptionsListUtils/index.ts index 7bb778fe7698..777afb702dcb 100644 --- a/src/libs/OptionsListUtils/index.ts +++ b/src/libs/OptionsListUtils/index.ts @@ -13,7 +13,7 @@ import filterArrayByMatch from '@libs/filterArrayByMatch'; import {isReportMessageAttachment} from '@libs/isReportMessageAttachment'; import {formatPhoneNumber} from '@libs/LocalePhoneNumber'; import {translateLocal} from '@libs/Localize'; -import {appendCountryCode, getPhoneNumberWithoutSpecialChars} from '@libs/LoginUtils'; +import {appendCountryCode, appendCountryCodeWithCountryCode, getPhoneNumberWithoutSpecialChars} from '@libs/LoginUtils'; import {MaxHeap} from '@libs/MaxHeap'; import {MinHeap} from '@libs/MinHeap'; import ModifiedExpenseMessage from '@libs/ModifiedExpenseMessage';