diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index b5eea4228042..46d8be0f7e82 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -169,6 +169,9 @@ const ONYXKEYS = { /** The NVP with the last action taken (for the Quick Action Button) */ NVP_QUICK_ACTION_GLOBAL_CREATE: 'nvp_quickActionGlobalCreate', + /** The NVP containing all information necessary to connect with Spontana */ + NVP_TRAVEL_SETTINGS: 'nvp_travelSettings', + /** The start date (yyyy-MM-dd HH:mm:ss) of the workspace owner’s free trial period. */ NVP_FIRST_DAY_FREE_TRIAL: 'nvp_private_firstDayFreeTrial', @@ -722,6 +725,7 @@ type OnyxValuesMapping = { [ONYXKEYS.CACHED_PDF_PATHS]: Record; [ONYXKEYS.POLICY_OWNERSHIP_CHANGE_CHECKS]: Record; [ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE]: OnyxTypes.QuickAction; + [ONYXKEYS.NVP_TRAVEL_SETTINGS]: OnyxTypes.TravelSettings; [ONYXKEYS.REVIEW_DUPLICATES]: OnyxTypes.ReviewDuplicates; [ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL]: string; [ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL]: string; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 92b6d7679418..89479186aea3 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -560,6 +560,7 @@ const SIDE_EFFECT_REQUEST_COMMANDS = { JOIN_POLICY_VIA_INVITE_LINK: 'JoinWorkspaceViaInviteLink', RECONNECT_APP: 'ReconnectApp', GENERATE_SPOTNANA_TOKEN: 'GenerateSpotnanaToken', + ACCEPT_SPOTNANA_TERMS: 'AcceptSpotnanaTerms', } as const; type SideEffectRequestCommand = ValueOf; @@ -573,6 +574,7 @@ type SideEffectRequestCommandParameters = { [SIDE_EFFECT_REQUEST_COMMANDS.JOIN_POLICY_VIA_INVITE_LINK]: Parameters.JoinPolicyInviteLinkParams; [SIDE_EFFECT_REQUEST_COMMANDS.RECONNECT_APP]: Parameters.ReconnectAppParams; [SIDE_EFFECT_REQUEST_COMMANDS.GENERATE_SPOTNANA_TOKEN]: Parameters.GenerateSpotnanaTokenParams; + [SIDE_EFFECT_REQUEST_COMMANDS.ACCEPT_SPOTNANA_TERMS]: EmptyObject; }; type ApiRequestCommandParameters = WriteCommandParameters & ReadCommandParameters & SideEffectRequestCommandParameters; diff --git a/src/libs/actions/Link.ts b/src/libs/actions/Link.ts index f97c4e17a9a5..702153dac0b7 100644 --- a/src/libs/actions/Link.ts +++ b/src/libs/actions/Link.ts @@ -157,4 +157,4 @@ function openLink(href: string, environmentURL: string, isAttachment = false) { openExternalLink(href); } -export {buildOldDotURL, openOldDotLink, openExternalLink, openLink, getInternalNewExpensifyPath, getInternalExpensifyPath, openTravelDotLink}; +export {buildOldDotURL, openOldDotLink, openExternalLink, openLink, getInternalNewExpensifyPath, getInternalExpensifyPath, openTravelDotLink, buildTravelDotURL}; diff --git a/src/libs/actions/Travel.ts b/src/libs/actions/Travel.ts index 02affae0fe67..38a8ce347b3f 100644 --- a/src/libs/actions/Travel.ts +++ b/src/libs/actions/Travel.ts @@ -1,25 +1,31 @@ import type {OnyxUpdate} from 'react-native-onyx'; import * as API from '@libs/API'; -import {WRITE_COMMANDS} from '@libs/API/types'; +import {SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types'; +import asyncOpenURL from '@libs/asyncOpenURL'; import ONYXKEYS from '@src/ONYXKEYS'; +import {buildTravelDotURL} from './Link'; /** * Accept Spotnana terms and conditions to receive a proper token used for authenticating further actions */ function acceptSpotnanaTerms() { - const successData: OnyxUpdate[] = [ + const optimisticData: OnyxUpdate[] = [ { onyxMethod: 'merge', - key: ONYXKEYS.ACCOUNT, + key: ONYXKEYS.NVP_TRAVEL_SETTINGS, value: { - travelSettings: { - hasAcceptedTerms: true, - }, + hasAcceptedTerms: true, }, }, ]; - API.write(WRITE_COMMANDS.ACCEPT_SPOTNANA_TERMS, {}, {successData}); + asyncOpenURL( + // eslint-disable-next-line rulesdir/no-api-side-effects-method + API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.ACCEPT_SPOTNANA_TERMS, {}, {optimisticData}) + .then((response) => (response?.spotnanaToken ? buildTravelDotURL(response.spotnanaToken) : buildTravelDotURL())) + .catch(() => buildTravelDotURL()), + (travelDotURL) => travelDotURL, + ); } // eslint-disable-next-line import/prefer-default-export diff --git a/src/pages/Travel/ManageTrips.tsx b/src/pages/Travel/ManageTrips.tsx index 3779e22ec6ef..5f32b51cc1f6 100644 --- a/src/pages/Travel/ManageTrips.tsx +++ b/src/pages/Travel/ManageTrips.tsx @@ -1,5 +1,6 @@ import React from 'react'; import {Linking, View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; import type {FeatureListItem} from '@components/FeatureList'; import FeatureList from '@components/FeatureList'; import * as Illustrations from '@components/Icon/Illustrations'; @@ -9,7 +10,9 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import Navigation from '@libs/Navigation/Navigation'; import colors from '@styles/theme/colors'; +import * as Link from '@userActions/Link'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; const tripsFeatures: FeatureListItem[] = [ @@ -27,6 +30,10 @@ function ManageTrips() { const styles = useThemeStyles(); const {isSmallScreenWidth} = useWindowDimensions(); const {translate} = useLocalize(); + const [travelSettings] = useOnyx(ONYXKEYS.NVP_TRAVEL_SETTINGS); + const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); + + const hasAcceptedTravelTerms = travelSettings?.hasAcceptedTerms; const navigateToBookTravelDemo = () => { Linking.openURL(CONST.BOOK_TRAVEL_DEMO_URL); @@ -42,7 +49,11 @@ function ManageTrips() { ctaText={translate('travel.bookTravel')} ctaAccessibilityLabel={translate('travel.bookTravel')} onCtaPress={() => { - Navigation.navigate(ROUTES.TRAVEL_TCS); + if (!hasAcceptedTravelTerms) { + Navigation.navigate(ROUTES.TRAVEL_TCS); + return; + } + Link.openTravelDotLink(activePolicyID); }} illustration={Illustrations.EmptyStateTravel} illustrationStyle={[styles.mv4, styles.tripIllustrationSize]} diff --git a/src/pages/Travel/TravelTerms.tsx b/src/pages/Travel/TravelTerms.tsx index 1c22ea51b178..42310a3ed4a8 100644 --- a/src/pages/Travel/TravelTerms.tsx +++ b/src/pages/Travel/TravelTerms.tsx @@ -92,7 +92,7 @@ function TravelTerms() { Travel.acceptSpotnanaTerms(); setError(false); - Navigation.resetToHome(); + Navigation.goBack(); }} message={errorMessage} isAlertVisible={error || !!errorMessage} diff --git a/src/types/onyx/Account.ts b/src/types/onyx/Account.ts index dc9d0c937cd2..6113f67ce201 100644 --- a/src/types/onyx/Account.ts +++ b/src/types/onyx/Account.ts @@ -2,7 +2,6 @@ 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'; /** Two factor authentication steps */ type TwoFactorAuthStep = ValueOf | ''; @@ -72,9 +71,6 @@ type Account = { /** Referral banners that the user dismissed */ dismissedReferralBanners?: DismissedReferralBanners; - /** Object containing all account information necessary to connect with Spontana */ - travelSettings?: TravelSettings; - /** Indicates whether the user is an approved accountant */ isApprovedAccountant?: boolean; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index becb56cb09f0..27e32f8e8c9c 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -76,6 +76,7 @@ import type Task from './Task'; import type Transaction from './Transaction'; import type {TransactionViolation, ViolationName} from './TransactionViolation'; import type TransactionViolations from './TransactionViolation'; +import type {TravelSettings} from './TravelSettings'; import type User from './User'; import type UserLocation from './UserLocation'; import type UserMetadata from './UserMetadata'; @@ -162,6 +163,7 @@ export type { Transaction, TransactionViolation, TransactionViolations, + TravelSettings, User, UserLocation, UserMetadata, diff --git a/tests/utils/collections/userAccount.ts b/tests/utils/collections/userAccount.ts index ebaa0a132169..9e7c33a228d5 100644 --- a/tests/utils/collections/userAccount.ts +++ b/tests/utils/collections/userAccount.ts @@ -7,10 +7,6 @@ function getValidAccount(credentialLogin = ''): Account { primaryLogin: credentialLogin, isLoading: false, requiresTwoFactorAuth: false, - travelSettings: { - accountIDs: {}, - hasAcceptedTerms: false, - }, }; }