Skip to content

Commit e489519

Browse files
authored
Merge pull request Expensify#88479 from ShridharGoel/gusto1.6
[NoQA] Implement Gusto connection flow
2 parents e53ad87 + fba8411 commit e489519

5 files changed

Lines changed: 123 additions & 7 deletions

File tree

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import React, {useCallback, useRef, useState} from 'react';
2+
import {StyleSheet, View} from 'react-native';
3+
import {WebView} from 'react-native-webview';
4+
import ActivityIndicator from '@components/ActivityIndicator';
5+
import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
6+
import HeaderWithBackButton from '@components/HeaderWithBackButton';
7+
import Modal from '@components/Modal';
8+
import useLocalize from '@hooks/useLocalize';
9+
import useOnyx from '@hooks/useOnyx';
10+
import useThemeStyles from '@hooks/useThemeStyles';
11+
import getGustoSetupLink from '@libs/actions/connections/Gusto';
12+
import CONST from '@src/CONST';
13+
import ONYXKEYS from '@src/ONYXKEYS';
14+
import type ConnectToGustoFlowProps from './types';
15+
16+
function ConnectToGustoFlow({policyID}: ConnectToGustoFlowProps) {
17+
const {translate} = useLocalize();
18+
const styles = useThemeStyles();
19+
const webViewRef = useRef<WebView>(null);
20+
const [isWebViewOpen, setIsWebViewOpen] = useState(true);
21+
const [session] = useOnyx(ONYXKEYS.SESSION);
22+
23+
const renderLoading = useCallback(
24+
() => (
25+
<View style={[StyleSheet.absoluteFill, styles.fullScreenLoading]}>
26+
<ActivityIndicator
27+
size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
28+
reasonAttributes={{context: 'ConnectToGustoFlow'}}
29+
/>
30+
</View>
31+
),
32+
[styles.fullScreenLoading],
33+
);
34+
35+
const authToken = session?.authToken ?? null;
36+
return (
37+
<Modal
38+
onClose={() => setIsWebViewOpen(false)}
39+
fullscreen
40+
isVisible={isWebViewOpen}
41+
type={CONST.MODAL.MODAL_TYPE.CENTERED_UNSWIPEABLE}
42+
>
43+
<HeaderWithBackButton
44+
title={translate('workspace.common.hr')}
45+
onBackButtonPress={() => setIsWebViewOpen(false)}
46+
shouldDisplayHelpButton={false}
47+
/>
48+
<FullPageOfflineBlockingView>
49+
<WebView
50+
ref={webViewRef}
51+
source={{
52+
uri: getGustoSetupLink(policyID),
53+
headers: {
54+
Cookie: `authToken=${authToken}`,
55+
},
56+
}}
57+
incognito
58+
startInLoadingState
59+
renderLoading={renderLoading}
60+
/>
61+
</FullPageOfflineBlockingView>
62+
</Modal>
63+
);
64+
}
65+
66+
export default ConnectToGustoFlow;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {useEffect} from 'react';
2+
import useEnvironment from '@hooks/useEnvironment';
3+
import getGustoSetupLink from '@libs/actions/connections/Gusto';
4+
import {openLink} from '@userActions/Link';
5+
import type ConnectToGustoFlowProps from './types';
6+
7+
function ConnectToGustoFlow({policyID}: ConnectToGustoFlowProps) {
8+
const {environmentURL} = useEnvironment();
9+
10+
useEffect(() => {
11+
openLink(getGustoSetupLink(policyID), environmentURL);
12+
}, [environmentURL, policyID]);
13+
14+
return null;
15+
}
16+
17+
export default ConnectToGustoFlow;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type ConnectToGustoFlowProps = {
2+
policyID: string;
3+
};
4+
5+
export default ConnectToGustoFlowProps;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type {ConnectPolicyToGustoParams} from '@libs/API/parameters';
2+
import {READ_COMMANDS} from '@libs/API/types';
3+
import {getCommandURL} from '@libs/ApiUtils';
4+
5+
function getGustoSetupLink(policyID: string) {
6+
const params: ConnectPolicyToGustoParams = {policyID};
7+
const commandURL = getCommandURL({
8+
command: READ_COMMANDS.CONNECT_POLICY_TO_GUSTO,
9+
shouldSkipWebProxy: true,
10+
});
11+
return commandURL + new URLSearchParams(params).toString();
12+
}
13+
14+
export default getGustoSetupLink;

