From 19db79fe3ecd66c78f9fcf75283e7ebde15bd8ff Mon Sep 17 00:00:00 2001 From: Ben Limpich Date: Thu, 24 Apr 2025 21:55:04 -0700 Subject: [PATCH 1/2] Revert "Merge pull request #60856 from allroundexperts/fix-60828" This reverts commit a329cec66d4c9f53d2b03c5241cd10279ae71d57, reversing changes made to fd56bb458adfca15f0d0761a73d6f1176bf969bc. --- .../index.native.tsx | 23 +------------------ .../BaseOnboardingPrivateDomain.tsx | 2 +- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/pages/OnboardingPersonalDetails/index.native.tsx b/src/pages/OnboardingPersonalDetails/index.native.tsx index ceecd9af7bd22..624d2dd305876 100644 --- a/src/pages/OnboardingPersonalDetails/index.native.tsx +++ b/src/pages/OnboardingPersonalDetails/index.native.tsx @@ -1,29 +1,8 @@ -import {useFocusEffect} from '@react-navigation/native'; -import React, {useCallback} from 'react'; -import {BackHandler} from 'react-native'; +import React from 'react'; import BaseOnboardingPersonalDetails from './BaseOnboardingPersonalDetails'; import type {OnboardingPersonalDetailsProps} from './types'; function OnboardingPersonalDetails({...rest}: OnboardingPersonalDetailsProps) { - const {index: routeIndex} = rest.navigation.getState(); - - // To block android native back button behavior - useFocusEffect( - useCallback(() => { - // We don't want to block the back button if this is not the first route - if (routeIndex !== 0) { - return; - } - - // Return true to indicate that the back button press is handled here - const backAction = () => true; - - const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction); - - return () => backHandler.remove(); - }, [routeIndex]), - ); - return ( - + {translate('onboarding.peopleYouMayKnow')} {translate('onboarding.workspaceYouMayJoin', {domain, email})} Date: Thu, 24 Apr 2025 22:00:32 -0700 Subject: [PATCH 2/2] Revert "Merge pull request #54912 from allroundexperts/feat-48189-3" This reverts commit e35d9e31d8acfe40be5b4e36addf64fb34077fd1, reversing changes made to 1c612838f96dbe60d99a6fd481b3e75b253abce1. --- src/ONYXKEYS.ts | 6 +- src/components/MagicCodeInput.tsx | 6 +- .../ValidateCodeForm/BaseValidateCodeForm.tsx | 5 - src/hooks/useOnboardingFlow.ts | 16 +-- .../API/parameters/AskToJoinPolicyParams.ts | 5 - .../API/parameters/JoinPolicyInviteLink.ts | 2 +- src/libs/API/parameters/index.ts | 1 - src/libs/API/types.ts | 5 - .../Navigators/OnboardingModalNavigator.tsx | 26 +---- src/libs/Navigation/NavigationRoot.tsx | 12 +- .../helpers/getAdaptedStateFromPath.ts | 2 +- src/libs/actions/Policy/Member.ts | 28 +---- src/libs/actions/Policy/Policy.ts | 50 --------- src/libs/actions/Report.ts | 3 +- src/libs/actions/Session/index.ts | 39 +++++++ src/libs/actions/Welcome/OnboardingFlow.ts | 2 +- .../BaseOnboardingPersonalDetails.tsx | 37 +++++-- .../BaseOnboardingPrivateDomain.tsx | 89 +++++++-------- .../BaseOnboardingPurpose.tsx | 35 ++---- .../BaseOnboardingWorkspaces.tsx | 103 ++++++++---------- src/types/onyx/User.ts | 3 - .../ValidateUserAndGetAccessiblePolicies.ts | 12 -- src/types/onyx/index.ts | 2 - 23 files changed, 187 insertions(+), 302 deletions(-) delete mode 100644 src/libs/API/parameters/AskToJoinPolicyParams.ts delete mode 100644 src/types/onyx/ValidateUserAndGetAccessiblePolicies.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index d66d6d0c0c66d..35f2511e45b3c 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -110,8 +110,8 @@ const ONYXKEYS = { /** A list of policies that a user can join */ JOINABLE_POLICIES: 'joinablePolicies', - /* Contains meta data for the call to the API to get the joinable policies */ - VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES: 'validateUserAndGetAccessiblePolicies', + /** Flag to indicate if the joinablePolicies are loading */ + JOINABLE_POLICIES_LOADING: 'joinablePoliciesLoading', /** Information about the current session (authToken, accountID, email, loading, error) */ SESSION: 'session', @@ -1011,7 +1011,7 @@ type OnyxValuesMapping = { [ONYXKEYS.PENDING_CONTACT_ACTION]: OnyxTypes.PendingContactAction; [ONYXKEYS.VALIDATE_ACTION_CODE]: OnyxTypes.ValidateMagicCodeAction; [ONYXKEYS.JOINABLE_POLICIES]: OnyxTypes.JoinablePolicies; - [ONYXKEYS.VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES]: OnyxTypes.ValidateUserAndGetAccessiblePolicies; + [ONYXKEYS.JOINABLE_POLICIES_LOADING]: boolean; [ONYXKEYS.SESSION]: OnyxTypes.Session; [ONYXKEYS.USER_METADATA]: OnyxTypes.UserMetadata; [ONYXKEYS.STASHED_SESSION]: OnyxTypes.Session; diff --git a/src/components/MagicCodeInput.tsx b/src/components/MagicCodeInput.tsx index 1641484020139..8d0d2a6c89a36 100644 --- a/src/components/MagicCodeInput.tsx +++ b/src/components/MagicCodeInput.tsx @@ -57,9 +57,6 @@ type MagicCodeInputProps = { /** TestID for test */ testID?: string; - - /** Whether to allow auto submit again after the previous attempt fails */ - allowResubmit?: boolean; }; type MagicCodeInputHandle = { @@ -108,7 +105,6 @@ function MagicCodeInput( autoComplete, hasError = false, testID = '', - allowResubmit = false, }: MagicCodeInputProps, ref: ForwardedRef, ) { @@ -179,7 +175,7 @@ function MagicCodeInput( const validateAndSubmit = () => { const numbers = decomposeString(value, maxLength); // eslint-disable-next-line @typescript-eslint/no-use-before-define - if ((wasSubmitted && !allowResubmit) || !shouldSubmitOnComplete || numbers.filter((n) => isNumeric(n)).length !== maxLength || isOffline) { + if (wasSubmitted || !shouldSubmitOnComplete || numbers.filter((n) => isNumeric(n)).length !== maxLength || isOffline) { return; } if (!wasSubmitted) { diff --git a/src/components/ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm.tsx b/src/components/ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm.tsx index f5046898d9a88..08732326c0070 100644 --- a/src/components/ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm.tsx +++ b/src/components/ValidateCodeActionModal/ValidateCodeForm/BaseValidateCodeForm.tsx @@ -80,9 +80,6 @@ type ValidateCodeFormProps = { /** Whether the form is loading or not */ isLoading?: boolean; - /** Whether to allow auto submit again after the previous attempt fails */ - allowResubmit?: boolean; - /** Whether to show skip button */ shouldShowSkipButton?: boolean; @@ -104,7 +101,6 @@ function BaseValidateCodeForm({ hideSubmitButton, submitButtonText, isLoading, - allowResubmit, shouldShowSkipButton = false, handleSkipButtonPress, }: ValidateCodeFormProps) { @@ -271,7 +267,6 @@ function BaseValidateCodeForm({ hasError={canShowError && !isEmptyObject(finalValidateError)} onFulfill={validateAndSubmitForm} autoFocus={false} - allowResubmit={allowResubmit} /> {shouldShowTimer && ( diff --git a/src/hooks/useOnboardingFlow.ts b/src/hooks/useOnboardingFlow.ts index 4cfbc4ca4ba6b..811a1dae4d2e4 100644 --- a/src/hooks/useOnboardingFlow.ts +++ b/src/hooks/useOnboardingFlow.ts @@ -1,6 +1,7 @@ import {useEffect} from 'react'; import {InteractionManager} from 'react-native'; import {useOnyx} from 'react-native-onyx'; +import {isUserOnPrivateDomain} from '@libs/actions/Session'; import {startOnboardingFlow} from '@libs/actions/Welcome/OnboardingFlow'; import Navigation from '@libs/Navigation/Navigation'; import {hasCompletedGuidedSetupFlowSelector, tryNewDotOnyxSelector} from '@libs/onboardingSelectors'; @@ -17,20 +18,20 @@ import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; * Warning: This hook should be used only once in the app */ function useOnboardingFlowRouter() { - const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP, {initialValue: true, canBeMissing: true}); + const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP, {initialValue: true}); const [isOnboardingCompleted, isOnboardingCompletedMetadata] = useOnyx(ONYXKEYS.NVP_ONBOARDING, { selector: hasCompletedGuidedSetupFlowSelector, - canBeMissing: true, }); const [tryNewDot, tryNewDotdMetadata] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT, { selector: tryNewDotOnyxSelector, - canBeMissing: true, }); const {isHybridAppOnboardingCompleted, hasBeenAddedToNudgeMigration} = tryNewDot ?? {}; - const [dismissedProductTraining, dismissedProductTrainingMetadata] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); + const [dismissedProductTraining, dismissedProductTrainingMetadata] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING); - const [isSingleNewDotEntry, isSingleNewDotEntryMetadata] = useOnyx(ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY, {canBeMissing: true}); + const isPrivateDomain = isUserOnPrivateDomain(); + + const [isSingleNewDotEntry, isSingleNewDotEntryMetadata] = useOnyx(ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY); useEffect(() => { // This should delay opening the onboarding modal so it does not interfere with the ongoing ReportScreen params changes InteractionManager.runAfterInteractions(() => { @@ -71,13 +72,13 @@ function useOnboardingFlowRouter() { // But if the hybrid app onboarding is completed, but NewDot onboarding is not completed, we start NewDot onboarding flow // This is a special case when user created an account from NewDot without finishing the onboarding flow and then logged in from OldDot if (isHybridAppOnboardingCompleted === true && isOnboardingCompleted === false) { - startOnboardingFlow(); + startOnboardingFlow(isPrivateDomain); } } // If the user is not transitioning from OldDot to NewDot, we should start NewDot onboarding flow if it's not completed yet if (!CONFIG.IS_HYBRID_APP && isOnboardingCompleted === false) { - startOnboardingFlow(); + startOnboardingFlow(isPrivateDomain); } }); }, [ @@ -92,6 +93,7 @@ function useOnboardingFlowRouter() { dismissedProductTrainingMetadata, dismissedProductTraining?.migratedUserWelcomeModal, dismissedProductTraining, + isPrivateDomain, ]); return {isOnboardingCompleted, isHybridAppOnboardingCompleted}; diff --git a/src/libs/API/parameters/AskToJoinPolicyParams.ts b/src/libs/API/parameters/AskToJoinPolicyParams.ts deleted file mode 100644 index 8537cea04204d..0000000000000 --- a/src/libs/API/parameters/AskToJoinPolicyParams.ts +++ /dev/null @@ -1,5 +0,0 @@ -type AskToJoinPolicyParams = { - policyID: string; -}; - -export default AskToJoinPolicyParams; diff --git a/src/libs/API/parameters/JoinPolicyInviteLink.ts b/src/libs/API/parameters/JoinPolicyInviteLink.ts index 7ada9e44686ba..4b280b8cd8c6a 100644 --- a/src/libs/API/parameters/JoinPolicyInviteLink.ts +++ b/src/libs/API/parameters/JoinPolicyInviteLink.ts @@ -1,6 +1,6 @@ type JoinPolicyInviteLinkParams = { policyID: string; - inviterEmail?: string; + inviterEmail: string; }; export default JoinPolicyInviteLinkParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index ec74fcf164d1e..0cad6cc0a7ab2 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -362,7 +362,6 @@ export type {default as TogglePlatformMuteParams} from './TogglePlatformMutePara export type {default as GetCorpayBankAccountFieldsParams} from './GetCorpayBankAccountFieldsParams'; export type {default as BankAccountCreateCorpayParams} from './BankAccountCreateCorpayParams'; export type {default as JoinAccessiblePolicyParams} from './JoinAccessiblePolicyParams'; -export type {default as AskToJoinPolicyParams} from './AskToJoinPolicyParams'; export type {default as ImportPerDiemRatesParams} from './ImportPerDiemRatesParams'; export type {default as ExportPerDiemCSVParams} from './ExportPerDiemCSVParams'; export type {default as ExportReportPDFParams} from './ExportReportPDFParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 191248350eeb1..31eda23a97133 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -251,7 +251,6 @@ const WRITE_COMMANDS = { SET_POLICY_CUSTOM_TAX_NAME: 'SetPolicyCustomTaxName', JOIN_POLICY_VIA_INVITE_LINK: 'JoinWorkspaceViaInviteLink', JOIN_ACCESSIBLE_POLICY: 'JoinAccessiblePolicy', - ASK_TO_JOIN_POLICY: 'AskToJoinPolicy', ACCEPT_JOIN_REQUEST: 'AcceptJoinRequest', DECLINE_JOIN_REQUEST: 'DeclineJoinRequest', CREATE_POLICY_TAX: 'CreatePolicyTax', @@ -458,7 +457,6 @@ const WRITE_COMMANDS = { GET_CORPAY_BANK_ACCOUNT_FIELDS: 'GetCorpayBankAccountFields', BANK_ACCOUNT_CREATE_CORPAY: 'BankAccount_CreateCorpay', UPDATE_WORKSPACE_CUSTOM_UNIT: 'UpdateWorkspaceCustomUnit', - GET_ACCESSIBLE_POLICIES: 'GetAccessibleDomainPoliciesForOnyx', VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES: 'ValidateUserAndGetAccessiblePolicies', DISMISS_PRODUCT_TRAINING: 'DismissProductTraining', GET_VALIDATE_CODE_FOR_ACCOUNT_MERGE: 'GetValidateCodeForAccountMerge', @@ -715,7 +713,6 @@ type WriteCommandParameters = { [WRITE_COMMANDS.SEARCH]: Parameters.SearchParams; [WRITE_COMMANDS.SET_POLICY_CATEGORY_TAX]: Parameters.SetPolicyCategoryTaxParams; [WRITE_COMMANDS.JOIN_POLICY_VIA_INVITE_LINK]: Parameters.JoinPolicyInviteLinkParams; - [WRITE_COMMANDS.GET_ACCESSIBLE_POLICIES]: null; [WRITE_COMMANDS.VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES]: Parameters.ValidateUserAndGetAccessiblePoliciesParams; [WRITE_COMMANDS.ACCEPT_JOIN_REQUEST]: Parameters.AcceptJoinRequestParams; [WRITE_COMMANDS.DECLINE_JOIN_REQUEST]: Parameters.DeclineJoinRequestParams; @@ -952,8 +949,6 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_INVOICE_COMPANY_WEBSITE]: Parameters.UpdateInvoiceCompanyWebsiteParams; [WRITE_COMMANDS.JOIN_ACCESSIBLE_POLICY]: Parameters.JoinAccessiblePolicyParams; - [WRITE_COMMANDS.ASK_TO_JOIN_POLICY]: Parameters.AskToJoinPolicyParams; - // Dismis Product Training [WRITE_COMMANDS.DISMISS_PRODUCT_TRAINING]: Parameters.DismissProductTrainingParams; [WRITE_COMMANDS.ADD_WORK_EMAIL]: Parameters.AddWorkEmailParams; diff --git a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx index e4a9925a51f95..ed5832dd7be63 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx @@ -38,13 +38,9 @@ function OnboardingModalNavigator() { const styles = useThemeStyles(); const {onboardingIsMediumOrLargerScreenWidth} = useResponsiveLayout(); const outerViewRef = React.useRef(null); - const [user] = useOnyx(ONYXKEYS.USER, {canBeMissing: true}); - - const isOnPrivateDomainAndHasAccessiblePolicies = !user?.isFromPublicDomain && user?.hasAccessibleDomainPolicies; - const [accountID] = useOnyx(ONYXKEYS.SESSION, { selector: (session) => session?.accountID ?? CONST.DEFAULT_NUMBER_ID, - canBeMissing: false, + canBeMissing: true, }); // Publish a sign_up event when we start the onboarding flow. This should track basic sign ups @@ -77,14 +73,10 @@ function OnboardingModalNavigator() { style={styles.OnboardingNavigatorInnerView(onboardingIsMediumOrLargerScreenWidth)} > - {/* The OnboardingPurpose screen is shown after the workspace step when the user is on a private domain and has accessible policies. - */} - {!isOnPrivateDomainAndHasAccessiblePolicies && ( - - )} + - {/* The OnboardingPurpose screen is only shown after the workspace step when the user is on a private domain and has accessible policies - */} - {!!isOnPrivateDomainAndHasAccessiblePolicies && ( - - )} ): Partia } const routes = []; - routes.push({name: onboardingRoute.name === SCREENS.ONBOARDING.WORKSPACES ? SCREENS.ONBOARDING.PERSONAL_DETAILS : SCREENS.ONBOARDING.PURPOSE}); + routes.push({name: SCREENS.ONBOARDING.PURPOSE}); if (onboardingRoute.name === SCREENS.ONBOARDING.ACCOUNTING) { routes.push({name: SCREENS.ONBOARDING.EMPLOYEES}); } diff --git a/src/libs/actions/Policy/Member.ts b/src/libs/actions/Policy/Member.ts index 91348f7dac5bd..6d266ff8dab69 100644 --- a/src/libs/actions/Policy/Member.ts +++ b/src/libs/actions/Policy/Member.ts @@ -971,7 +971,7 @@ function importPolicyMembers(policyID: string, members: PolicyMember[]) { * Invite member to the specified policyID * Please see https://github.com/Expensify/App/blob/main/README.md#Security for more details */ -function inviteMemberToWorkspace(policyID: string, inviterEmail?: string) { +function inviteMemberToWorkspace(policyID: string, inviterEmail: string) { const memberJoinKey = `${ONYXKEYS.COLLECTION.POLICY_JOIN_MEMBER}${policyID}` as const; const optimisticMembersState = {policyID, inviterEmail}; @@ -1023,31 +1023,6 @@ function joinAccessiblePolicy(policyID: string) { API.write(WRITE_COMMANDS.JOIN_ACCESSIBLE_POLICY, {policyID}, {optimisticData, failureData}); } -/** - * Ask the policy admin to add member to the selected private domain workspace based on policyID - */ -function askToJoinPolicy(policyID: string) { - const memberJoinKey = `${ONYXKEYS.COLLECTION.POLICY_JOIN_MEMBER}${policyID}` as const; - - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: memberJoinKey, - value: {policyID}, - }, - ]; - - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: memberJoinKey, - value: {policyID, errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.people.error.genericAdd')}, - }, - ]; - - API.write(WRITE_COMMANDS.ASK_TO_JOIN_POLICY, {policyID}, {optimisticData, failureData}); -} - /** * Removes an error after trying to delete a member */ @@ -1260,7 +1235,6 @@ export { setWorkspaceInviteMembersDraft, inviteMemberToWorkspace, joinAccessiblePolicy, - askToJoinPolicy, acceptJoinRequest, declineJoinRequest, isApprover, diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 275d5e92403c1..eb11c07fb8682 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -5050,54 +5050,6 @@ function getAssignedSupportData(policyID: string) { API.read(READ_COMMANDS.GET_ASSIGNED_SUPPORT_DATA, parameters); } -/** - * Validates user account and returns a list of accessible policies. - */ -function getAccessiblePolicies(validateCode?: string) { - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES, - value: { - loading: true, - errors: null, - }, - }, - ]; - - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES, - value: { - loading: false, - errors: null, - }, - }, - ]; - - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: ONYXKEYS.VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES, - value: { - loading: false, - }, - }, - ]; - - const command = validateCode ? WRITE_COMMANDS.VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES : WRITE_COMMANDS.GET_ACCESSIBLE_POLICIES; - - API.write(command, validateCode ? {validateCode} : null, {optimisticData, successData, failureData}); -} - -/** - * Clear the errors from the get accessible policies request - */ -function clearGetAccessiblePoliciesErrors() { - Onyx.merge(ONYXKEYS.VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES, {errors: null}); -} - /** * Call the API to calculate the bill for the new dot */ @@ -5269,8 +5221,6 @@ export { updateDefaultPolicy, getAssignedSupportData, downgradeToTeam, - getAccessiblePolicies, - clearGetAccessiblePoliciesErrors, calculateBillNewDot, payAndDowngrade, clearBillingReceiptDetailsErrors, diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 10e8d0d8f9837..7975f622f023b 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -247,7 +247,6 @@ const addNewMessageWithText = new Set([WRITE_COMMANDS.ADD_COMMENT, WRITE let conciergeChatReportID: string | undefined; let currentUserAccountID = -1; let currentUserEmail: string | undefined; - Onyx.connect({ key: ONYXKEYS.SESSION, callback: (value) => { @@ -3332,7 +3331,7 @@ function openReportFromDeepLink(url: string) { } // We need skip deeplinking if the user hasn't completed the guided setup flow. isOnboardingFlowCompleted({ - onNotCompleted: () => startOnboardingFlow(), + onNotCompleted: startOnboardingFlow, onCompleted: handleDeeplinkNavigation, onCanceled: handleDeeplinkNavigation, }); diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index 6c5ed1c554ee7..524fd8f0fc70f 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -1247,6 +1247,43 @@ const canAnonymousUserAccessRoute = (route: string) => { return false; }; +/** + * Validates user account and returns a list of accessible policies. + */ +function validateUserAndGetAccessiblePolicies(validateCode: string) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.JOINABLE_POLICIES_LOADING, + value: true, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.JOINABLE_POLICIES_LOADING, + value: false, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.JOINABLE_POLICIES_LOADING, + value: false, + }, + ]; + + API.write(WRITE_COMMANDS.VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES, {validateCode}, {optimisticData, successData, failureData}); +} + +function isUserOnPrivateDomain() { + // TODO: Implement this function later, and skip the check for now + // return !!session?.email && !LoginUtils.isEmailPublicDomain(session?.email); + return false; +} + function AddWorkEmail(workEmail: string) { const optimisticData: OnyxUpdate[] = [ { @@ -1459,6 +1496,8 @@ export { hasStashedSession, signUpUser, signInAfterTransitionFromOldDot, + validateUserAndGetAccessiblePolicies, + isUserOnPrivateDomain, AddWorkEmail, MergeIntoAccountAndLogin, resetSMSDeliveryFailureStatus, diff --git a/src/libs/actions/Welcome/OnboardingFlow.ts b/src/libs/actions/Welcome/OnboardingFlow.ts index 3d10833419c01..97bee83a0646f 100644 --- a/src/libs/actions/Welcome/OnboardingFlow.ts +++ b/src/libs/actions/Welcome/OnboardingFlow.ts @@ -68,7 +68,7 @@ function getOnboardingInitialPath(isPrivateDomain?: boolean): string { const isUserFromPublicDomain = user?.isFromPublicDomain; const isVsb = onboardingValues && 'signupQualifier' in onboardingValues && onboardingValues.signupQualifier === CONST.ONBOARDING_SIGNUP_QUALIFIERS.VSB; const isSmb = onboardingValues && 'signupQualifier' in onboardingValues && onboardingValues.signupQualifier === CONST.ONBOARDING_SIGNUP_QUALIFIERS.SMB; - const isIndividual = onboardingValues && 'signupQualifier' in onboardingValues && onboardingValues.signupQualifier === CONST.ONBOARDING_SIGNUP_QUALIFIERS.INDIVIDUAL; + const isIndividual = onboardingValues.signupQualifier === CONST.ONBOARDING_SIGNUP_QUALIFIERS.INDIVIDUAL; if (isVsb) { Onyx.set(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED, CONST.ONBOARDING_CHOICES.MANAGE_TEAM); diff --git a/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx b/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx index f988bd78bfab0..95e16f4ea7f0b 100644 --- a/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx +++ b/src/pages/OnboardingPersonalDetails/BaseOnboardingPersonalDetails.tsx @@ -19,11 +19,11 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {addErrorMessage} from '@libs/ErrorUtils'; import navigateAfterOnboarding from '@libs/navigateAfterOnboarding'; import Navigation from '@libs/Navigation/Navigation'; -import {isCurrentUserValidated} from '@libs/UserUtils'; import {doesContainReservedWord, isValidDisplayName} from '@libs/ValidationUtils'; import {clearPersonalDetailsDraft, setPersonalDetails} from '@userActions/Onboarding'; import {setDisplayName} from '@userActions/PersonalDetails'; import {completeOnboarding as completeOnboardingReport} from '@userActions/Report'; +import {isUserOnPrivateDomain} from '@userActions/Session'; import {setOnboardingAdminsChatReportID, setOnboardingErrorMessage, setOnboardingPolicyID} from '@userActions/Welcome'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -37,8 +37,7 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat const [onboardingPurposeSelected] = useOnyx(ONYXKEYS.ONBOARDING_PURPOSE_SELECTED, {canBeMissing: true}); const [onboardingPolicyID] = useOnyx(ONYXKEYS.ONBOARDING_POLICY_ID, {canBeMissing: true}); const [onboardingAdminsChatReportID] = useOnyx(ONYXKEYS.ONBOARDING_ADMINS_CHAT_REPORT_ID, {canBeMissing: true}); - const [user] = useOnyx(ONYXKEYS.USER, {canBeMissing: true}); - const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST, {canBeMissing: true}); + const [onboardingPersonalDetails] = useOnyx(ONYXKEYS.FORMS.ONBOARDING_PERSONAL_DETAILS_FORM, {canBeMissing: true}); const [onboardingValues] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {canBeMissing: true}); const [conciergeChatReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID, {canBeMissing: true}); // When we merge public email with work email, we now want to navigate to the @@ -49,12 +48,10 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat const {onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout(); const {inputCallbackRef} = useAutoFocusInput(); const [shouldValidateOnChange, setShouldValidateOnChange] = useState(false); + const isPrivateDomain = isUserOnPrivateDomain(); const {canUseDefaultRooms} = usePermissions(); const {activeWorkspaceID} = useActiveWorkspace(); - const isPrivateDomainAndHasAccesiblePolicies = !user?.isFromPublicDomain && !!user?.hasAccessibleDomainPolicies; - const isValidated = isCurrentUserValidated(loginList); - useEffect(() => { setOnboardingErrorMessage(''); }, []); @@ -82,6 +79,23 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat [onboardingPurposeSelected, onboardingAdminsChatReportID, onboardingPolicyID, activeWorkspaceID, canUseDefaultRooms, isSmallScreenWidth, mergedAccountConciergeReportID], ); + useEffect(() => { + /** + * Handle onboarding flow for users on private domains: + * 1. If on a private domain, the flow starts with personal details. + * 2. If the user skips this step, they must select an onboarding purpose. + * 3. If an onboarding purpose is selected and the person is on a private domain, + * skip the personal details step as it was already filled. + */ + const skippedPrivateDomainFlow = isPrivateDomain && onboardingPurposeSelected; + + if (!skippedPrivateDomainFlow || !onboardingPersonalDetails?.firstName || !onboardingPersonalDetails?.lastName) { + return; + } + + completeOnboarding(onboardingPersonalDetails.firstName, onboardingPersonalDetails.lastName); + }, [onboardingPersonalDetails, isPrivateDomain, onboardingPurposeSelected, completeOnboarding]); + const handleSubmit = useCallback( (values: FormOnyxValues<'onboardingPersonalDetailsForm'>) => { const firstName = values.firstName.trim(); @@ -91,15 +105,14 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat clearPersonalDetailsDraft(); setPersonalDetails(firstName, lastName); - if (isPrivateDomainAndHasAccesiblePolicies && !onboardingPurposeSelected) { - const nextRoute = isValidated ? ROUTES.ONBOARDING_WORKSPACES : ROUTES.ONBOARDING_PRIVATE_DOMAIN; - Navigation.navigate(nextRoute.getRoute(route.params?.backTo)); + if (isPrivateDomain && !onboardingPurposeSelected) { + Navigation.navigate(ROUTES.ONBOARDING_PRIVATE_DOMAIN.getRoute(route.params?.backTo)); return; } completeOnboarding(firstName, lastName); }, - [isPrivateDomainAndHasAccesiblePolicies, onboardingPurposeSelected, isValidated, route.params?.backTo, completeOnboarding], + [isPrivateDomain, onboardingPurposeSelected, route.params?.backTo, completeOnboarding], ); const validate = (values: FormOnyxValues<'onboardingPersonalDetailsForm'>) => { @@ -144,8 +157,8 @@ function BaseOnboardingPersonalDetails({currentUserPersonalDetails, shouldUseNat style={[styles.defaultModalContainer, shouldUseNativeStyles && styles.pt8]} > { if (!credentials?.login) { return; } - resendValidateCode(credentials.login); + User.resendValidateCode(credentials.login); }, [credentials?.login]); useEffect(() => { - if (isValidated) { + if (!isValidated) { + sendValidateCode(); return; } - sendValidateCode(); - }, [sendValidateCode, isValidated]); - useEffect(() => { - if (!isValidated || joinablePoliciesLength === 0) { - return; - } - - Navigation.navigate(ROUTES.ONBOARDING_WORKSPACES.getRoute(ROUTES.ONBOARDING_PERSONAL_DETAILS.getRoute()), {forceReplace: true}); - }, [isValidated, joinablePoliciesLength]); + Navigation.navigate(ROUTES.ONBOARDING_WORKSPACES.getRoute()); + }, [sendValidateCode, isValidated]); return ( @@ -73,33 +66,27 @@ function BaseOnboardingPrivateDomain({shouldUseNativeStyles, route}: BaseOnboard progressBarPercentage={40} onBackButtonPress={Navigation.goBack} /> - - - {translate('onboarding.peopleYouMayKnow')} - {translate('onboarding.workspaceYouMayJoin', {domain, email})} - { - getAccessiblePolicies(code); - setHasMagicCodeBeenSent(false); - }} - sendValidateCode={() => { - sendValidateCode(); - setHasMagicCodeBeenSent(true); - }} - clearError={() => clearGetAccessiblePoliciesErrors()} - hideSubmitButton - validateError={getAccessiblePoliciesAction?.errors} - hasMagicCodeBeenSent={hasMagicCodeBeenSent} - allowResubmit - /> - - + + {translate('onboarding.peopleYouMayKnow')} + {translate('onboarding.workspaceYouMayJoin', {domain, email})} + { + Session.validateUserAndGetAccessiblePolicies(code); + return Navigation.navigate(ROUTES.ONBOARDING_WORKSPACES.getRoute(route.params?.backTo)); + }} + sendValidateCode={sendValidateCode} + clearError={() => {}} + hideSubmitButton + /> +