From 762747fc131dbe56bd4418420cf35817e86e1a7e Mon Sep 17 00:00:00 2001 From: Ben Limpich Date: Wed, 27 May 2026 13:11:30 -0700 Subject: [PATCH 1/6] Relax card-feed selector check to any validated non-public login --- .../WorkspaceCompanyCardFeedSelectorPage.tsx | 17 +++++++---------- ...WorkspaceExpensifyCardFeedSelectorPage.tsx | 19 +++++++------------ 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx index a23e99311011..ae9359e55e70 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardFeedSelectorPage.tsx @@ -69,8 +69,6 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS const otherFeeds = useOtherFeedsForFeedSelector(policyID); const primaryContactMethod = usePrimaryContactMethod(); - const isUserFromPublicDomain = isEmailPublicDomain(primaryContactMethod); - const feeds: CardFeedListItem[] = (Object.entries(companyCardFeeds ?? {}) as Array<[CompanyCardFeedWithDomainID, CombinedCardFeed]>).map(([feedName, feedSettings]) => { const plaidUrl = getPlaidInstitutionIconUrl(feedSettings.feed); const domain = allDomains?.[`${ONYXKEYS.COLLECTION.DOMAIN}${feedSettings.domainID}`]; @@ -130,14 +128,13 @@ function WorkspaceCompanyCardFeedSelectorPage({route}: WorkspaceCompanyCardFeedS }; const selectOtherFeed = (feed: CardFeedListItem) => { - if (isUserFromPublicDomain) { - Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARD_ADD_WORK_EMAIL.getRoute(policyID, feed.value)); - return; - } - const primaryLoginKey = primaryContactMethod ? Object.keys(loginList ?? {}).find((login) => login.toLowerCase() === primaryContactMethod.toLowerCase()) : undefined; - const isPrimaryContactValidated = primaryLoginKey ? !!loginList?.[primaryLoginKey]?.validatedDate : !primaryContactMethod; - if (!isPrimaryContactValidated) { - Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARD_VERIFY_WORK_EMAIL.getRoute(policyID, feed.value)); + const hasValidatedNonPublicLogin = Object.entries(loginList ?? {}).some(([login, data]) => !!data?.validatedDate && !isEmailPublicDomain(login)); + if (!hasValidatedNonPublicLogin) { + if (primaryContactMethod && !isEmailPublicDomain(primaryContactMethod)) { + Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARD_VERIFY_WORK_EMAIL.getRoute(policyID, feed.value)); + return; + } + Navigation.navigate(ROUTES.SETTINGS_NEW_CONTACT_METHOD.getRoute(Navigation.getActiveRoute())); return; } if (!feed.fundID) { diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx index 8d425c4a015d..442da45e5049 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage.tsx @@ -1,4 +1,3 @@ -import {isUserValidatedSelector} from '@selectors/Account'; import React, {useState} from 'react'; import {View} from 'react-native'; import {useDelegateNoAccessActions, useDelegateNoAccessState} from '@components/DelegateNoAccessModalProvider'; @@ -58,7 +57,6 @@ function WorkspaceExpensifyCardFeedSelectorPage({route}: WorkspaceExpensifyCardF const {showLockedAccountModal} = useLockedAccountActions(); const [lastSelectedExpensifyCardFeed] = useOnyx(`${ONYXKEYS.COLLECTION.LAST_SELECTED_EXPENSIFY_CARD_FEED}${policyID}`); const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); - const [isUserValidated] = useOnyx(ONYXKEYS.ACCOUNT, {selector: isUserValidatedSelector}); const primaryContactMethod = usePrimaryContactMethod(); const defaultFundID = useDefaultFundID(policyID); const lastSelectedExpensifyCardFeedID = lastSelectedExpensifyCardFeed ?? defaultFundID; @@ -149,16 +147,13 @@ function WorkspaceExpensifyCardFeedSelectorPage({route}: WorkspaceExpensifyCardF const selectOtherFeed = (feed: ExpensifyFeedListItem) => { resetCardFlowState(); - const isUserFromPublicDomain = isEmailPublicDomain(primaryContactMethod); - if (!isUserValidated || isUserFromPublicDomain) { - Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_ADD_WORK_EMAIL.getRoute(policyID, feed.value)); - return; - } - - const primaryLoginKey = primaryContactMethod ? Object.keys(loginList ?? {}).find((login) => login.toLowerCase() === primaryContactMethod.toLowerCase()) : undefined; - const isPrimaryContactValidated = primaryLoginKey ? !!loginList?.[primaryLoginKey]?.validatedDate : !primaryContactMethod; - if (!isPrimaryContactValidated) { - Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_VERIFY_WORK_EMAIL.getRoute(policyID, feed.value)); + const hasValidatedNonPublicLogin = Object.entries(loginList ?? {}).some(([login, data]) => !!data?.validatedDate && !isEmailPublicDomain(login)); + if (!hasValidatedNonPublicLogin) { + if (primaryContactMethod && !isEmailPublicDomain(primaryContactMethod)) { + Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_VERIFY_WORK_EMAIL.getRoute(policyID, feed.value)); + return; + } + Navigation.navigate(ROUTES.SETTINGS_NEW_CONTACT_METHOD.getRoute(Navigation.getActiveRoute())); return; } From f24601fd6671983f8ac3e1bb93767a305d854e16 Mon Sep 17 00:00:00 2001 From: Ben Limpich Date: Wed, 27 May 2026 13:13:14 -0700 Subject: [PATCH 2/6] Delete the AddWorkEmail workspace card pages and their routes --- src/ROUTES.ts | 8 - src/SCREENS.ts | 2 - .../ModalStackNavigators/index.tsx | 2 - .../RELATIONS/WORKSPACE_TO_RHP.ts | 2 - src/libs/Navigation/linkingConfig/config.ts | 6 - src/libs/Navigation/types.ts | 8 - .../WorkspaceCompanyCardAddWorkEmailPage.tsx | 170 ------------------ ...WorkspaceExpensifyCardAddWorkEmailPage.tsx | 161 ----------------- src/pages/workspace/withPolicy.tsx | 1 - 9 files changed, 360 deletions(-) delete mode 100644 src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx delete mode 100644 src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index cf6f8f95f7a5..8f66fc140bfb 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -2795,10 +2795,6 @@ const ROUTES = { getRoute: (policyID: string, cardID: string, feed: CompanyCardFeedWithDomainID) => `workspaces/${policyID}/company-cards/${encodeURIComponent(feed)}/${encodeURIComponent(cardID)}/edit/name` as const, }, - WORKSPACE_COMPANY_CARD_ADD_WORK_EMAIL: { - route: 'workspaces/:policyID/company-cards/:feed/work-email', - getRoute: (policyID: string, feed: CompanyCardFeedWithDomainID) => `workspaces/${policyID}/company-cards/${encodeURIComponent(feed)}/work-email` as const, - }, WORKSPACE_COMPANY_CARD_VERIFY_WORK_EMAIL: { route: 'workspaces/:policyID/company-cards/:feed/verify-work-email', getRoute: (policyID: string, feed: CompanyCardFeedWithDomainID) => `workspaces/${policyID}/company-cards/${encodeURIComponent(feed)}/verify-work-email` as const, @@ -2850,10 +2846,6 @@ const ROUTES = { route: 'workspaces/:policyID/expensify-card/settings', getRoute: (policyID: string) => `workspaces/${policyID}/expensify-card/settings` as const, }, - WORKSPACE_EXPENSIFY_CARD_ADD_WORK_EMAIL: { - route: 'workspaces/:policyID/expensify-card/:fundID/work-email', - getRoute: (policyID: string, fundID: number) => `workspaces/${policyID}/expensify-card/${encodeURIComponent(fundID)}/work-email` as const, - }, WORKSPACE_EXPENSIFY_CARD_VERIFY_WORK_EMAIL: { route: 'workspaces/:policyID/expensify-card/:fundID/verify-work-email', getRoute: (policyID: string, fundID: number) => `workspaces/${policyID}/expensify-card/${encodeURIComponent(fundID)}/verify-work-email` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 66956e3afc50..bedfde7a2676 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -737,13 +737,11 @@ const SCREENS = { COMPANY_CARDS_SETTINGS_STATEMENT_CLOSE_DATE: 'Workspace_CompanyCards_Settings_Statement_Close_Date', COMPANY_CARD_DETAILS: 'Workspace_CompanyCard_Details', COMPANY_CARD_EDIT_CARD_NAME: 'Workspace_CompanyCard_Edit_Card_Name', - COMPANY_CARD_ADD_WORK_EMAIL: 'Workspace_CompanyCard_Add_Work_Email', COMPANY_CARD_VERIFY_WORK_EMAIL: 'Workspace_CompanyCard_Verify_Work_Email', COMPANY_CARD_EDIT_TRANSACTION_START_DATE: 'Workspace_CompanyCard_Edit_Transaction_Start_Date', COMPANY_CARD_EXPORT: 'Workspace_CompanyCard_Export', EXPENSIFY_CARD: 'Workspace_ExpensifyCard', EXPENSIFY_CARD_DETAILS: 'Workspace_ExpensifyCard_Details', - EXPENSIFY_CARD_ADD_WORK_EMAIL: 'Workspace_ExpensifyCard_Add_Work_Email', DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW: 'Dynamic_Workspace_ExpensifyCard_New', DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_CONFIRM_MAGIC_CODE: 'Dynamic_Workspace_ExpensifyCard_IssueNew_ConfirmMagicCode', DYNAMIC_WORKSPACE_EXPENSIFY_CARD_SELECT_FEED: 'Dynamic_Workspace_ExpensifyCard_Select_Feed', diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 24eb086ebc38..a6c42c61e46a 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -941,7 +941,6 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/companyCards/BrokenCardFeedConnectionPage').default, [SCREENS.WORKSPACE.COMPANY_CARDS_REFRESH_CARD_FEED_CONNECTION]: () => require('../../../../pages/workspace/companyCards/RefreshCardFeedConnectionPage').default, [SCREENS.WORKSPACE.COMPANY_CARDS_VERIFY_ACCOUNT]: () => require('../../../../pages/workspace/companyCards/WorkspaceCompanyCardsVerifyAccountPage').default, - [SCREENS.WORKSPACE.COMPANY_CARD_ADD_WORK_EMAIL]: () => require('../../../../pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage').default, [SCREENS.WORKSPACE.COMPANY_CARD_VERIFY_WORK_EMAIL]: () => require('../../../../pages/workspace/companyCards/WorkspaceVerifyWorkAccountPage').default, [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_ASSIGNEE]: () => require('../../../../pages/workspace/companyCards/assignCard/AssigneeStep').default, [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_CARD_SELECTION]: () => require('../../../../pages/workspace/companyCards/assignCard/CardSelectionStep').default, @@ -975,7 +974,6 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/Travel/TravelLegalNamePage').default, [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_SELECT_FEED]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage').default, - [SCREENS.WORKSPACE.EXPENSIFY_CARD_ADD_WORK_EMAIL]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage').default, [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_SELECTION]: () => require('../../../../pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleSelectionPage').default, [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_MERCHANTS]: () => diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts index b6c64e0ddddf..8757128b2e8d 100755 --- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts +++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts @@ -286,7 +286,6 @@ const WORKSPACE_TO_RHP: Partial['config'] = { [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_SETTINGS_ACCOUNT]: DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_SETTINGS_ACCOUNT.path, [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_SELECT_FEED]: DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_SELECT_FEED.path, - [SCREENS.WORKSPACE.EXPENSIFY_CARD_ADD_WORK_EMAIL]: { - path: ROUTES.WORKSPACE_EXPENSIFY_CARD_ADD_WORK_EMAIL.route, - }, [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_SELECTION]: { path: DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_SELECTION.path, }, @@ -941,9 +938,6 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.COMPANY_CARDS_VERIFY_ACCOUNT]: { path: ROUTES.WORKSPACE_COMPANY_CARDS_VERIFY_ACCOUNT.route, }, - [SCREENS.WORKSPACE.COMPANY_CARD_ADD_WORK_EMAIL]: { - path: ROUTES.WORKSPACE_COMPANY_CARD_ADD_WORK_EMAIL.route, - }, [SCREENS.WORKSPACE.COMPANY_CARD_VERIFY_WORK_EMAIL]: { path: ROUTES.WORKSPACE_COMPANY_CARD_VERIFY_WORK_EMAIL.route, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 4957871c9dc0..f76caa8e8e8f 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1274,10 +1274,6 @@ type SettingsNavigatorParamList = { [SCREENS.WORKSPACE.EXPENSIFY_CARD_SETTINGS_FREQUENCY]: { policyID: string; }; - [SCREENS.WORKSPACE.EXPENSIFY_CARD_ADD_WORK_EMAIL]: { - policyID: string; - fundID: number; - }; [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_SELECTION]: { policyID: string; }; @@ -1333,10 +1329,6 @@ type SettingsNavigatorParamList = { /** Present when verifying before a feed refresh; absent when verifying before adding a new feed */ feed?: CompanyCardFeedWithDomainID; }; - [SCREENS.WORKSPACE.COMPANY_CARD_ADD_WORK_EMAIL]: { - policyID: string; - feed: CompanyCardFeedWithDomainID; - }; [SCREENS.WORKSPACE.COMPANY_CARD_VERIFY_WORK_EMAIL]: { policyID: string; feed: CompanyCardFeedWithDomainID; diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx deleted file mode 100644 index fd77b2a8cd57..000000000000 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardAddWorkEmailPage.tsx +++ /dev/null @@ -1,170 +0,0 @@ -import {PUBLIC_DOMAINS_SET, Str} from 'expensify-common'; -import React, {useEffect, useState} from 'react'; -import FormProvider from '@components/Form/FormProvider'; -import InputWrapper from '@components/Form/InputWrapper'; -import type {FormOnyxValues} from '@components/Form/types'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import Text from '@components/Text'; -import TextInput from '@components/TextInput'; -import useAutoFocusInput from '@hooks/useAutoFocusInput'; -import useCardFeedsForActivePolicies from '@hooks/useCardFeedsForActivePolicies'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; -import useLocalize from '@hooks/useLocalize'; -import useNetwork from '@hooks/useNetwork'; -import useOnyx from '@hooks/useOnyx'; -import usePrimaryContactMethod from '@hooks/usePrimaryContactMethod'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {setContactMethodAsDefault} from '@libs/actions/User'; -import {getFeedInfo} from '@libs/CardFeedUtils'; -import {getCardFeedWithDomainID} from '@libs/CardUtils'; -import {addErrorMessage} from '@libs/ErrorUtils'; -import Log from '@libs/Log'; -import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; -import {isValidEmail} from '@libs/ValidationUtils'; -import Navigation from '@navigation/Navigation'; -import type {SettingsNavigatorParamList} from '@navigation/types'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; -import {updateSelectedFeed} from '@userActions/Card'; -import {linkCardFeedToPolicy} from '@userActions/CompanyCards'; -import {AddWorkEmail} from '@userActions/Session'; -import CONST from '@src/CONST'; -import type {TranslationPaths} from '@src/languages/types'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type SCREENS from '@src/SCREENS'; -import INPUT_IDS from '@src/types/form/AddWorkEmailForm'; -import type {CompanyCardFeedWithDomainID} from '@src/types/onyx'; -import type {CompanyCardFeedWithNumber} from '@src/types/onyx/CardFeeds'; -import type {Errors} from '@src/types/onyx/OnyxCommon'; - -type WorkspaceCompanyCardAddWorkEmailPageProps = PlatformStackScreenProps; - -function WorkspaceCompanyCardAddWorkEmailPage({route}: WorkspaceCompanyCardAddWorkEmailPageProps) { - const {policyID, feed} = route.params; - const primaryContactMethod = usePrimaryContactMethod(); - const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const {isOffline} = useNetwork(); - const [loading, setLoading] = useState(false); - const {cardFeedsByPolicy} = useCardFeedsForActivePolicies(); - const feedInfo = getFeedInfo(feed, cardFeedsByPolicy); - - const {translate, formatPhoneNumber} = useLocalize(); - const styles = useThemeStyles(); - const [email, setEmail] = React.useState(''); - const emailLoginKey = email ? Object.keys(loginList ?? {}).find((login) => login.toLowerCase() === email.toLowerCase()) : undefined; - const isWorkEmailValidated = emailLoginKey ? !!loginList?.[emailLoginKey]?.validatedDate : false; - - const {inputCallbackRef} = useAutoFocusInput(); - - const handleSubmit = (values: FormOnyxValues) => { - const submittedEmail = values[INPUT_IDS.EMAIL].trim(); - const existingLoginKey = Object.keys(loginList ?? {}).find((login) => login.toLowerCase() === submittedEmail.toLowerCase()); - const isExistingLoginValidated = existingLoginKey ? !!loginList?.[existingLoginKey]?.validatedDate : false; - - if (existingLoginKey) { - if (!isExistingLoginValidated) { - setEmail(submittedEmail); - Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARD_VERIFY_WORK_EMAIL.getRoute(policyID, feed)); - return; - } - setContactMethodAsDefault(currentUserPersonalDetails, existingLoginKey, formatPhoneNumber, undefined, true, ''); - if (!feedInfo) { - setEmail(submittedEmail); - return; - } - setLoading(true); - const feedValue = getCardFeedWithDomainID(feedInfo.feed, feedInfo.fundID) as CompanyCardFeedWithDomainID; - linkCardFeedToPolicy(Number(feedInfo.fundID), policyID, CONST.COMPANY_CARD.LINK_FEED_TYPE.COMPANY_CARD, feedInfo?.country, feedInfo.feed as CompanyCardFeedWithNumber) - .then(() => { - updateSelectedFeed(feedValue, policyID); - Navigation.closeRHPFlow(); - }) - .catch((error: TranslationPaths) => { - addErrorMessage({}, INPUT_IDS.EMAIL, translate(error)); - }) - .finally(() => { - setLoading(false); - }); - } else { - AddWorkEmail(submittedEmail); - } - setEmail(submittedEmail); - }; - - useEffect(() => { - if (!email || !primaryContactMethod || primaryContactMethod.toLowerCase() !== email.toLowerCase() || isWorkEmailValidated) { - return; - } - Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARD_VERIFY_WORK_EMAIL.getRoute(policyID, feed)); - }, [primaryContactMethod, email, policyID, feed, isWorkEmailValidated]); - - const validate = (values: FormOnyxValues): Errors => { - const errors = {}; - const userEmail = values.email; - const emailParts = userEmail.split('@'); - const domain = emailParts.at(1) ?? ''; - - if (!values.email) { - addErrorMessage(errors, INPUT_IDS.EMAIL, translate('common.error.fieldRequired')); - } else if (values.email.length > CONST.LOGIN_CHARACTER_LIMIT) { - addErrorMessage(errors, INPUT_IDS.EMAIL, translate('common.error.characterLimitExceedCounter', values.email.length, CONST.LOGIN_CHARACTER_LIMIT)); - } else if ((!Str.isValidEmail(userEmail) || PUBLIC_DOMAINS_SET.has(domain.toLowerCase())) && !isOffline) { - Log.hmmm('User is trying to add an invalid work email', {userEmail, domain}); - addErrorMessage(errors, INPUT_IDS.EMAIL, translate('onboarding.workEmailValidationError.publicEmail')); - } - - if (isOffline ?? false) { - addErrorMessage(errors, INPUT_IDS.EMAIL, translate('onboarding.workEmailValidationError.offline')); - } - - const isEmailInvalid = !!values.email && !isValidEmail(values.email); - - if (isEmailInvalid) { - addErrorMessage(errors, INPUT_IDS.EMAIL, translate('messages.errorMessageInvalidEmail')); - } - return errors; - }; - - return ( - - - - {translate('workspace.companyCards.addWorkEmail')} - {translate('workspace.companyCards.addWorkEmailDescription')} - - - - - - ); -} - -export default WorkspaceCompanyCardAddWorkEmailPage; diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx deleted file mode 100644 index 0122e26cadfb..000000000000 --- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardAddWorkEmailPage.tsx +++ /dev/null @@ -1,161 +0,0 @@ -import {PUBLIC_DOMAINS_SET, Str} from 'expensify-common'; -import React, {useEffect, useState} from 'react'; -import FormProvider from '@components/Form/FormProvider'; -import InputWrapper from '@components/Form/InputWrapper'; -import type {FormOnyxValues} from '@components/Form/types'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import Text from '@components/Text'; -import TextInput from '@components/TextInput'; -import useAutoFocusInput from '@hooks/useAutoFocusInput'; -import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; -import useLocalize from '@hooks/useLocalize'; -import useNetwork from '@hooks/useNetwork'; -import useOnyx from '@hooks/useOnyx'; -import usePrimaryContactMethod from '@hooks/usePrimaryContactMethod'; -import useThemeStyles from '@hooks/useThemeStyles'; -import {updateSelectedExpensifyCardFeed} from '@libs/actions/Card'; -import {setContactMethodAsDefault} from '@libs/actions/User'; -import {addErrorMessage, getMicroSecondOnyxErrorWithMessage} from '@libs/ErrorUtils'; -import Log from '@libs/Log'; -import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; -import {isValidEmail} from '@libs/ValidationUtils'; -import Navigation from '@navigation/Navigation'; -import type {SettingsNavigatorParamList} from '@navigation/types'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; -import {linkCardFeedToPolicy} from '@userActions/CompanyCards'; -import {setErrorFields} from '@userActions/FormActions'; -import {AddWorkEmail} from '@userActions/Session'; -import CONST from '@src/CONST'; -import type {TranslationPaths} from '@src/languages/types'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; -import type SCREENS from '@src/SCREENS'; -import INPUT_IDS from '@src/types/form/AddWorkEmailForm'; -import type {Errors} from '@src/types/onyx/OnyxCommon'; - -type WorkspaceExpensifyCardAddWorkEmailPageProps = PlatformStackScreenProps; - -function WorkspaceExpensifyCardAddWorkEmailPage({route}: WorkspaceExpensifyCardAddWorkEmailPageProps) { - const {policyID, fundID} = route.params; - const primaryContactMethod = usePrimaryContactMethod(); - const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST); - const currentUserPersonalDetails = useCurrentUserPersonalDetails(); - const {isOffline} = useNetwork(); - const [loading, setLoading] = useState(false); - - const {translate, formatPhoneNumber} = useLocalize(); - const styles = useThemeStyles(); - const [email, setEmail] = useState(''); - const emailLoginKey = email ? Object.keys(loginList ?? {}).find((login) => login.toLowerCase() === email.toLowerCase()) : undefined; - const isWorkEmailValidated = emailLoginKey ? !!loginList?.[emailLoginKey]?.validatedDate : false; - - const {inputCallbackRef} = useAutoFocusInput(); - - const handleSubmit = (values: FormOnyxValues) => { - const submittedEmail = values[INPUT_IDS.EMAIL].trim(); - const existingLoginKey = Object.keys(loginList ?? {}).find((login) => login.toLowerCase() === submittedEmail.toLowerCase()); - const isExistingLoginValidated = existingLoginKey ? !!loginList?.[existingLoginKey]?.validatedDate : false; - - if (existingLoginKey) { - if (!isExistingLoginValidated) { - setEmail(submittedEmail); - Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_VERIFY_WORK_EMAIL.getRoute(policyID, fundID)); - return; - } - setContactMethodAsDefault(currentUserPersonalDetails, existingLoginKey, formatPhoneNumber, undefined, true, ''); - setLoading(true); - linkCardFeedToPolicy(Number(fundID), policyID, CONST.COMPANY_CARD.LINK_FEED_TYPE.EXPENSIFY_CARD) - .then(() => { - updateSelectedExpensifyCardFeed(Number(fundID), policyID); - Navigation.closeRHPFlow(); - }) - .catch((error: TranslationPaths) => { - setErrorFields(ONYXKEYS.FORMS.ADD_WORK_EMAIL_FORM, { - [INPUT_IDS.EMAIL]: getMicroSecondOnyxErrorWithMessage(translate(error)), - }); - }) - .finally(() => { - setLoading(false); - }); - } else { - AddWorkEmail(submittedEmail); - } - setEmail(submittedEmail); - }; - - useEffect(() => { - if (!email || !primaryContactMethod || primaryContactMethod.toLowerCase() !== email.toLowerCase() || isWorkEmailValidated) { - return; - } - Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD_VERIFY_WORK_EMAIL.getRoute(policyID, fundID)); - }, [primaryContactMethod, email, policyID, fundID, isWorkEmailValidated]); - - const validate = (values: FormOnyxValues): Errors => { - const errors = {}; - const userEmail = values.email; - const emailParts = userEmail.split('@'); - const domain = emailParts.at(1) ?? ''; - - if (!values.email) { - addErrorMessage(errors, INPUT_IDS.EMAIL, translate('common.error.fieldRequired')); - } else if (values.email.length > CONST.LOGIN_CHARACTER_LIMIT) { - addErrorMessage(errors, INPUT_IDS.EMAIL, translate('common.error.characterLimitExceedCounter', values.email.length, CONST.LOGIN_CHARACTER_LIMIT)); - } else if ((!Str.isValidEmail(userEmail) || PUBLIC_DOMAINS_SET.has(domain.toLowerCase())) && !isOffline) { - Log.hmmm('User is trying to add an invalid work email', {userEmail, domain}); - addErrorMessage(errors, INPUT_IDS.EMAIL, translate('onboarding.workEmailValidationError.publicEmail')); - } - - if (isOffline ?? false) { - addErrorMessage(errors, INPUT_IDS.EMAIL, translate('onboarding.workEmailValidationError.offline')); - } - - const isEmailInvalid = !!values.email && !isValidEmail(values.email); - - if (isEmailInvalid) { - addErrorMessage(errors, INPUT_IDS.EMAIL, translate('messages.errorMessageInvalidEmail')); - } - return errors; - }; - - return ( - - - - {translate('workspace.companyCards.addWorkEmail')} - {translate('workspace.companyCards.addWorkEmailDescription')} - - - - - - ); -} - -export default WorkspaceExpensifyCardAddWorkEmailPage; diff --git a/src/pages/workspace/withPolicy.tsx b/src/pages/workspace/withPolicy.tsx index b28cb2dacfca..8627dc0123a2 100644 --- a/src/pages/workspace/withPolicy.tsx +++ b/src/pages/workspace/withPolicy.tsx @@ -55,7 +55,6 @@ type PolicyRouteName = | typeof SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW | typeof SCREENS.WORKSPACE.COMPANY_CARDS_BROKEN_CARD_FEED_CONNECTION | typeof SCREENS.WORKSPACE.COMPANY_CARDS_REFRESH_CARD_FEED_CONNECTION - | typeof SCREENS.WORKSPACE.COMPANY_CARD_ADD_WORK_EMAIL | typeof SCREENS.WORKSPACE.COMPANY_CARD_VERIFY_WORK_EMAIL | typeof SCREENS.WORKSPACE.ACCOUNTING.CLAIM_OFFER | typeof SCREENS.WORKSPACE.TIME_TRACKING; From 3c139e8f3848508a2d0cee3af057bbc2472af92e Mon Sep 17 00:00:00 2001 From: Ben Limpich Date: Wed, 27 May 2026 13:14:08 -0700 Subject: [PATCH 3/6] Delete unused AddWorkEmailForm type and Onyx form keys --- src/ONYXKEYS.ts | 3 --- src/types/form/AddWorkEmailForm.ts | 18 ------------------ src/types/form/index.ts | 1 - 3 files changed, 22 deletions(-) delete mode 100644 src/types/form/AddWorkEmailForm.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index a63f5503f492..1dcf2e389d89 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -1135,8 +1135,6 @@ const ONYXKEYS = { SPEND_RULE_FORM_DRAFT: 'spendRuleFormDraft', ADD_DOMAIN_MEMBER_FORM: 'addDomainMemberForm', ADD_DOMAIN_MEMBER_FORM_DRAFT: 'addDomainMemberFormDraft', - ADD_WORK_EMAIL_FORM: 'addWorkEmailForm', - ADD_WORK_EMAIL_FORM_DRAFT: 'addWorkEmailFormDraft', EDIT_DOMAIN_GROUP_NAME_FORM: 'editDomainGroupNameForm', EDIT_DOMAIN_GROUP_NAME_FORM_DRAFT: 'editDomainGroupNameFormDraft', SPEND_RULE_MAX_AMOUNT_FORM: 'spendRuleMaxAmountForm', @@ -1294,7 +1292,6 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.MERCHANT_RULE_FORM]: FormTypes.MerchantRuleForm; [ONYXKEYS.FORMS.SPEND_RULE_FORM]: FormTypes.SpendRuleForm; [ONYXKEYS.FORMS.ADD_DOMAIN_MEMBER_FORM]: FormTypes.AddDomainMemberForm; - [ONYXKEYS.FORMS.ADD_WORK_EMAIL_FORM]: FormTypes.AddWorkEmailForm; [ONYXKEYS.FORMS.EDIT_DOMAIN_GROUP_NAME_FORM]: FormTypes.DomainGroupEditNameForm; [ONYXKEYS.FORMS.SPEND_RULE_MAX_AMOUNT_FORM]: FormTypes.SpendRuleMaxAmountForm; [ONYXKEYS.FORMS.SPEND_RULE_MERCHANT_EDIT_FORM]: FormTypes.SpendRuleMerchantEditForm; diff --git a/src/types/form/AddWorkEmailForm.ts b/src/types/form/AddWorkEmailForm.ts deleted file mode 100644 index 31f9a9b1bec2..000000000000 --- a/src/types/form/AddWorkEmailForm.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type {ValueOf} from 'type-fest'; -import type Form from './Form'; - -const INPUT_IDS = { - EMAIL: 'email', -} as const; - -type InputID = ValueOf; - -type AddWorkEmailForm = Form< - InputID, - { - [INPUT_IDS.EMAIL]: string; - } ->; - -export type {AddWorkEmailForm}; -export default INPUT_IDS; diff --git a/src/types/form/index.ts b/src/types/form/index.ts index 9f306b30f72d..87f74e96df88 100644 --- a/src/types/form/index.ts +++ b/src/types/form/index.ts @@ -122,7 +122,6 @@ export type {DomainGroupEditNameForm} from './DomainGroupEditNameForm'; export type {WorkspaceTimeTrackingDefaultRateForm} from './WorkspaceTimeTrackingDefaultRateForm'; export type {EditExpensifyCardLimitTypeForm} from './EditExpensifyCardLimitTypeForm'; export type {DomainGroupCreateForm} from './DomainGroupCreateForm'; -export type {AddWorkEmailForm} from './AddWorkEmailForm'; export type {SpendRuleMaxAmountForm} from './SpendRuleMaxAmountForm'; export type {SpendRuleMerchantEditForm} from './SpendRuleMerchantEditForm'; export type {AddAgentForm} from './AddAgentForm'; From d891741f5445c86c2255e71d78886f70a59b923d Mon Sep 17 00:00:00 2001 From: Ben Limpich Date: Wed, 27 May 2026 13:49:01 -0700 Subject: [PATCH 4/6] Add explainer RHP screen between selector and Settings flow --- src/ROUTES.ts | 8 ++++ src/SCREENS.ts | 2 + src/languages/en.ts | 1 + src/languages/es.ts | 1 + .../ModalStackNavigators/index.tsx | 2 + .../RELATIONS/WORKSPACE_TO_RHP.ts | 2 + src/libs/Navigation/linkingConfig/config.ts | 6 +++ src/libs/Navigation/types.ts | 8 ++++ .../WorkspaceCardFeedAddWorkEmailPage.tsx | 43 +++++++++++++++++++ .../WorkspaceCompanyCardFeedSelectorPage.tsx | 2 +- ...WorkspaceExpensifyCardFeedSelectorPage.tsx | 2 +- src/pages/workspace/withPolicy.tsx | 1 + 12 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 src/pages/workspace/cardFeed/WorkspaceCardFeedAddWorkEmailPage.tsx diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 8f66fc140bfb..cf6f8f95f7a5 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -2795,6 +2795,10 @@ const ROUTES = { getRoute: (policyID: string, cardID: string, feed: CompanyCardFeedWithDomainID) => `workspaces/${policyID}/company-cards/${encodeURIComponent(feed)}/${encodeURIComponent(cardID)}/edit/name` as const, }, + WORKSPACE_COMPANY_CARD_ADD_WORK_EMAIL: { + route: 'workspaces/:policyID/company-cards/:feed/work-email', + getRoute: (policyID: string, feed: CompanyCardFeedWithDomainID) => `workspaces/${policyID}/company-cards/${encodeURIComponent(feed)}/work-email` as const, + }, WORKSPACE_COMPANY_CARD_VERIFY_WORK_EMAIL: { route: 'workspaces/:policyID/company-cards/:feed/verify-work-email', getRoute: (policyID: string, feed: CompanyCardFeedWithDomainID) => `workspaces/${policyID}/company-cards/${encodeURIComponent(feed)}/verify-work-email` as const, @@ -2846,6 +2850,10 @@ const ROUTES = { route: 'workspaces/:policyID/expensify-card/settings', getRoute: (policyID: string) => `workspaces/${policyID}/expensify-card/settings` as const, }, + WORKSPACE_EXPENSIFY_CARD_ADD_WORK_EMAIL: { + route: 'workspaces/:policyID/expensify-card/:fundID/work-email', + getRoute: (policyID: string, fundID: number) => `workspaces/${policyID}/expensify-card/${encodeURIComponent(fundID)}/work-email` as const, + }, WORKSPACE_EXPENSIFY_CARD_VERIFY_WORK_EMAIL: { route: 'workspaces/:policyID/expensify-card/:fundID/verify-work-email', getRoute: (policyID: string, fundID: number) => `workspaces/${policyID}/expensify-card/${encodeURIComponent(fundID)}/verify-work-email` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index bedfde7a2676..66956e3afc50 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -737,11 +737,13 @@ const SCREENS = { COMPANY_CARDS_SETTINGS_STATEMENT_CLOSE_DATE: 'Workspace_CompanyCards_Settings_Statement_Close_Date', COMPANY_CARD_DETAILS: 'Workspace_CompanyCard_Details', COMPANY_CARD_EDIT_CARD_NAME: 'Workspace_CompanyCard_Edit_Card_Name', + COMPANY_CARD_ADD_WORK_EMAIL: 'Workspace_CompanyCard_Add_Work_Email', COMPANY_CARD_VERIFY_WORK_EMAIL: 'Workspace_CompanyCard_Verify_Work_Email', COMPANY_CARD_EDIT_TRANSACTION_START_DATE: 'Workspace_CompanyCard_Edit_Transaction_Start_Date', COMPANY_CARD_EXPORT: 'Workspace_CompanyCard_Export', EXPENSIFY_CARD: 'Workspace_ExpensifyCard', EXPENSIFY_CARD_DETAILS: 'Workspace_ExpensifyCard_Details', + EXPENSIFY_CARD_ADD_WORK_EMAIL: 'Workspace_ExpensifyCard_Add_Work_Email', DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW: 'Dynamic_Workspace_ExpensifyCard_New', DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_CONFIRM_MAGIC_CODE: 'Dynamic_Workspace_ExpensifyCard_IssueNew_ConfirmMagicCode', DYNAMIC_WORKSPACE_EXPENSIFY_CARD_SELECT_FEED: 'Dynamic_Workspace_ExpensifyCard_Select_Feed', diff --git a/src/languages/en.ts b/src/languages/en.ts index 0b50e1b7b55e..c95b4b889f28 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -5320,6 +5320,7 @@ const translations = { fromOtherWorkspaces: 'From other workspaces', addWorkEmail: 'Add your work email', addWorkEmailDescription: 'Please add your work email in order to use existing feeds from other workspaces.', + openContactMethods: 'Open Contact Methods', error: { workspaceFeedsCouldNotBeLoadedTitle: "Couldn't load card feeds", workspaceFeedsCouldNotBeLoadedMessage: 'An error occurred while loading workspace card feeds. Please try again or contact your administrator.', diff --git a/src/languages/es.ts b/src/languages/es.ts index f84ec9f6a162..771b34f74570 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -5131,6 +5131,7 @@ ${amount} para ${merchant} - ${date}`, fromOtherWorkspaces: 'De otros espacios de trabajo', addWorkEmail: 'Añade tu correo electrónico de trabajo', addWorkEmailDescription: 'Por favor, añade tu correo de trabajo para poder usar los feeds existentes de otros espacios de trabajo.', + openContactMethods: 'Abrir Métodos de contacto', error: { workspaceFeedsCouldNotBeLoadedTitle: 'Error al cargar las fuentes de tarjetas del espacio de trabajo', workspaceFeedsCouldNotBeLoadedMessage: diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index a6c42c61e46a..ac2159ba40b0 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -941,6 +941,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/workspace/companyCards/BrokenCardFeedConnectionPage').default, [SCREENS.WORKSPACE.COMPANY_CARDS_REFRESH_CARD_FEED_CONNECTION]: () => require('../../../../pages/workspace/companyCards/RefreshCardFeedConnectionPage').default, [SCREENS.WORKSPACE.COMPANY_CARDS_VERIFY_ACCOUNT]: () => require('../../../../pages/workspace/companyCards/WorkspaceCompanyCardsVerifyAccountPage').default, + [SCREENS.WORKSPACE.COMPANY_CARD_ADD_WORK_EMAIL]: () => require('../../../../pages/workspace/cardFeed/WorkspaceCardFeedAddWorkEmailPage').default, [SCREENS.WORKSPACE.COMPANY_CARD_VERIFY_WORK_EMAIL]: () => require('../../../../pages/workspace/companyCards/WorkspaceVerifyWorkAccountPage').default, [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_ASSIGNEE]: () => require('../../../../pages/workspace/companyCards/assignCard/AssigneeStep').default, [SCREENS.WORKSPACE.COMPANY_CARDS_ASSIGN_CARD_CARD_SELECTION]: () => require('../../../../pages/workspace/companyCards/assignCard/CardSelectionStep').default, @@ -974,6 +975,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/Travel/TravelLegalNamePage').default, [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_SELECT_FEED]: () => require('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardFeedSelectorPage').default, + [SCREENS.WORKSPACE.EXPENSIFY_CARD_ADD_WORK_EMAIL]: () => require('../../../../pages/workspace/cardFeed/WorkspaceCardFeedAddWorkEmailPage').default, [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_SELECTION]: () => require('../../../../pages/workspace/expensifyCard/issueNew/spendRules/SpendRuleSelectionPage').default, [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_MERCHANTS]: () => diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts index 8757128b2e8d..b6c64e0ddddf 100755 --- a/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts +++ b/src/libs/Navigation/linkingConfig/RELATIONS/WORKSPACE_TO_RHP.ts @@ -286,6 +286,7 @@ const WORKSPACE_TO_RHP: Partial['config'] = { [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_SETTINGS_ACCOUNT]: DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_SETTINGS_ACCOUNT.path, [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_SELECT_FEED]: DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_SELECT_FEED.path, + [SCREENS.WORKSPACE.EXPENSIFY_CARD_ADD_WORK_EMAIL]: { + path: ROUTES.WORKSPACE_EXPENSIFY_CARD_ADD_WORK_EMAIL.route, + }, [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_SELECTION]: { path: DYNAMIC_ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_SELECTION.path, }, @@ -938,6 +941,9 @@ const config: LinkingOptions['config'] = { [SCREENS.WORKSPACE.COMPANY_CARDS_VERIFY_ACCOUNT]: { path: ROUTES.WORKSPACE_COMPANY_CARDS_VERIFY_ACCOUNT.route, }, + [SCREENS.WORKSPACE.COMPANY_CARD_ADD_WORK_EMAIL]: { + path: ROUTES.WORKSPACE_COMPANY_CARD_ADD_WORK_EMAIL.route, + }, [SCREENS.WORKSPACE.COMPANY_CARD_VERIFY_WORK_EMAIL]: { path: ROUTES.WORKSPACE_COMPANY_CARD_VERIFY_WORK_EMAIL.route, }, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index f76caa8e8e8f..4957871c9dc0 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -1274,6 +1274,10 @@ type SettingsNavigatorParamList = { [SCREENS.WORKSPACE.EXPENSIFY_CARD_SETTINGS_FREQUENCY]: { policyID: string; }; + [SCREENS.WORKSPACE.EXPENSIFY_CARD_ADD_WORK_EMAIL]: { + policyID: string; + fundID: number; + }; [SCREENS.WORKSPACE.DYNAMIC_WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW_SPEND_RULE_SELECTION]: { policyID: string; }; @@ -1329,6 +1333,10 @@ type SettingsNavigatorParamList = { /** Present when verifying before a feed refresh; absent when verifying before adding a new feed */ feed?: CompanyCardFeedWithDomainID; }; + [SCREENS.WORKSPACE.COMPANY_CARD_ADD_WORK_EMAIL]: { + policyID: string; + feed: CompanyCardFeedWithDomainID; + }; [SCREENS.WORKSPACE.COMPANY_CARD_VERIFY_WORK_EMAIL]: { policyID: string; feed: CompanyCardFeedWithDomainID; diff --git a/src/pages/workspace/cardFeed/WorkspaceCardFeedAddWorkEmailPage.tsx b/src/pages/workspace/cardFeed/WorkspaceCardFeedAddWorkEmailPage.tsx new file mode 100644 index 000000000000..3203e2ba229d --- /dev/null +++ b/src/pages/workspace/cardFeed/WorkspaceCardFeedAddWorkEmailPage.tsx @@ -0,0 +1,43 @@ +import React from 'react'; +import {View} from 'react-native'; +import Button from '@components/Button'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@libs/Navigation/Navigation'; +import ROUTES from '@src/ROUTES'; + +function WorkspaceCardFeedAddWorkEmailPage() { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + + const openContactMethods = () => { + Navigation.navigate(ROUTES.SETTINGS_NEW_CONTACT_METHOD.getRoute(Navigation.getActiveRoute())); + }; + + return ( + + + + {translate('workspace.companyCards.addWorkEmail')} + {translate('workspace.companyCards.addWorkEmailDescription')} + +