Skip to content

Commit 6ba2ed4

Browse files
authored
Merge pull request #60078 from callstack-internal/pac-guerreiro/feature/test-drive-admin-modal
2 parents e0f7cc0 + 3856251 commit 6ba2ed4

File tree

15 files changed

+150
-10
lines changed

15 files changed

+150
-10
lines changed

assets/images/fast-track-cover.jpg

157 KB
Loading

src/CONST.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5160,6 +5160,7 @@ const CONST = {
51605160
VIDEO_URL: `${CLOUDFRONT_URL}/videos/guided-setup-track-business-v2.mp4`,
51615161
LEARN_MORE_LINK: `${USE_EXPENSIFY_URL}/track-expenses`,
51625162
},
5163+
TEST_DRIVE_COVER_ASPECT_RATIO: 500 / 300,
51635164
},
51645165

51655166
/**

src/NAVIGATORS.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export default {
1111
WELCOME_VIDEO_MODAL_NAVIGATOR: 'WelcomeVideoModalNavigator',
1212
EXPLANATION_MODAL_NAVIGATOR: 'ExplanationModalNavigator',
1313
MIGRATED_USER_MODAL_NAVIGATOR: 'MigratedUserModalNavigator',
14+
TEST_DRIVE_MODAL_NAVIGATOR: 'TestDriveModalNavigator',
1415
REPORTS_SPLIT_NAVIGATOR: 'ReportsSplitNavigator',
1516
SETTINGS_SPLIT_NAVIGATOR: 'SettingsSplitNavigator',
1617
WORKSPACE_SPLIT_NAVIGATOR: 'WorkspaceSplitNavigator',

src/ROUTES.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,6 +1893,7 @@ const ROUTES = {
18931893
},
18941894
WELCOME_VIDEO_ROOT: 'onboarding/welcome-video',
18951895
EXPLANATION_MODAL_ROOT: 'onboarding/explanation',
1896+
TEST_DRIVE_MODAL_ROOT: 'onboarding/test-drive',
18961897
WORKSPACE_CONFIRMATION: {
18971898
route: 'workspace/confirmation',
18981899
getRoute: (backTo?: string) => getUrlWithBackToParam(`workspace/confirmation`, backTo),

src/SCREENS.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,10 @@ const SCREENS = {
658658
ROOT: 'MigratedUserWelcomeModal_Root',
659659
},
660660

661+
TEST_DRIVE_MODAL: {
662+
ROOT: 'TestDrive_Modal_Root',
663+
},
664+
661665
I_KNOW_A_TEACHER: 'I_Know_A_Teacher',
662666
INTRO_SCHOOL_PRINCIPAL: 'Intro_School_Principal',
663667
I_AM_A_TEACHER: 'I_Am_A_Teacher',

src/components/FeatureTrainingModal.tsx

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import type {VideoReadyForDisplayEvent} from 'expo-av';
22
import type {ImageContentFit} from 'expo-image';
33
import React, {useCallback, useEffect, useLayoutEffect, useState} from 'react';
4-
import {InteractionManager, View} from 'react-native';
5-
import type {StyleProp, ViewStyle} from 'react-native';
4+
import {Image, InteractionManager, View} from 'react-native';
5+
import type {ImageResizeMode, ImageSourcePropType, StyleProp, ViewStyle} from 'react-native';
66
import {GestureHandlerRootView} from 'react-native-gesture-handler';
77
import type {MergeExclusive} from 'type-fest';
88
import useLocalize from '@hooks/useLocalize';
@@ -96,6 +96,9 @@ type BaseFeatureTrainingModalProps = {
9696

9797
/** Whether to disable the modal */
9898
isModalDisabled?: boolean;
99+
100+
/** Whether the modal image is a SVG */
101+
shouldRenderSVG?: boolean;
99102
};
100103

