From effa4616e4b3eafbb5be3f509d4ebc573d13678f Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Fri, 18 Apr 2025 21:28:09 +0200 Subject: [PATCH 01/23] Update onboarding page with new integration choices --- src/CONST.ts | 4 +++ src/languages/en.ts | 12 +++++++ .../Navigators/OnboardingModalNavigator.tsx | 6 +++- .../BaseOnboardingAccounting.tsx | 34 +++++++++++++++++++ src/styles/index.ts | 4 +-- src/styles/variables.ts | 1 + 6 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 14adbe9e7b7d..85743f1b12d2 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2938,6 +2938,10 @@ const CONST = { XERO: 'xero', NETSUITE: 'netsuite', SAGE_INTACCT: 'intacct', + SAP: 'sap', + ORACLE: 'oracle', + MS_DYNAMICS: 'msDynamics', + OTHER: 'other', }, ROUTE: { QBO: 'quickbooks-online', diff --git a/src/languages/en.ts b/src/languages/en.ts index 477ff0201c46..a9e34005cf33 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -4296,6 +4296,10 @@ const translations = { xero: 'Xero', netsuite: 'NetSuite', intacct: 'Sage Intacct', + sap: 'SAP', + oracle: 'Oracle', + msDynamics: 'Microsoft Dynamics', + other: 'Other', talkYourOnboardingSpecialist: 'Chat with your setup specialist.', talkYourAccountManager: 'Chat with your account manager.', talkToConcierge: 'Chat with Concierge.', @@ -4310,6 +4314,14 @@ const translations = { return 'NetSuite'; case CONST.POLICY.CONNECTIONS.NAME.SAGE_INTACCT: return 'Sage Intacct'; + case CONST.POLICY.CONNECTIONS.NAME.SAP: + return 'SAP'; + case CONST.POLICY.CONNECTIONS.NAME.ORACLE: + return 'Oracle'; + case CONST.POLICY.CONNECTIONS.NAME.MS_DYNAMICS: + return 'Microsoft Dynamics'; + case CONST.POLICY.CONNECTIONS.NAME.OTHER: + return 'Other'; default: { return ''; } diff --git a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx index 6fc61e5a7efd..a1ec9bd95b3e 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx @@ -1,3 +1,4 @@ +import {useNavigationState} from '@react-navigation/native'; import {CardStyleInterpolators} from '@react-navigation/stack'; import React, {useCallback, useEffect} from 'react'; import {View} from 'react-native'; @@ -40,6 +41,9 @@ function OnboardingModalNavigator() { const outerViewRef = React.useRef(null); const [accountID] = useOnyx(ONYXKEYS.SESSION, {selector: (session) => session?.accountID ?? CONST.DEFAULT_NUMBER_ID, canBeMissing: true}); + const currentRoute = useNavigationState((state) => state.routes[state.index]); + const lastRouteName = currentRoute?.state?.routes?.[currentRoute?.state?.routes?.length - 1]?.name; + // Publish a sign_up event when we start the onboarding flow. This should track basic sign ups // as well as Google and Apple SSO. useEffect(() => { @@ -67,7 +71,7 @@ function OnboardingModalNavigator() { e.stopPropagation()} - style={styles.OnboardingNavigatorInnerView(onboardingIsMediumOrLargerScreenWidth)} + style={styles.OnboardingNavigatorInnerView(onboardingIsMediumOrLargerScreenWidth, lastRouteName === SCREENS.ONBOARDING.ACCOUNTING)} > alignItems: 'center', }, - OnboardingNavigatorInnerView: (shouldUseNarrowLayout: boolean) => + OnboardingNavigatorInnerView: (shouldUseNarrowLayout: boolean, isAccountingStep: boolean) => ({ - width: shouldUseNarrowLayout ? variables.onboardingModalWidth : '100%', + width: shouldUseNarrowLayout ? (isAccountingStep ? variables.onboardingAccountingModalWidth : variables.onboardingModalWidth) : '100%', height: shouldUseNarrowLayout ? 732 : '100%', maxHeight: '100%', borderRadius: shouldUseNarrowLayout ? 16 : 0, diff --git a/src/styles/variables.ts b/src/styles/variables.ts index e7728ead0670..00a38659b682 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -218,6 +218,7 @@ export default { restrictedActionIllustrationHeight: 136, photoUploadPopoverWidth: 335, onboardingModalWidth: 500, + onboardingAccountingModalWidth: 800, holdEducationModalWidth: 400, changePolicyEducationModalWidth: 400, changePolicyEducationModalIconWidth: 147.69, From 8b2d0ae23dff1d5952d240bcf2829da681483995 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Sat, 19 Apr 2025 02:57:46 +0200 Subject: [PATCH 02/23] Refactoring --- src/CONST.ts | 2 +- src/languages/en.ts | 2 +- src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index ec30086cec81..6d338b6a7c99 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2941,7 +2941,7 @@ const CONST = { SAGE_INTACCT: 'intacct', SAP: 'sap', ORACLE: 'oracle', - MS_DYNAMICS: 'msDynamics', + MICROSOFT_DYNAMICS: 'Microsoft Dynamics', OTHER: 'other', }, ROUTE: { diff --git a/src/languages/en.ts b/src/languages/en.ts index c855c8d8da66..a5c3a24ff529 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -4318,7 +4318,7 @@ const translations = { return 'SAP'; case CONST.POLICY.CONNECTIONS.NAME.ORACLE: return 'Oracle'; - case CONST.POLICY.CONNECTIONS.NAME.MS_DYNAMICS: + case CONST.POLICY.CONNECTIONS.NAME.MICROSOFT_DYNAMICS: return 'Microsoft Dynamics'; case CONST.POLICY.CONNECTIONS.NAME.OTHER: return 'Other'; diff --git a/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx b/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx index c6871a99a442..df67a299ead5 100644 --- a/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx +++ b/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx @@ -129,8 +129,8 @@ function BaseOnboardingAccounting({shouldUseNativeStyles}: BaseOnboardingAccount accountingIcon = Expensicons.IntacctSquare; break; } - case CONST.POLICY.CONNECTIONS.NAME.MS_DYNAMICS: { - text = translate('workspace.accounting.msDynamics'); + case CONST.POLICY.CONNECTIONS.NAME.MICROSOFT_DYNAMICS: { + text = translate('workspace.accounting.microsoftDynamics'); accountingIcon = Expensicons.IntacctSquare; break; } From 90ddceaf9ca6f278d1edeeec28a3a492f9e5c981 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Sat, 19 Apr 2025 03:00:34 +0200 Subject: [PATCH 03/23] refactoring --- src/languages/en.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index a5c3a24ff529..7965111c4ce5 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -4298,7 +4298,7 @@ const translations = { intacct: 'Sage Intacct', sap: 'SAP', oracle: 'Oracle', - msDynamics: 'Microsoft Dynamics', + microsoftDynamics: 'Microsoft Dynamics', other: 'Other', talkYourOnboardingSpecialist: 'Chat with your setup specialist.', talkYourAccountManager: 'Chat with your account manager.', From aa912f5a2834d78888b58494deddde1b3387d484 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Sun, 27 Apr 2025 23:41:21 +0200 Subject: [PATCH 04/23] Changing SelectionList to FlatList inside the BaseOnboardingAccounting --- src/components/RadioButtonWithLabel.tsx | 61 +++-- .../Navigators/OnboardingModalNavigator.tsx | 6 +- .../BaseOnboardingAccounting.tsx | 238 ++++++++++-------- src/styles/index.ts | 12 +- src/styles/variables.ts | 2 +- 5 files changed, 188 insertions(+), 131 deletions(-) diff --git a/src/components/RadioButtonWithLabel.tsx b/src/components/RadioButtonWithLabel.tsx index 43f44065f5d9..84db5d01b22d 100644 --- a/src/components/RadioButtonWithLabel.tsx +++ b/src/components/RadioButtonWithLabel.tsx @@ -29,39 +29,60 @@ type RadioButtonWithLabelProps = { /** Error text to display */ errorText?: string; + + /** If true, radio button is rendered **after** the label (right-hand side). */ + radioOnRight?: boolean; }; const PressableWithFeedback = Pressables.PressableWithFeedback; -function RadioButtonWithLabel({LabelComponent, style, label = '', hasError = false, errorText = '', isChecked, onPress}: RadioButtonWithLabelProps) { +function RadioButtonWithLabel({LabelComponent, style, label = '', hasError = false, errorText = '', isChecked, onPress, radioOnRight = false}: RadioButtonWithLabelProps) { const styles = useThemeStyles(); const defaultStyles = [styles.flexRow, styles.alignItemsCenter]; if (!label && !LabelComponent) { throw new Error('Must provide at least label or LabelComponent prop'); } + + const LabelPressable = ( + + {!!label && {label}} + {!!LabelComponent && } + + ); + + const Radio = ( + + ); + return ( <> - - - {!!label && {label}} - {!!LabelComponent && } - + {radioOnRight ? ( + <> + {LabelPressable} + {Radio} + + ) : ( + <> + {Radio} + {LabelPressable} + + )} diff --git a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx index f2a59ad2d272..e4a9925a51f9 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx +++ b/src/libs/Navigation/AppNavigator/Navigators/OnboardingModalNavigator.tsx @@ -1,4 +1,3 @@ -import {useNavigationState} from '@react-navigation/native'; import {CardStyleInterpolators} from '@react-navigation/stack'; import React, {useCallback, useEffect} from 'react'; import {View} from 'react-native'; @@ -48,9 +47,6 @@ function OnboardingModalNavigator() { canBeMissing: false, }); - const currentRoute = useNavigationState((state) => state.routes[state.index]); - const lastRouteName = currentRoute?.state?.routes?.[currentRoute?.state?.routes?.length - 1]?.name; - // Publish a sign_up event when we start the onboarding flow. This should track basic sign ups // as well as Google and Apple SSO. useEffect(() => { @@ -78,7 +74,7 @@ function OnboardingModalNavigator() { e.stopPropagation()} - style={styles.OnboardingNavigatorInnerView(onboardingIsMediumOrLargerScreenWidth, lastRouteName === SCREENS.ONBOARDING.ACCOUNTING)} + style={styles.OnboardingNavigatorInnerView(onboardingIsMediumOrLargerScreenWidth)} > {/* The OnboardingPurpose screen is shown after the workspace step when the user is on a private domain and has accessible policies. diff --git a/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx b/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx index be670b21f99e..de2de2216e26 100644 --- a/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx +++ b/src/pages/OnboardingAccounting/BaseOnboardingAccounting.tsx @@ -1,17 +1,19 @@ import HybridAppModule from '@expensify/react-native-hybrid-app'; -import React, {useContext, useEffect, useMemo, useState} from 'react'; -import {InteractionManager} from 'react-native'; +import React, {useCallback, useContext, useEffect, useMemo, useState} from 'react'; +import {InteractionManager, View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import Button from '@components/Button'; import CustomStatusBarAndBackgroundContext from '@components/CustomStatusBarAndBackground/CustomStatusBarAndBackgroundContext'; +import FixedFooter from '@components/FixedFooter'; +import FlatList from '@components/FlatList'; import FormHelpMessage from '@components/FormHelpMessage'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; +import OfflineIndicator from '@components/OfflineIndicator'; +import RadioButtonWithLabel from '@components/RadioButtonWithLabel'; import ScreenWrapper from '@components/ScreenWrapper'; -import SelectionList from '@components/SelectionList'; -import RadioListItem from '@components/SelectionList/RadioListItem'; -import type {ListItem} from '@components/SelectionList/types'; +import {ListItem} from '@components/SelectionList/types'; import Text from '@components/Text'; import useActiveWorkspace from '@hooks/useActiveWorkspace'; import useLocalize from '@hooks/useLocalize'; @@ -32,10 +34,9 @@ import Navigation from '@libs/Navigation/Navigation'; import {isPaidGroupPolicy, isPolicyAdmin} from '@libs/PolicyUtils'; import variables from '@styles/variables'; import CONFIG from '@src/CONFIG'; -import CONST from '@src/CONST'; import type {OnboardingAccounting} from '@src/CONST'; +import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {} from '@src/types/onyx/Bank'; import type {BaseOnboardingAccountingProps} from './types'; type OnboardingListItem = ListItem & { @@ -175,124 +176,155 @@ function BaseOnboardingAccounting({shouldUseNativeStyles}: BaseOnboardingAccount return [...policyAccountingOptions, noneAccountingOption]; }, [StyleUtils, styles.mr3, styles.onboardingSmallIcon, theme.success, translate, userReportedIntegration]); - const footerContent = ( - <> - {!!error && ( - ( + + { + setUserReportedIntegration(item.keyForList); + setError(''); + }} + radioOnRight + LabelComponent={() => ( + + {item.leftElement} + {item.text} + + )} /> - )} -