-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Add full screen engagement modal to NewDot #32154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
71aaa5a
38f9c59
d387417
94aa8f8
01629a2
96dc71e
2e6ab73
39b3593
2c21559
cc9aead
7f32222
1d2ff01
5fb78b8
877efb9
5f921af
cfad7cc
0ef6e32
d31d697
6ac457b
91120f9
0def96f
e5ef2b4
9e49cee
73fb919
01ce5e3
e8296c4
60c13dc
6855f21
bb36f6e
f7dcb5e
9abcb6d
dabb866
a1e53cc
0a81573
0773d9e
e52c81e
08e8843
14f532a
4d70303
c68d728
17dbbe6
7b31ef9
356db31
2ba2966
1f3420c
874543f
728e215
30ea7b5
ca904e0
489b148
4de8c5b
d6d06ce
cf1a9ec
82b26ad
30f88f8
4e0eb0d
37e1e78
fdf8429
23b3f89
6176876
9adf07d
daf05b6
998c2e9
8f15ee3
eb0d5cc
3ca872a
5bdc2c6
cf23709
4df4d3a
8ac48cb
6cc3f5c
aa6398a
37ff12a
c0a737b
cbd3db5
69ccc51
a02c8ae
a248b46
6d260df
1569ef6
d571914
50ce52a
f216232
6f8ccf0
bca21af
0055dee
8c59d64
6ca99b0
58a4e52
4e9d290
b41489d
fe2625e
189bae9
9e86e8e
7edb569
9ec0c2a
0b6bf56
eda0fe7
47c32f4
82b5552
a526027
cf5f181
2502778
49b6915
9bd6e2e
5fa2403
a313c40
da884be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| import {useNavigation} from '@react-navigation/native'; | ||
| import React, {useCallback, useEffect, useMemo, useState} from 'react'; | ||
| import {ScrollView, View} from 'react-native'; | ||
| import type {ValueOf} from 'type-fest'; | ||
| import useLocalize from '@hooks/useLocalize'; | ||
| import useStyleUtils from '@hooks/useStyleUtils'; | ||
| import useTheme from '@hooks/useTheme'; | ||
| import useThemeStyles from '@hooks/useThemeStyles'; | ||
| import useWindowDimensions from '@hooks/useWindowDimensions'; | ||
| import * as Report from '@userActions/Report'; | ||
| import * as Welcome from '@userActions/Welcome'; | ||
| import CONST from '@src/CONST'; | ||
| import NAVIGATORS from '@src/NAVIGATORS'; | ||
| import SCREENS from '@src/SCREENS'; | ||
| import HeaderWithBackButton from './HeaderWithBackButton'; | ||
| import * as Expensicons from './Icon/Expensicons'; | ||
| import Lottie from './Lottie'; | ||
| import LottieAnimations from './LottieAnimations'; | ||
| import type {MenuItemProps} from './MenuItem'; | ||
| import MenuItemList from './MenuItemList'; | ||
| import Modal from './Modal'; | ||
| import Text from './Text'; | ||
|
|
||
| // This is not translated because it is a message coming from concierge, which only supports english | ||
| const messageCopy = { | ||
| [CONST.INTRO_CHOICES.TRACK]: | ||
| 'Great! To track your expenses, I suggest you create a workspace to keep everything contained:\n' + | ||
| '\n' + | ||
| '1. Press your avatar icon\n' + | ||
| '2. Choose Workspaces\n' + | ||
| '3. Choose New Workspace\n' + | ||
| '4. Name your workspace something meaningful (eg, "My Business Expenses")\n' + | ||
| '\n' + | ||
| 'Once you have your workspace set up, you can add expenses to it as follows:\n' + | ||
| '\n' + | ||
| '1. Choose My Business Expenses (or whatever you named it) in the list of chat rooms\n' + | ||
| '2. Choose the + button in the chat compose window\n' + | ||
| '3. Choose Request money\n' + | ||
| "4. Choose what kind of expense you'd like to log, whether a manual expense, scanned receipt, or tracked distance.\n" + | ||
| '\n' + | ||
| "That'll be stored in your My Business Expenses room for your later access. Thanks for asking, and let me know how it goes!", | ||
| [CONST.INTRO_CHOICES.SUBMIT]: | ||
| 'Hi there, to submit expenses for reimbursement, please:\n' + | ||
| '\n' + | ||
| '1. Press the big green + button\n' + | ||
| '2. Choose Request money\n' + | ||
| '3. Indicate how much to request, either manually, by scanning a receipt, or by tracking distance\n' + | ||
| '4. Enter the email address or phone number of your boss\n' + | ||
| '\n' + | ||
| "And we'll take it from there to get you paid back. Please give it a shot and let me know how it goes!", | ||
| [CONST.INTRO_CHOICES.MANAGE_TEAM]: | ||
| "Great! To manage your team's expenses, create a workspace to keep everything contained:\n" + | ||
| '\n' + | ||
| '1. Press your avatar icon\n' + | ||
| '2. Choose Workspaces\n' + | ||
| '3. Choose New Workspace\n' + | ||
| '4. Name your workspace something meaningful (eg, "Galaxy Food Inc.")\n' + | ||
| '\n' + | ||
| 'Once you have your workspace set up, you can invite your team to it via the Members pane and connect a business bank account to reimburse them!', | ||
| [CONST.INTRO_CHOICES.CHAT_SPLIT]: | ||
| 'Hi there, to split an expense such as with a friend, please:\n' + | ||
| '\n' + | ||
| 'Press the big green + button\n' + | ||
| 'Choose *Request money*\n' + | ||
| 'Indicate how much was spent, either manually, by scanning a receipt, or by tracking distance\n' + | ||
| 'Enter the email address or phone number of your friend\n' + | ||
| 'Press *Split* next to their name\n' + | ||
| 'Repeat as many times as you like for each of your friends\n' + | ||
| 'Press *Add to split* when done adding friends\n' + | ||
| 'Press Split to split the bill\n' + | ||
| '\n' + | ||
| "This will send a money request to each of your friends for however much they owe you, and we'll take care of getting you paid back. Thanks for asking, and let me know how it goes!", | ||
| }; | ||
|
|
||
| const menuIcons = { | ||
| [CONST.INTRO_CHOICES.TRACK]: Expensicons.ReceiptSearch, | ||
| [CONST.INTRO_CHOICES.SUBMIT]: Expensicons.Scan, | ||
| [CONST.INTRO_CHOICES.MANAGE_TEAM]: Expensicons.MoneyBag, | ||
| [CONST.INTRO_CHOICES.CHAT_SPLIT]: Expensicons.Briefcase, | ||
| }; | ||
|
|
||
| function PurposeForUsingExpensifyModal() { | ||
| const {translate} = useLocalize(); | ||
| const StyleUtils = useStyleUtils(); | ||
| const styles = useThemeStyles(); | ||
| const {isSmallScreenWidth, windowHeight} = useWindowDimensions(); | ||
| const navigation = useNavigation(); | ||
| const [isModalOpen, setIsModalOpen] = useState(false); | ||
| const theme = useTheme(); | ||
|
|
||
| useEffect(() => { | ||
| const navigationState = navigation.getState(); | ||
| const routes = navigationState.routes; | ||
| const currentRoute = routes[navigationState.index]; | ||
| if (currentRoute && NAVIGATORS.CENTRAL_PANE_NAVIGATOR !== currentRoute.name && currentRoute.name !== SCREENS.HOME) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please add context behind this logic?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there is a route, we don't want to show the modal unless the page we're on is home or the central pane navigator
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok so #32154 (review) is correct. Just wanted to confirm 🙂
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep that's correct! Thanks for double checking :) |
||
| return; | ||
| } | ||
|
|
||
| Welcome.show(routes, () => setIsModalOpen(true)); | ||
| // eslint-disable-next-line react-hooks/exhaustive-deps | ||
| }, []); | ||
|
|
||
| const closeModal = useCallback(() => { | ||
| Report.dismissEngagementModal(); | ||
| setIsModalOpen(false); | ||
| }, []); | ||
|
|
||
| const completeModalAndClose = useCallback((message: string, choice: ValueOf<typeof CONST.INTRO_CHOICES>) => { | ||
| Report.completeEngagementModal(message, choice); | ||
| setIsModalOpen(false); | ||
| Report.navigateToConciergeChat(); | ||
| }, []); | ||
|
|
||
| const menuItems: MenuItemProps[] = useMemo( | ||
| () => | ||
| Object.values(CONST.INTRO_CHOICES).map((choice) => { | ||
| const translationKey = `purposeForExpensify.${choice}` as const; | ||
| return { | ||
| key: translationKey, | ||
| title: translate(translationKey), | ||
| icon: menuIcons[choice], | ||
| iconRight: Expensicons.ArrowRight, | ||
| onPress: () => completeModalAndClose(messageCopy[choice], choice), | ||
| shouldShowRightIcon: true, | ||
| numberOfLinesTitle: 2, | ||
| }; | ||
| }), | ||
| [completeModalAndClose, translate], | ||
| ); | ||
|
|
||
| return ( | ||
| <Modal | ||
| type={isSmallScreenWidth ? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : CONST.MODAL.MODAL_TYPE.RIGHT_DOCKED} | ||
| isVisible={isModalOpen} | ||
| onClose={closeModal} | ||
| innerContainerStyle={styles.pt0} | ||
| shouldUseCustomBackdrop | ||
| > | ||
| <View style={{maxHeight: windowHeight}}> | ||
| <ScrollView> | ||
| <View style={StyleUtils.getBackgroundColorStyle(theme.PAGE_THEMES[SCREENS.SETTINGS.WORKSPACES].backgroundColor)}> | ||
| <Lottie | ||
| source={LottieAnimations.Hands} | ||
| style={styles.w100} | ||
| webStyle={styles.w100} | ||
| autoPlay | ||
| loop | ||
| /> | ||
| <HeaderWithBackButton | ||
| shouldShowCloseButton | ||
| shouldShowBackButton={false} | ||
| onCloseButtonPress={closeModal} | ||
| shouldOverlay | ||
| iconFill={theme.iconColorfulBackground} | ||
| /> | ||
| </View> | ||
| <View style={[styles.w100, styles.ph5, styles.pv5]}> | ||
| <Text | ||
| style={[styles.textHeadline, styles.preWrap, styles.mb2]} | ||
| numberOfLines={2} | ||
| > | ||
| {translate('purposeForExpensify.welcomeMessage')} | ||
| </Text> | ||
| <Text>{translate('purposeForExpensify.welcomeSubtitle')}</Text> | ||
| </View> | ||
| <MenuItemList | ||
| menuItems={menuItems} | ||
| shouldUseSingleExecution | ||
stitesExpensify marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /> | ||
| </ScrollView> | ||
| </View> | ||
| </Modal> | ||
| ); | ||
| } | ||
|
|
||
| PurposeForUsingExpensifyModal.displayName = 'PurposeForUsingExpensifyModal'; | ||
|
|
||
| export default PurposeForUsingExpensifyModal; | ||
Uh oh!
There was an error while loading. Please reload this page.