101104
type FeatureTrainingModalVideoProps = {
@@ -152,6 +155,7 @@ function FeatureTrainingModal({
152155
imageWidth,
153156
imageHeight,
154157
isModalDisabled = true,
158+
shouldRenderSVG = true,
155159
}: FeatureTrainingModalProps) {
156160
const styles = useThemeStyles();
157161
const StyleUtils = useStyleUtils();
@@ -215,13 +219,19 @@ function FeatureTrainingModal({
215219
(!!videoURL || !!image) && {aspectRatio},
216220
]}
217221
>
218-
{!!image && (
222+
{!!image && shouldRenderSVG ? (
219223
<ImageSVG
220224
src={image}
221225
contentFit={contentFitImage}
222226
width={imageWidth}
223227
height={imageHeight}
224228
/>
229+
) : (
230+
<Image
231+
source={image as ImageSourcePropType}
232+
resizeMode={contentFitImage as ImageResizeMode}
233+
style={styles.featureTrainingModalImage}
234+
/>
225235
)}
226236
{!!videoURL && videoStatus === 'video' && (
227237
<GestureHandlerRootView>
@@ -250,23 +260,25 @@ function FeatureTrainingModal({
250260
</View>
251261
);
252262
}, [
253-
image,
254-
imageHeight,
255-
imageWidth,
256-
contentFitImage,
257263
illustrationAspectRatio,
258264
styles.w100,
265+
styles.featureTrainingModalImage,
259266
styles.onboardingVideoPlayer,
260267
styles.flex1,
261268
styles.alignItemsCenter,
262269
styles.justifyContentCenter,
263270
styles.h100,
264-
videoStatus,
271+
illustrationInnerContainerStyle,
265272
videoURL,
273+
image,
274+
shouldRenderSVG,
275+
contentFitImage,
276+
imageWidth,
277+
imageHeight,
278+
videoStatus,
266279
animationStyle,
267280
animation,
268281
shouldUseNarrowLayout,
269-
illustrationInnerContainerStyle,
270282
]);
271283

272284
const toggleWillShowAgain = useCallback(() => setWillShowAgain((prevWillShowAgain) => !prevWillShowAgain), []);

src/components/TestDriveModal.tsx

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React from 'react';
2+
import FastTrack from '@assets/images/fast-track-cover.jpg';
3+
import useLocalize from '@hooks/useLocalize';
4+
import useThemeStyles from '@hooks/useThemeStyles';
5+
import Navigation from '@libs/Navigation/Navigation';
6+
import CONST from '@src/CONST';
7+
import FeatureTrainingModal from './FeatureTrainingModal';
8+
9+
function TestDriveModal() {
10+
const styles = useThemeStyles();
11+
const {translate} = useLocalize();
12+
13+
const closeModal = () => {
14+
Navigation.dismissModal();
15+
};
16+
17+
const navigateTestDriveDemo = () => {};
18+
19+
return (
20+
<FeatureTrainingModal
21+
image={FastTrack}
22+
illustrationOuterContainerStyle={styles.p0}
23+
illustrationAspectRatio={CONST.FEATURE_TRAINING.TEST_DRIVE_COVER_ASPECT_RATIO}
24+
title={translate('testDrive.modal.title')}
25+
description={translate('testDrive.modal.description')}
26+
helpText={translate('testDrive.modal.helpText')}
27+
confirmText={translate('testDrive.modal.confirmText')}
28+
onHelp={closeModal}
29+
onConfirm={navigateTestDriveDemo}
30+
shouldRenderSVG={false}
31+
modalInnerContainerStyle={styles.testDriveModalContainer}
32+
/>
33+
);
34+
}
35+
36+
TestDriveModal.displayName = 'TestDriveModal';
37+
38+
export default TestDriveModal;

src/languages/en.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6227,6 +6227,14 @@ const translations = {
62276227
talkToConcierge: 'Talk to Concierge',
62286228
hangUp: 'Hang up',
62296229
},
6230+
testDrive: {
6231+
modal: {
6232+
title: 'Take us for a test drive',
6233+
description: 'Take a quick product tour to get up to speed fast. No pit stops required!',
6234+
confirmText: 'Start test drive',
6235+
helpText: 'Skip',
6236+
},
6237+
},
62306238
};
62316239

62326240
export default translations satisfies TranslationDeepObject<typeof translations>;

src/languages/es.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6749,6 +6749,14 @@ const translations = {
67496749
talkToConcierge: 'Habla con Concierge',
67506750
hangUp: 'Colgar',
67516751
},
6752+
testDrive: {
6753+
modal: {
6754+
title: 'Haz una prueba con nosotros',
6755+
description: 'Haz un recorrido rápido por el producto para ponerte al día rápidamente. ¡No se requieren paradas!',
6756+
confirmText: 'Iniciar prueba',
6757+
helpText: 'Omitir',
6758+
},
6759+
},
67526760
};
67536761

67546762
export default translations satisfies TranslationDeepObject<typeof en>;

src/libs/Navigation/AppNavigator/AuthScreens.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import LeftModalNavigator from './Navigators/LeftModalNavigator';
6969
import MigratedUserWelcomeModalNavigator from './Navigators/MigratedUserWelcomeModalNavigator';
7070
import OnboardingModalNavigator from './Navigators/OnboardingModalNavigator';
7171
import RightModalNavigator from './Navigators/RightModalNavigator';
72+
import TestDriveModalNavigator from './Navigators/TestDriveModalNavigator';
7273
import WelcomeVideoModalNavigator from './Navigators/WelcomeVideoModalNavigator';
7374
import useRootNavigatorScreenOptions from './useRootNavigatorScreenOptions';
7475

@@ -224,7 +225,9 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
224225
const currentUrl = getCurrentUrl();
225226
const delegatorEmail = getSearchParamFromUrl(currentUrl, 'delegatorEmail');
226227

227-
const [account] = useOnyx(ONYXKEYS.ACCOUNT);
228+
const [account] = useOnyx(ONYXKEYS.ACCOUNT, {
229+
canBeMissing: true,
230+
});
228231
const modal = useRef<OnyxTypes.Modal>({});
229232
const {isOnboardingCompleted} = useOnboardingFlowRouter();
230233
const [shouldShowRequire2FAPage, setShouldShowRequire2FAPage] = useState(!!account?.needsTwoFactorAuthSetup && !account.requiresTwoFactorAuth);
@@ -628,6 +631,11 @@ function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDApplie
628631
options={rootNavigatorScreenOptions.basicModalNavigator}
629632
component={MigratedUserWelcomeModalNavigator}
630633
/>
634+
<RootStack.Screen
635+
name={NAVIGATORS.TEST_DRIVE_MODAL_NAVIGATOR}
636+
options={rootNavigatorScreenOptions.basicModalNavigator}
637+
component={TestDriveModalNavigator}
638+
/>
631639
<RootStack.Screen
632640
name={NAVIGATORS.FEATURE_TRANING_MODAL_NAVIGATOR}
633641
options={rootNavigatorScreenOptions.basicModalNavigator}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react';
2+
import {View} from 'react-native';
3+
import NoDropZone from '@components/DragAndDrop/NoDropZone';
4+
import TestDriveModal from '@components/TestDriveModal';
5+
import createPlatformStackNavigator from '@libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator';
6+
import Animations from '@libs/Navigation/PlatformStackNavigation/navigationOptions/animation';
7+
import type {TestDriveModalNavigatorParamList} from '@libs/Navigation/types';
8+
import SCREENS from '@src/SCREENS';
9+
10+
const Stack = createPlatformStackNavigator<TestDriveModalNavigatorParamList>();
11+
12+
function TestDriveModalNavigator() {
13+
return (
14+
<NoDropZone>
15+
<View>
16+
<Stack.Navigator screenOptions={{headerShown: false, animation: Animations.SLIDE_FROM_RIGHT}}>
17+
<Stack.Screen
18+
name={SCREENS.TEST_DRIVE_MODAL.ROOT}
19+
component={TestDriveModal}
20+
/>
21+
</Stack.Navigator>
22+
</View>
23+
</NoDropZone>
24+
);
25+
}
26+
27+
TestDriveModalNavigator.displayName = 'TestDriveModalNavigator';
28+
29+
export default TestDriveModalNavigator;

src/libs/Navigation/AppNavigator/createRootStackNavigator/GetStateForActionHandlers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const MODAL_ROUTES_TO_DISMISS: string[] = [
1919
NAVIGATORS.ONBOARDING_MODAL_NAVIGATOR,
2020
NAVIGATORS.FEATURE_TRANING_MODAL_NAVIGATOR,
2121
NAVIGATORS.SHARE_MODAL_NAVIGATOR,
22+
NAVIGATORS.TEST_DRIVE_MODAL_NAVIGATOR,
2223
SCREENS.NOT_FOUND,
2324
SCREENS.ATTACHMENTS,
2425
SCREENS.TRANSACTION_RECEIPT,

src/libs/Navigation/linkingConfig/config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
8383
},
8484
},
8585

86+
[NAVIGATORS.TEST_DRIVE_MODAL_NAVIGATOR]: {
87+
screens: {
88+
[SCREENS.TEST_DRIVE_MODAL.ROOT]: {
89+
path: ROUTES.TEST_DRIVE_MODAL_ROOT,
90+
exact: true,
91+
},
92+
},
93+
},
94+
8695
[NAVIGATORS.ONBOARDING_MODAL_NAVIGATOR]: {
8796
// Don't set the initialRouteName, because when the user continues from the last visited onboarding page,
8897
// the onboarding purpose page will be briefly visible.

src/libs/Navigation/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,6 +1778,10 @@ type MigratedUserModalNavigatorParamList = {
17781778
[SCREENS.MIGRATED_USER_WELCOME_MODAL.ROOT]: undefined;
17791779
};
17801780

1781+
type TestDriveModalNavigatorParamList = {
1782+
[SCREENS.TEST_DRIVE_MODAL.ROOT]: undefined;
1783+
};
1784+
17811785
type SharedScreensParamList = {
17821786
[NAVIGATORS.REPORTS_SPLIT_NAVIGATOR]: NavigatorScreenParams<ReportsSplitNavigatorParamList>;
17831787
[SCREENS.TRANSITION_BETWEEN_APPS]: {
@@ -1859,6 +1863,7 @@ type AuthScreensParamList = SharedScreensParamList & {
18591863
[NAVIGATORS.WELCOME_VIDEO_MODAL_NAVIGATOR]: NavigatorScreenParams<WelcomeVideoModalNavigatorParamList>;
18601864
[NAVIGATORS.EXPLANATION_MODAL_NAVIGATOR]: NavigatorScreenParams<ExplanationModalNavigatorParamList>;
18611865
[NAVIGATORS.MIGRATED_USER_MODAL_NAVIGATOR]: NavigatorScreenParams<MigratedUserModalNavigatorParamList>;
1866+
[NAVIGATORS.TEST_DRIVE_MODAL_NAVIGATOR]: NavigatorScreenParams<TestDriveModalNavigatorParamList>;
18621867
[NAVIGATORS.SEARCH_FULLSCREEN_NAVIGATOR]: NavigatorScreenParams<SearchFullscreenNavigatorParamList>;
18631868
[SCREENS.DESKTOP_SIGN_IN_REDIRECT]: undefined;
18641869
[SCREENS.TRANSACTION_RECEIPT]: {
@@ -2054,6 +2059,7 @@ export type {
20542059
WorkspaceConfirmationNavigatorParamList,
20552060
TwoFactorAuthNavigatorParamList,
20562061
ConsoleNavigatorParamList,
2062+
TestDriveModalNavigatorParamList,
20572063
WorkspaceScreenName,
20582064
SettingsTabScreenName,
20592065
};

src/styles/index.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5655,6 +5655,20 @@ const styles = (theme: ThemeColors) =>
56555655
left: 0,
56565656
right: 0,
56575657
},
5658+
5659+
testDriveModalContainer: {
5660+
// On small/medium screens, we need to remove the top padding
5661+
paddingTop: 0,
5662+
// On medium screens, we need to prevent the modal from becoming too big
5663+
maxWidth: 500,
5664+
},
5665+
5666+
featureTrainingModalImage: {
5667+
width: '100%',
5668+
height: '100%',
5669+
borderTopLeftRadius: variables.componentBorderRadiusLarge,
5670+
borderTopRightRadius: variables.componentBorderRadiusLarge,
5671+
},
56585672
} satisfies Styles);
56595673

56605674
type ThemeStyles = ReturnType<typeof styles>;

0 commit comments

Comments
 (0)