diff --git a/assets/animations/Plane.lottie b/assets/animations/Plane.lottie new file mode 100644 index 000000000000..5244cb7bea10 Binary files /dev/null and b/assets/animations/Plane.lottie differ diff --git a/assets/images/simple-illustrations/simple-illustration__alert.svg b/assets/images/simple-illustrations/simple-illustration__alert.svg new file mode 100644 index 000000000000..55429cf39b8f --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__alert.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/images/suitcase.svg b/assets/images/suitcase.svg new file mode 100644 index 000000000000..97036db6b5ac --- /dev/null +++ b/assets/images/suitcase.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 179cc751ef3f..a1b76414f800 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -754,8 +754,10 @@ const ROUTES = { route: 'referral/:contentType', getRoute: (contentType: string, backTo?: string) => getUrlWithBackToParam(`referral/${contentType}`, backTo), }, - TRACK_TRAINING_MODAL: 'track-training', PROCESS_MONEY_REQUEST_HOLD: 'hold-expense-educational', + TRAVEL_MY_TRIPS: 'travel', + TRAVEL_TCS: 'travel/terms', + TRACK_TRAINING_MODAL: 'track-training', ONBOARDING_ROOT: 'onboarding', ONBOARDING_PERSONAL_DETAILS: 'onboarding/personal-details', ONBOARDING_WORK: 'onboarding/work', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 00933686004f..223e276e2e26 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -23,6 +23,10 @@ const SCREENS = { CONNECTION_COMPLETE: 'ConnectionComplete', UNLINK_LOGIN: 'UnlinkLogin', SETTINGS_CENTRAL_PANE: 'SettingsCentralPane', + TRAVEL: { + MY_TRIPS: 'Travel_MyTrips', + TCS: 'Travel_TCS', + }, WORKSPACES_CENTRAL_PANE: 'WorkspacesCentralPane', SEARCH: { CENTRAL_PANE: 'Search_Central_Pane', @@ -133,6 +137,7 @@ const SCREENS = { ROOM_INVITE: 'RoomInvite', REFERRAL: 'Referral', PROCESS_MONEY_REQUEST_HOLD: 'ProcessMoneyRequestHold', + TRAVEL: 'Travel', SEARCH_REPORT: 'SearchReport', }, ONBOARDING_MODAL: { diff --git a/src/components/FeatureList.tsx b/src/components/FeatureList.tsx index 5f713d5f3aef..85f421731cfa 100644 --- a/src/components/FeatureList.tsx +++ b/src/components/FeatureList.tsx @@ -1,6 +1,6 @@ import React from 'react'; import {View} from 'react-native'; -import type {StyleProp, ViewStyle} from 'react-native'; +import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import variables from '@styles/variables'; @@ -43,6 +43,12 @@ type FeatureListProps = { /** The background color to apply in the upper half of the screen. */ illustrationBackgroundColor?: string; + + /** The style used for the title */ + titleStyles?: StyleProp; + + /** Padding for content on large screens */ + contentPaddingOnLargeScreens?: {padding: number}; }; function FeatureList({ @@ -55,6 +61,8 @@ function FeatureList({ illustration, illustrationStyle, illustrationBackgroundColor, + titleStyles, + contentPaddingOnLargeScreens, }: FeatureListProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -68,6 +76,8 @@ function FeatureList({ illustration={illustration} illustrationBackgroundColor={illustrationBackgroundColor} illustrationStyle={illustrationStyle} + titleStyles={titleStyles} + contentPaddingOnLargeScreens={contentPaddingOnLargeScreens} > diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts index 22117652c5f9..f564bcf48345 100644 --- a/src/components/Icon/Expensicons.ts +++ b/src/components/Icon/Expensicons.ts @@ -144,6 +144,7 @@ import Podcast from '@assets/images/social-podcast.svg'; import Twitter from '@assets/images/social-twitter.svg'; import Youtube from '@assets/images/social-youtube.svg'; import Stopwatch from '@assets/images/stopwatch.svg'; +import Suitcase from '@assets/images/suitcase.svg'; import Sync from '@assets/images/sync.svg'; import Tag from '@assets/images/tag.svg'; import Task from '@assets/images/task.svg'; @@ -302,6 +303,7 @@ export { Send, Shield, Stopwatch, + Suitcase, Sync, Task, ThumbsUp, diff --git a/src/components/Icon/Illustrations.ts b/src/components/Icon/Illustrations.ts index b639b2efdd26..8d3f53be9396 100644 --- a/src/components/Icon/Illustrations.ts +++ b/src/components/Icon/Illustrations.ts @@ -31,6 +31,7 @@ import ThreeLeggedLaptopWoman from '@assets/images/product-illustrations/three_l import ToddBehindCloud from '@assets/images/product-illustrations/todd-behind-cloud.svg'; import Abacus from '@assets/images/simple-illustrations/simple-illustration__abacus.svg'; import Accounting from '@assets/images/simple-illustrations/simple-illustration__accounting.svg'; +import Alert from '@assets/images/simple-illustrations/simple-illustration__alert.svg'; import Approval from '@assets/images/simple-illustrations/simple-illustration__approval.svg'; import BankArrow from '@assets/images/simple-illustrations/simple-illustration__bank-arrow.svg'; import BigRocket from '@assets/images/simple-illustrations/simple-illustration__bigrocket.svg'; @@ -160,6 +161,7 @@ export { Workflows, ThreeLeggedLaptopWoman, House, + Alert, TeachersUnite, Abacus, Binoculars, diff --git a/src/components/LottieAnimations/index.tsx b/src/components/LottieAnimations/index.tsx index 18cb9188d60c..598819e19361 100644 --- a/src/components/LottieAnimations/index.tsx +++ b/src/components/LottieAnimations/index.tsx @@ -67,6 +67,11 @@ const DotLottieAnimations = { w: 200, h: 120, }, + Plane: { + file: require('@assets/animations/Plane.lottie'), + w: 180, + h: 200, + }, } satisfies Record; export default DotLottieAnimations; diff --git a/src/components/Section/index.tsx b/src/components/Section/index.tsx index 848761c9e982..7f7d759c72aa 100644 --- a/src/components/Section/index.tsx +++ b/src/components/Section/index.tsx @@ -68,6 +68,9 @@ type SectionProps = ChildrenProps & { /** Styles to apply to illustration component */ illustrationStyle?: StyleProp; + /** Padding for content on large screens */ + contentPaddingOnLargeScreens?: {padding: number}; + /** Overlay content to display on top of animation */ overlayContent?: () => ReactNode; @@ -92,6 +95,7 @@ function Section({ illustration, illustrationBackgroundColor, illustrationStyle, + contentPaddingOnLargeScreens, overlayContent, renderSubtitle, }: SectionProps) { @@ -124,7 +128,7 @@ function Section({ {overlayContent?.()} )} - + {cardLayout === CARD_LAYOUT.ICON_ON_LEFT && ( require('../../../../pages/settings/Profile/PersonalDetails/StateSelectionPage').default as React.ComponentType, }); +const TravelModalStackNavigator = createModalStackNavigator({ + [SCREENS.TRAVEL.MY_TRIPS]: () => require('../../../../pages/Travel/MyTripsPage').default as React.ComponentType, + [SCREENS.TRAVEL.TCS]: () => require('../../../../pages/Travel/TravelTerms').default as React.ComponentType, +}); + const SplitDetailsModalStackNavigator = createModalStackNavigator({ [SCREENS.SPLIT_DETAILS.ROOT]: () => require('../../../../pages/iou/SplitBillDetailsPage').default as React.ComponentType, }); @@ -364,6 +370,7 @@ export { PrivateNotesModalStackNavigator, ProfileModalStackNavigator, ReferralModalStackNavigator, + TravelModalStackNavigator, WorkspaceSwitcherModalStackNavigator, ReimbursementAccountModalStackNavigator, ReportDetailsModalStackNavigator, diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx index c3cff62eefe2..1d595f05ee88 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.tsx @@ -133,6 +133,10 @@ function RightModalNavigator({navigation}: RightModalNavigatorProps) { name="ProcessMoneyRequestHold" component={ModalStackNavigators.ProcessMoneyRequestHoldStackNavigator} /> + | undefined; const routes = navigationState?.routes; const currentRoute = routes?.[navigationState?.index ?? 0]; - + // When we are redirected to the Settings tab from the OldDot, we don't want to call the Welcome.show() method. + // To prevent this, the value of the bottomTabRoute?.name is checked here if (Boolean(currentRoute && currentRoute.name !== NAVIGATORS.BOTTOM_TAB_NAVIGATOR && currentRoute.name !== NAVIGATORS.CENTRAL_PANE_NAVIGATOR) || Session.isAnonymousUser()) { return; } diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index a34bac1fb9c5..00ae38136c3b 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -688,6 +688,12 @@ const config: LinkingOptions['config'] = { [SCREENS.PROCESS_MONEY_REQUEST_HOLD_ROOT]: ROUTES.PROCESS_MONEY_REQUEST_HOLD, }, }, + [SCREENS.RIGHT_MODAL.TRAVEL]: { + screens: { + [SCREENS.TRAVEL.MY_TRIPS]: ROUTES.TRAVEL_MY_TRIPS, + [SCREENS.TRAVEL.TCS]: ROUTES.TRAVEL_TCS, + }, + }, [SCREENS.RIGHT_MODAL.SEARCH_REPORT]: { screens: { [SCREENS.SEARCH.REPORT_RHP]: ROUTES.SEARCH_REPORT.route, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 68320f306f80..e210879f3795 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -707,6 +707,12 @@ type RightModalNavigatorParamList = { [SCREENS.RIGHT_MODAL.PROCESS_MONEY_REQUEST_HOLD]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.REFERRAL]: NavigatorScreenParams; [SCREENS.RIGHT_MODAL.PRIVATE_NOTES]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.TRAVEL]: NavigatorScreenParams; + [SCREENS.RIGHT_MODAL.SEARCH_REPORT]: NavigatorScreenParams; +}; + +type TravelNavigatorParamList = { + [SCREENS.TRAVEL.MY_TRIPS]: undefined; [SCREENS.RIGHT_MODAL.SEARCH_REPORT]: NavigatorScreenParams; }; @@ -931,6 +937,7 @@ export type { State, StateOrRoute, SwitchPolicyIDParams, + TravelNavigatorParamList, TaskDetailsNavigatorParamList, TeachersUniteNavigatorParamList, WalletStatementNavigatorParamList, diff --git a/src/libs/actions/Travel.ts b/src/libs/actions/Travel.ts new file mode 100644 index 000000000000..02affae0fe67 --- /dev/null +++ b/src/libs/actions/Travel.ts @@ -0,0 +1,26 @@ +import type {OnyxUpdate} from 'react-native-onyx'; +import * as API from '@libs/API'; +import {WRITE_COMMANDS} from '@libs/API/types'; +import ONYXKEYS from '@src/ONYXKEYS'; + +/** + * Accept Spotnana terms and conditions to receive a proper token used for authenticating further actions + */ +function acceptSpotnanaTerms() { + const successData: OnyxUpdate[] = [ + { + onyxMethod: 'merge', + key: ONYXKEYS.ACCOUNT, + value: { + travelSettings: { + hasAcceptedTerms: true, + }, + }, + }, + ]; + + API.write(WRITE_COMMANDS.ACCEPT_SPOTNANA_TERMS, {}, {successData}); +} + +// eslint-disable-next-line import/prefer-default-export +export {acceptSpotnanaTerms}; diff --git a/src/pages/Travel/ManageTrips.tsx b/src/pages/Travel/ManageTrips.tsx new file mode 100644 index 000000000000..401f06277b5e --- /dev/null +++ b/src/pages/Travel/ManageTrips.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import {View} from 'react-native'; +import type {FeatureListItem} from '@components/FeatureList'; +import FeatureList from '@components/FeatureList'; +import * as Illustrations from '@components/Icon/Illustrations'; +import LottieAnimations from '@components/LottieAnimations'; +import ScrollView from '@components/ScrollView'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import useWindowDimensions from '@hooks/useWindowDimensions'; +import Navigation from '@libs/Navigation/Navigation'; +import colors from '@styles/theme/colors'; +import ROUTES from '@src/ROUTES'; +import getTripIllustrationStyle from './getTripIllustrationStyle'; + +const tripsFeatures: FeatureListItem[] = [ + { + icon: Illustrations.PiggyBank, + translationKey: 'travel.features.saveMoney', + }, + { + icon: Illustrations.Alert, + translationKey: 'travel.features.alerts', + }, +]; + +function ManageTrips() { + const styles = useThemeStyles(); + const {isSmallScreenWidth} = useWindowDimensions(); + const {translate} = useLocalize(); + const illustrationStyle = getTripIllustrationStyle(); + + return ( + + + { + Navigation.navigate(ROUTES.TRAVEL_TCS); + }} + illustration={LottieAnimations.Plane} + illustrationStyle={illustrationStyle} + illustrationBackgroundColor={colors.blue600} + titleStyles={styles.textHeadlineH1} + contentPaddingOnLargeScreens={styles.p5} + /> + + + ); +} + +ManageTrips.displayName = 'ManageTrips'; + +export default ManageTrips; diff --git a/src/pages/Travel/MyTripsPage.tsx b/src/pages/Travel/MyTripsPage.tsx new file mode 100644 index 000000000000..be29e8dc8c12 --- /dev/null +++ b/src/pages/Travel/MyTripsPage.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import useLocalize from '@hooks/useLocalize'; +import usePermissions from '@hooks/usePermissions'; +import ManageTrips from './ManageTrips'; + +function MyTripsPage() { + const {translate} = useLocalize(); + const {canUseSpotnanaTravel} = usePermissions(); + + return ( + + + + + + + ); +} + +MyTripsPage.displayName = 'MyTripsPage'; + +export default MyTripsPage; diff --git a/src/pages/Travel/TravelTerms.tsx b/src/pages/Travel/TravelTerms.tsx new file mode 100644 index 000000000000..6852275dfe91 --- /dev/null +++ b/src/pages/Travel/TravelTerms.tsx @@ -0,0 +1,110 @@ +import React, {useCallback, useEffect, useState} from 'react'; +import {View} from 'react-native'; +import {ScrollView} from 'react-native-gesture-handler'; +import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; +import CheckboxWithLabel from '@components/CheckboxWithLabel'; +import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import SafeAreaConsumer from '@components/SafeAreaConsumer'; +import ScreenWrapper from '@components/ScreenWrapper'; +import Text from '@components/Text'; +import TextLink from '@components/TextLink'; +import useLocalize from '@hooks/useLocalize'; +import usePermissions from '@hooks/usePermissions'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@libs/Navigation/Navigation'; +import * as Travel from '@userActions/Travel'; + +function TravelTerms() { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const {canUseSpotnanaTravel} = usePermissions(); + const [hasAcceptedTravelTerms, setHasAcceptedTravelTerms] = useState(false); + const [error, setError] = useState(false); + + const errorMessage = error ? 'travel.termsAndConditions.error' : ''; + + const toggleTravelTerms = () => { + setHasAcceptedTravelTerms(!hasAcceptedTravelTerms); + }; + + useEffect(() => { + if (!hasAcceptedTravelTerms) { + return; + } + + setError(false); + }, [hasAcceptedTravelTerms]); + + const AgreeToTheLabel = useCallback( + () => ( + + {`${translate('travel.termsAndConditions.agree')}`} + {`${translate('travel.termsAndConditions.travelTermsAndConditions')}`} + + ), + [translate], + ); + + // Add beta support for FullPageNotFound that is universal across travel pages + return ( + + + Navigation.goBack()} + /> + + {({safeAreaPaddingBottomStyle}) => ( + + + {`${translate('travel.termsAndConditions.title')}`} + + {`${translate('travel.termsAndConditions.subtitle')}`} + {`${translate('travel.termsAndConditions.termsconditions')}.`} + + + {`${translate('travel.termsAndConditions.helpDocIntro')}`} + {`${translate('travel.termsAndConditions.helpDoc')} `} + {`${translate('travel.termsAndConditions.helpDocOutro')}`} + + + + + { + if (!hasAcceptedTravelTerms) { + setError(true); + return; + } + + Travel.acceptSpotnanaTerms(); + setError(false); + Navigation.resetToHome(); + }} + message={errorMessage} + isAlertVisible={error || Boolean(errorMessage)} + containerStyles={[styles.mh0, styles.mt5]} + /> + + )} + + + + ); +} + +TravelTerms.displayName = 'TravelMenu'; + +export default TravelTerms; diff --git a/src/pages/Travel/getTripIllustrationStyle/index.native.ts b/src/pages/Travel/getTripIllustrationStyle/index.native.ts new file mode 100644 index 000000000000..e5b0a1381d7e --- /dev/null +++ b/src/pages/Travel/getTripIllustrationStyle/index.native.ts @@ -0,0 +1,8 @@ +import type {ViewStyle} from 'react-native'; + +// Styling lottie animations for the ManageTrips component requires different margin values depending on the platform. +export default function getTripIllustrationStyle(): ViewStyle { + return { + marginVertical: 20, + }; +} diff --git a/src/pages/Travel/getTripIllustrationStyle/index.ts b/src/pages/Travel/getTripIllustrationStyle/index.ts new file mode 100644 index 000000000000..a2a141022d73 --- /dev/null +++ b/src/pages/Travel/getTripIllustrationStyle/index.ts @@ -0,0 +1,9 @@ +import type {ViewStyle} from 'react-native'; + +// Styling lottie animations for the ManageTrips component requires different margin values depending on the platform. +export default function getTripIllustrationStyle(): ViewStyle { + return { + marginTop: 20, + marginBottom: -20, + }; +} diff --git a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx index cc61e61aa1f8..9f492ad90a5b 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx @@ -178,6 +178,7 @@ function FloatingActionButtonAndPopover( const prevIsFocused = usePrevious(isFocused); const {isOffline} = useNetwork(); + const {canUseSpotnanaTravel} = usePermissions(); const canSendInvoice = useMemo(() => PolicyUtils.canSendInvoice(allPolicies as OnyxCollection), [allPolicies]); const quickActionAvatars = useMemo(() => { @@ -401,6 +402,15 @@ function FloatingActionButtonAndPopover( text: translate('newTaskPage.assignTask'), onSelected: () => interceptAnonymousUser(() => Task.clearOutTaskInfoAndNavigate()), }, + ...(canUseSpotnanaTravel + ? [ + { + icon: Expensicons.Suitcase, + text: translate('travel.bookTravel'), + onSelected: () => interceptAnonymousUser(() => Navigation.navigate(ROUTES.TRAVEL_MY_TRIPS)), + }, + ] + : []), ...(!isLoading && !Policy.hasActiveChatEnabledPolicies(allPolicies) ? [ { diff --git a/src/styles/index.ts b/src/styles/index.ts index 365c89ac4a18..1b1587d81bce 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1868,6 +1868,11 @@ const styles = (theme: ThemeColors) => marginBottom: -20, }, + travelIllustrationStyle: { + marginTop: 16, + marginBottom: -16, + }, + overlayStyles: (current: OverlayStylesParams, isModalOnTheLeft: boolean) => ({ ...positioning.pFixed, diff --git a/src/types/onyx/Account.ts b/src/types/onyx/Account.ts index 67ff12c74150..c53d7ea816f8 100644 --- a/src/types/onyx/Account.ts +++ b/src/types/onyx/Account.ts @@ -2,6 +2,7 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; import type DismissedReferralBanners from './DismissedReferralBanners'; import type * as OnyxCommon from './OnyxCommon'; +import type {TravelSettings} from './TravelSettings'; type TwoFactorAuthStep = ValueOf | ''; @@ -59,6 +60,9 @@ type Account = { codesAreCopied?: boolean; twoFactorAuthStep?: TwoFactorAuthStep; dismissedReferralBanners?: DismissedReferralBanners; + + /** Object containing all account information necessary to connect with Spontana */ + travelSettings?: TravelSettings; }; export default Account; diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index d64de6196985..b2ec43c4f55e 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -3,6 +3,7 @@ import type CONST from '@src/CONST'; import type {Country} from '@src/CONST'; import type * as OnyxTypes from '.'; import type * as OnyxCommon from './OnyxCommon'; +import type {WorkspaceTravelSettings} from './TravelSettings'; type Unit = 'mi' | 'km'; @@ -523,6 +524,9 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback< /** Indicates if the Policy ownership change is failed */ isChangeOwnerFailed?: boolean; + + /** Object containing all policy information necessary to connect with Spontana */ + travelSettings?: WorkspaceTravelSettings; } & Partial, 'generalSettings' | 'addWorkspaceRoom' | keyof ACHAccount >; diff --git a/src/types/onyx/TravelSettings.ts b/src/types/onyx/TravelSettings.ts new file mode 100644 index 000000000000..e653c3378572 --- /dev/null +++ b/src/types/onyx/TravelSettings.ts @@ -0,0 +1,17 @@ +type TravelSettings = { + /** UUIDs that spotnana provides us with when we provision users in their system, and the spotnanaCompanyIDs as the values */ + accountIDs: Record; + + /** Whether the user has completed the travel terms and conditions checkbox */ + hasAcceptedTerms: boolean; +}; + +type WorkspaceTravelSettings = { + /** The UUID that spotnana provides us when we create a “company” in their system */ + spotnanaCompanyID: string; + + /** The UUID that spotnana provides us when we provision the workspace as an “entity” in their system */ + spotnanaEntityID: boolean; +}; + +export type {TravelSettings, WorkspaceTravelSettings}; diff --git a/tests/utils/collections/userAccount.ts b/tests/utils/collections/userAccount.ts index 9e7c33a228d5..ebaa0a132169 100644 --- a/tests/utils/collections/userAccount.ts +++ b/tests/utils/collections/userAccount.ts @@ -7,6 +7,10 @@ function getValidAccount(credentialLogin = ''): Account { primaryLogin: credentialLogin, isLoading: false, requiresTwoFactorAuth: false, + travelSettings: { + accountIDs: {}, + hasAcceptedTerms: false, + }, }; }