-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
Copy pathBookTravelButton.tsx
120 lines (108 loc) · 5.46 KB
/
BookTravelButton.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import {Str} from 'expensify-common';
import React, {useCallback, useContext, useState} from 'react';
import {NativeModules} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import useLocalize from '@hooks/useLocalize';
import usePolicy from '@hooks/usePolicy';
import useThemeStyles from '@hooks/useThemeStyles';
import {openTravelDotLink} from '@libs/actions/Link';
import {cleanupTravelProvisioningSession} from '@libs/actions/Travel';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import {getAdminsPrivateEmailDomains} from '@libs/PolicyUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import Button from './Button';
import CustomStatusBarAndBackgroundContext from './CustomStatusBarAndBackground/CustomStatusBarAndBackgroundContext';
import DotIndicatorMessage from './DotIndicatorMessage';
type BookTravelButtonProps = {
text: string;
};
const navigateToAcceptTerms = (domain: string) => {
// Remove the previous provision session infromation if any is cached.
cleanupTravelProvisioningSession();
Navigation.navigate(ROUTES.TRAVEL_TCS.getRoute(domain));
};
function BookTravelButton({text}: BookTravelButtonProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID);
const policy = usePolicy(activePolicyID);
const [errorMessage, setErrorMessage] = useState('');
const [travelSettings] = useOnyx(ONYXKEYS.NVP_TRAVEL_SETTINGS);
const [account] = useOnyx(ONYXKEYS.ACCOUNT);
const primaryLogin = account?.primaryLogin;
const {setRootStatusBarEnabled} = useContext(CustomStatusBarAndBackgroundContext);
// Flag indicating whether NewDot was launched exclusively for Travel,
// e.g., when the user selects "Trips" from the Expensify Classic menu in HybridApp.
const [wasNewDotLaunchedJustForTravel] = useOnyx(ONYXKEYS.IS_SINGLE_NEW_DOT_ENTRY);
const bookATrip = useCallback(() => {
setErrorMessage('');
// The primary login of the user is where Spotnana sends the emails with booking confirmations, itinerary etc. It can't be a phone number.
if (!primaryLogin || Str.isSMSLogin(primaryLogin)) {
setErrorMessage(translate('travel.phoneError'));
return;
}
// Spotnana requires an address anytime an entity is created for a policy
if (isEmptyObject(policy?.address)) {
Navigation.navigate(ROUTES.WORKSPACE_PROFILE_ADDRESS.getRoute(policy?.id, Navigation.getActiveRoute()));
return;
}
const isPolicyProvisioned = policy?.travelSettings?.spotnanaCompanyID ?? policy?.travelSettings?.associatedTravelDomainAccountID;
if (policy?.travelSettings?.hasAcceptedTerms ?? (travelSettings?.hasAcceptedTerms && isPolicyProvisioned)) {
openTravelDotLink(policy?.id)
?.then(() => {
// When a user selects "Trips" in the Expensify Classic menu, the HybridApp opens the ManageTrips page in NewDot.
// The wasNewDotLaunchedJustForTravel flag indicates if NewDot was launched solely for this purpose.
if (!NativeModules.HybridAppModule || !wasNewDotLaunchedJustForTravel) {
return;
}
// Close NewDot if it was opened only for Travel, as its purpose is now fulfilled.
Log.info('[HybridApp] Returning to OldDot after opening TravelDot');
NativeModules.HybridAppModule.closeReactNativeApp(false, false);
setRootStatusBarEnabled(false);
})
?.catch(() => {
setErrorMessage(translate('travel.errorMessage'));
});
} else if (isPolicyProvisioned) {
navigateToAcceptTerms(CONST.TRAVEL.DEFAULT_DOMAIN);
} else {
// Determine the domain to associate with the workspace during provisioning in Spotnana.
// - If all admins share the same private domain, the workspace is tied to it automatically.
// - If admins have multiple private domains, the user must select one.
// - Public domains are not allowed; an error page is shown in that case.
const adminDomains = getAdminsPrivateEmailDomains(policy);
if (adminDomains.length === 0) {
Navigation.navigate(ROUTES.TRAVEL_PUBLIC_DOMAIN_ERROR);
} else if (adminDomains.length === 1) {
navigateToAcceptTerms(adminDomains.at(0) ?? CONST.TRAVEL.DEFAULT_DOMAIN);
} else {
Navigation.navigate(ROUTES.TRAVEL_DOMAIN_SELECTOR);
}
}
}, [policy, wasNewDotLaunchedJustForTravel, travelSettings, translate, primaryLogin, setRootStatusBarEnabled]);
return (
<>
{!!errorMessage && (
<DotIndicatorMessage
style={styles.mb1}
messages={{error: errorMessage}}
type="error"
/>
)}
<Button
text={text}
onPress={bookATrip}
accessibilityLabel={translate('travel.bookTravel')}
style={styles.w100}
success
large
/>
</>
);
}
BookTravelButton.displayName = 'BookTravelButton';
export default BookTravelButton;