src/pages/workspace/hr/WorkspaceHRPage.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import React, {useCallback, useEffect} from 'react';
1+
import React, {useCallback, useEffect, useState} from 'react';
22
import {View} from 'react-native';
33
import Button from '@components/Button';
4+
import ConnectToGustoFlow from '@components/ConnectToGustoFlow';
45
import HeaderWithBackButton from '@components/HeaderWithBackButton';
56
import MenuItem from '@components/MenuItem';
67
import ScreenWrapper from '@components/ScreenWrapper';
@@ -11,13 +12,15 @@ import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hook
1112
import useLocalize from '@hooks/useLocalize';
1213
import useNetwork from '@hooks/useNetwork';
1314
import usePermissions from '@hooks/usePermissions';
15+
import usePolicy from '@hooks/usePolicy';
1416
import useResponsiveLayout from '@hooks/useResponsiveLayout';
1517
import useThemeStyles from '@hooks/useThemeStyles';
1618
import useWorkspaceDocumentTitle from '@hooks/useWorkspaceDocumentTitle';
1719
import {openPolicyHRPage} from '@libs/actions/PolicyConnections';
1820
import Navigation from '@libs/Navigation/Navigation';
1921
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
2022
import type {WorkspaceSplitNavigatorParamList} from '@libs/Navigation/types';
23+
import {isGustoConnected} from '@libs/PolicyUtils';
2124
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
2225
import CONST from '@src/CONST';
2326
import type SCREENS from '@src/SCREENS';
@@ -33,8 +36,11 @@ function WorkspaceHRPage({
3336
const {isBetaEnabled} = usePermissions();
3437
const styles = useThemeStyles();
3538
const {shouldUseNarrowLayout} = useResponsiveLayout();
39+
const policy = usePolicy(policyID);
40+
const [activeGustoFlowKey, setActiveGustoFlowKey] = useState<number>();
3641
const icons = useMemoizedLazyExpensifyIcons(['GustoSquare']);
3742
const illustrations = useMemoizedLazyIllustrations(['NewUser']);
43+
const isConnected = isGustoConnected(policy);
3844

3945
useWorkspaceDocumentTitle(undefined, 'workspace.common.hr');
4046

@@ -62,6 +68,12 @@ function WorkspaceHRPage({
6268
shouldShowOfflineIndicatorInWideScreen
6369
offlineIndicatorStyle={styles.mtAuto}
6470
>
71+
{!!activeGustoFlowKey && (
72+
<ConnectToGustoFlow
73+
key={activeGustoFlowKey}
74+
policyID={policyID}
75+
/>
76+
)}
6577
<HeaderWithBackButton
6678
icon={illustrations.NewUser}
6779
title={translate('workspace.common.hr')}
@@ -82,13 +94,15 @@ function WorkspaceHRPage({
8294
iconType={CONST.ICON_TYPE_AVATAR}
8395
wrapperStyle={[styles.ph0, styles.pv2, styles.mt4]}
8496
interactive={false}
85-
shouldShowRightComponent
97+
shouldShowRightComponent={!isConnected}
8698
rightComponent={
87-
<Button
88-
small
89-
text={translate('workspace.hr.gusto.connect')}
90-
onPress={() => {}}
91-
/>
99+
!isConnected ? (
100+
<Button
101+
small
102+
text={translate('workspace.hr.gusto.connect')}
103+
onPress={() => setActiveGustoFlowKey(Math.random())}
104+
/>
105+
) : undefined
92106
}
93107
/>
94108
</Section>

0 commit comments

Comments
 (0)