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..2e7bca02f5e3 --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__alert.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/images/simple-illustrations/simple-illustration__piggybank.svg b/assets/images/simple-illustrations/simple-illustration__piggybank.svg index a9cf2b02c5dc..be87ff34752a 100644 --- a/assets/images/simple-illustrations/simple-illustration__piggybank.svg +++ b/assets/images/simple-illustrations/simple-illustration__piggybank.svg @@ -1,50 +1,50 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/CONST.ts b/src/CONST.ts index 310bb3959300..4442635e6767 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -584,6 +584,7 @@ const CONST = { ONFIDO_PRIVACY_POLICY_URL: 'https://onfido.com/privacy/', ONFIDO_TERMS_OF_SERVICE_URL: 'https://onfido.com/terms-of-service/', LIST_OF_RESTRICTED_BUSINESSES: 'https://community.expensify.com/discussion/6191/list-of-restricted-businesses', + TRAVEL_TERMS_URL: `${USE_EXPENSIFY_URL}/travelterms`, // Use Environment.getEnvironmentURL to get the complete URL with port number DEV_NEW_EXPENSIFY_URL: 'https://dev.new.expensify.com:', diff --git a/src/ROUTES.ts b/src/ROUTES.ts index df87daf52b57..341d058d2cd1 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -758,8 +758,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 1129a86a4e92..45c9906e8ca3 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..5e4ab89cf150 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} > @@ -79,8 +89,8 @@ function FeatureList({ ; 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, }); @@ -367,6 +373,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 1fdd575364f3..618805f3c02a 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -692,6 +692,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 40427bf8cbbd..eabdb29db495 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -713,6 +713,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; }; @@ -937,6 +943,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/OnboardingPurpose/BaseOnboardingPurpose.tsx b/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx index ced19a99d493..14de7a0f4c14 100644 --- a/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx +++ b/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx @@ -86,8 +86,8 @@ function BaseOnboardingPurpose({shouldUseNativeStyles, shouldEnableMaxHeight, on title: translate(translationKey), icon: menuIcons[choice], displayInDefaultIconColor: true, - iconWidth: variables.purposeMenuIconSize, - iconHeight: variables.purposeMenuIconSize, + iconWidth: variables.menuIconSize, + iconHeight: variables.menuIconSize, iconStyles: [styles.mh3], wrapperStyle: [styles.purposeMenuItem, isSelected && styles.purposeMenuItemSelected], hoverAndPressStyle: [styles.purposeMenuItemSelected], 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..468ca9b8082a --- /dev/null +++ b/src/pages/Travel/TravelTerms.tsx @@ -0,0 +1,111 @@ +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'; +import CONST from '@src/CONST'; + +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 bc7b49f94c91..8ac3f7e0ca94 100644 --- a/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx +++ b/src/pages/home/sidebar/SidebarScreen/FloatingActionButtonAndPopover.tsx @@ -180,6 +180,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(() => { @@ -403,6 +404,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/styles/variables.ts b/src/styles/variables.ts index ad0ffeecda40..023dc39bb3d1 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -211,7 +211,7 @@ export default { hoverDimValue: 1, pressDimValue: 0.8, qrShareHorizontalPadding: 32, - purposeMenuIconSize: 48, + menuIconSize: 48, moneyRequestSkeletonHeight: 107, 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 cbae62c7d29e..fed42477c635 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'; @@ -520,6 +521,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, + }, }; }