diff --git a/src/components/ConfirmationPage.tsx b/src/components/ConfirmationPage.tsx deleted file mode 100644 index 204fbb6f62d6..000000000000 --- a/src/components/ConfirmationPage.tsx +++ /dev/null @@ -1,209 +0,0 @@ -import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; -import useThemeStyles from '@hooks/useThemeStyles'; - -import Accessibility from '@libs/Accessibility'; -import isIllustrationLottieAnimation from '@libs/isIllustrationLottieAnimation'; - -import CONST from '@src/CONST'; -import type IconAsset from '@src/types/utils/IconAsset'; - -import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; - -import React from 'react'; -import {StyleSheet, View} from 'react-native'; - -import type DotLottieAnimation from './LottieAnimations/types'; - -import Button from './Button'; -import FixedFooter from './FixedFooter'; -import ImageSVG from './ImageSVG'; -import Lottie from './Lottie'; -import LottieAnimations from './LottieAnimations'; -import ScrollView from './ScrollView'; -import Text from './Text'; - -type ConfirmationPageProps = { - illustration?: DotLottieAnimation | IconAsset; - heading: string; - description?: React.ReactNode; - descriptionComponent?: React.ReactNode; - - /** The text for the call to action */ - cta?: React.ReactNode; - - /** Call to action component of the confirmation page */ - ctaComponent?: React.ReactNode; - - /** The text for the primary button label */ - buttonText?: string; - - /** A function that is called when the primary button is clicked on */ - onButtonPress?: () => void; - - /** Whether we should show a primary confirmation button */ - shouldShowButton?: boolean; - - /** Whether the primary confirmation button should be disabled */ - isButtonDisabled?: boolean; - - /** Whether the primary confirmation button should show a loading spinner */ - isButtonLoading?: boolean; - - /** The text for the secondary button label */ - secondaryButtonText?: string; - - onSecondaryButtonPress?: () => void; - shouldShowSecondaryButton?: boolean; - - /** Whether the secondary confirmation button should be disabled */ - isSecondaryButtonDisabled?: boolean; - - /** Whether the secondary confirmation button should show a loading spinner */ - isSecondaryButtonLoading?: boolean; - headingStyle?: TextStyle; - - /** Additional style for the animation */ - illustrationStyle?: StyleProp; - - descriptionStyle?: StyleProp; - ctaStyle?: TextStyle; - footerStyle?: ViewStyle; - - /** Component rendered inside the footer, above the buttons (e.g. an inline error message) */ - footerComponent?: React.ReactNode; - - containerStyle?: ViewStyle; - innerContainerStyle?: ViewStyle; -}; - -function ConfirmationPage({ - illustration = LottieAnimations.Fireworks, - heading, - description, - descriptionComponent, - cta, - ctaComponent, - buttonText = '', - onButtonPress = () => {}, - shouldShowButton = false, - isButtonDisabled = false, - isButtonLoading = false, - secondaryButtonText = '', - onSecondaryButtonPress = () => {}, - shouldShowSecondaryButton = false, - isSecondaryButtonDisabled = false, - isSecondaryButtonLoading = false, - headingStyle, - illustrationStyle, - descriptionStyle, - ctaStyle, - footerStyle, - footerComponent, - containerStyle, - innerContainerStyle, -}: ConfirmationPageProps) { - const styles = useThemeStyles(); - const isReduceMotionEnabled = Accessibility.useReducedMotion(); - const illustrations = useMemoizedLazyIllustrations(['Fireworks']); - const isLottie = isIllustrationLottieAnimation(illustration); - const shouldShowStaticFallback = isLottie && isReduceMotionEnabled && illustration === LottieAnimations.Fireworks; - const flattenedIllustrationStyle = StyleSheet.flatten(illustrationStyle); - const flattenedIllustrationWidth = flattenedIllustrationStyle?.width; - const flattenedIllustrationHeight = flattenedIllustrationStyle?.height; - const webIllustrationWidth = - typeof flattenedIllustrationWidth === 'string' || typeof flattenedIllustrationWidth === 'number' ? flattenedIllustrationWidth : styles.confirmationAnimation.width; - const webIllustrationHeight = - typeof flattenedIllustrationHeight === 'string' || typeof flattenedIllustrationHeight === 'number' ? flattenedIllustrationHeight : styles.confirmationAnimation.height; - - return ( - - - - - {(() => { - if (shouldShowStaticFallback) { - return ( - - - - ); - } - if (isLottie) { - return ( - - ); - } - return ( - - - - ); - })()} - - {heading} - - {!!descriptionComponent && descriptionComponent} - {!!description && {description}} - {cta ? {cta} : null} - {!!ctaComponent && ctaComponent} - - - {!!footerComponent && {footerComponent}} - - {(shouldShowSecondaryButton || shouldShowButton) && ( - - {shouldShowSecondaryButton && ( - - )} - {shouldShowButton && ( - - )} - - )} - - ); -} - -export default ConfirmationPage; - -export type {ConfirmationPageProps}; diff --git a/src/components/ConfirmationPage/ConfirmationPage.tsx b/src/components/ConfirmationPage/ConfirmationPage.tsx new file mode 100644 index 000000000000..7fdf1d908df8 --- /dev/null +++ b/src/components/ConfirmationPage/ConfirmationPage.tsx @@ -0,0 +1,18 @@ +import useThemeStyles from '@hooks/useThemeStyles'; + +import type {StyleProp, ViewStyle} from 'react-native'; + +import {View} from 'react-native'; + +type ConfirmationPageProps = { + children: React.ReactNode; + style?: StyleProp; +}; + +function ConfirmationPage({children, style}: ConfirmationPageProps) { + const styles = useThemeStyles(); + + return {children}; +} + +export default ConfirmationPage; diff --git a/src/components/ConfirmationPage/composed/ConfirmationPageDefault.tsx b/src/components/ConfirmationPage/composed/ConfirmationPageDefault.tsx new file mode 100644 index 000000000000..45c78e087a28 --- /dev/null +++ b/src/components/ConfirmationPage/composed/ConfirmationPageDefault.tsx @@ -0,0 +1,101 @@ +import ConfirmationPage from '@components/ConfirmationPage/ConfirmationPage'; +import ConfirmationPageContent from '@components/ConfirmationPage/layout/ConfirmationPageContent'; +import ConfirmationPageDescription from '@components/ConfirmationPage/primitives/ConfirmationPageDescription'; +import ConfirmationPageHeading from '@components/ConfirmationPage/primitives/ConfirmationPageHeading'; +import ConfirmationPageIllustration from '@components/ConfirmationPage/primitives/ConfirmationPageIllustration'; +import ConfirmationPagePrimaryButton from '@components/ConfirmationPage/primitives/ConfirmationPagePrimaryButton'; +import FixedFooter from '@components/FixedFooter'; +import LottieAnimations from '@components/LottieAnimations'; +import type DotLottieAnimation from '@components/LottieAnimations/types'; + +import type {Errors} from '@src/types/onyx/OnyxCommon'; +import type IconAsset from '@src/types/utils/IconAsset'; + +import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; + +type ConfirmationPageProps = { + /** Illustration shown at the top: a Lottie animation or a static icon. Defaults to the fireworks animation */ + illustration?: DotLottieAnimation | IconAsset; + + /** Heading text displayed below the illustration */ + heading: string; + + /** Description text displayed below the heading */ + description: string; + + /** The text for the button label */ + buttonText?: string; + + /** A function that is called when the button is clicked on */ + onButtonPress?: () => void; + + /** Whether the button should be disabled */ + isButtonDisabled?: boolean; + + /** Whether the button should show a loading spinner */ + isButtonLoading?: boolean; + + /** Errors rendered as a message inside the footer, above the button */ + requestErrors?: Errors | null; + + /** Additional style for the outermost container */ + containerStyle?: StyleProp; + + /** Additional style for the centered container wrapping the illustration, heading and description */ + innerContainerStyle?: StyleProp; + + /** Additional style for the illustration */ + illustrationStyle?: StyleProp; + + /** Additional style for the heading text */ + headingStyle?: StyleProp; + + /** Additional style for the description text */ + descriptionStyle?: StyleProp; + + /** Additional style for the footer containing the button */ + footerStyle?: StyleProp; +}; + +function ConfirmationPageDefault({ + illustration = LottieAnimations.Fireworks, + heading, + description, + buttonText = '', + onButtonPress = () => {}, + isButtonDisabled = false, + isButtonLoading = false, + headingStyle, + illustrationStyle, + descriptionStyle, + footerStyle, + requestErrors, + containerStyle, + innerContainerStyle, +}: ConfirmationPageProps) { + return ( + + + + {heading} + {description} + + + + + + ); +} + +export default ConfirmationPageDefault; diff --git a/src/components/ConfirmationPage/index.tsx b/src/components/ConfirmationPage/index.tsx new file mode 100644 index 000000000000..53995aa90ea4 --- /dev/null +++ b/src/components/ConfirmationPage/index.tsx @@ -0,0 +1,48 @@ +/** + * ConfirmationPage: a confirmation/illustration screen built with composition API. + * + * Instead of a large flat props list (illustration, heading, description, shouldShowButton, …), + * sub-components are composed as children: + * + * @example + * ```tsx + * import ConfirmationPage from '@components/ConfirmationPage'; + * + * + * + * + * All set! + * Your changes have been saved. + * + * + * + * + * + * ``` + * + * For the common illustration/heading/description/button shape without custom composition, use `ConfirmationPageDefault` instead. + */ +import React from 'react'; + +import ConfirmationPageComponent from './ConfirmationPage'; +import ConfirmationPageContent from './layout/ConfirmationPageContent'; +import ConfirmationPageDescription from './primitives/ConfirmationPageDescription'; +import ConfirmationPageHeading from './primitives/ConfirmationPageHeading'; +import ConfirmationPageIllustration from './primitives/ConfirmationPageIllustration'; +import ConfirmationPagePrimaryButton from './primitives/ConfirmationPagePrimaryButton'; +import ConfirmationPageSecondaryButton from './primitives/ConfirmationPageSecondaryButton'; + +function ConfirmationPageBase(props: React.ComponentProps) { + return ; +} + +const ConfirmationPage = Object.assign(ConfirmationPageBase, { + Illustration: ConfirmationPageIllustration, + Heading: ConfirmationPageHeading, + Description: ConfirmationPageDescription, + PrimaryButton: ConfirmationPagePrimaryButton, + SecondaryButton: ConfirmationPageSecondaryButton, + Content: ConfirmationPageContent, +}); + +export default ConfirmationPage; diff --git a/src/components/ConfirmationPage/layout/ConfirmationPageContent.tsx b/src/components/ConfirmationPage/layout/ConfirmationPageContent.tsx new file mode 100644 index 000000000000..2d2e65db1ae3 --- /dev/null +++ b/src/components/ConfirmationPage/layout/ConfirmationPageContent.tsx @@ -0,0 +1,45 @@ +import FormHelpMessage from '@components/FormHelpMessage'; +import ScrollView from '@components/ScrollView'; + +import useThemeStyles from '@hooks/useThemeStyles'; + +import {getLatestErrorMessage} from '@libs/ErrorUtils'; + +import type {Errors} from '@src/types/onyx/OnyxCommon'; + +import type {StyleProp, ViewStyle} from 'react-native'; + +import {View} from 'react-native'; + +type ConfirmationPageContentProps = { + /** Errors rendered as a message at the bottom of the content area, above the footer */ + requestErrors?: Errors | null; + + /** Additional style for the centered container wrapping the children */ + style?: StyleProp; + + /** Content to render, typically the illustration, heading and description */ + children?: React.ReactNode; +}; + +function ConfirmationPageContent({requestErrors, style, children}: ConfirmationPageContentProps) { + const styles = useThemeStyles(); + + return ( + + + {children} + + {!!requestErrors && ( + + + + )} + + ); +} + +export default ConfirmationPageContent; diff --git a/src/components/ConfirmationPage/primitives/ConfirmationPageButtonBase.tsx b/src/components/ConfirmationPage/primitives/ConfirmationPageButtonBase.tsx new file mode 100644 index 000000000000..326a81fa434a --- /dev/null +++ b/src/components/ConfirmationPage/primitives/ConfirmationPageButtonBase.tsx @@ -0,0 +1,38 @@ +import Button from '@components/Button'; +import type {ButtonProps} from '@components/Button'; + +import useThemeStyles from '@hooks/useThemeStyles'; + +import CONST from '@src/CONST'; + +type ConfirmationPageButtonProps = Pick & { + text: string; + onPress?: () => void; +}; + +type ConfirmationPageButtonBaseProps = ConfirmationPageButtonProps & + Pick & { + children?: React.ReactNode; + }; + +function ConfirmationPageButtonBase({text, onPress = () => {}, isDisabled, isLoading, testID, variant, children}: ConfirmationPageButtonBaseProps) { + const styles = useThemeStyles(); + + return ( + + ); +} + +export default ConfirmationPageButtonBase; +export type {ConfirmationPageButtonProps}; diff --git a/src/components/ConfirmationPage/primitives/ConfirmationPageDescription.tsx b/src/components/ConfirmationPage/primitives/ConfirmationPageDescription.tsx new file mode 100644 index 000000000000..0cd572040457 --- /dev/null +++ b/src/components/ConfirmationPage/primitives/ConfirmationPageDescription.tsx @@ -0,0 +1,18 @@ +import Text from '@components/Text'; + +import useThemeStyles from '@hooks/useThemeStyles'; + +import type {StyleProp, TextStyle} from 'react-native'; + +type ConfirmationPageDescriptionProps = { + children: React.ReactNode; + style?: StyleProp; +}; + +function ConfirmationPageDescription({children, style}: ConfirmationPageDescriptionProps) { + const styles = useThemeStyles(); + + return {children}; +} + +export default ConfirmationPageDescription; diff --git a/src/components/ConfirmationPage/primitives/ConfirmationPageHeading.tsx b/src/components/ConfirmationPage/primitives/ConfirmationPageHeading.tsx new file mode 100644 index 000000000000..587fabd468d9 --- /dev/null +++ b/src/components/ConfirmationPage/primitives/ConfirmationPageHeading.tsx @@ -0,0 +1,27 @@ +import Text from '@components/Text'; + +import useThemeStyles from '@hooks/useThemeStyles'; + +import CONST from '@src/CONST'; + +import type {StyleProp, TextStyle} from 'react-native'; + +type ConfirmationPageHeadingProps = { + children: string; + style?: StyleProp; +}; + +function ConfirmationPageHeading({children, style}: ConfirmationPageHeadingProps) { + const styles = useThemeStyles(); + + return ( + + {children} + + ); +} + +export default ConfirmationPageHeading; diff --git a/src/components/ConfirmationPage/primitives/ConfirmationPageIllustration.tsx b/src/components/ConfirmationPage/primitives/ConfirmationPageIllustration.tsx new file mode 100644 index 000000000000..41ff0bfd5ada --- /dev/null +++ b/src/components/ConfirmationPage/primitives/ConfirmationPageIllustration.tsx @@ -0,0 +1,74 @@ +import ImageSVG from '@components/ImageSVG'; +import Lottie from '@components/Lottie'; +import LottieAnimations from '@components/LottieAnimations'; +import type DotLottieAnimation from '@components/LottieAnimations/types'; + +import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; +import useThemeStyles from '@hooks/useThemeStyles'; + +import Accessibility from '@libs/Accessibility'; +import isIllustrationLottieAnimation from '@libs/isIllustrationLottieAnimation'; + +import type IconAsset from '@src/types/utils/IconAsset'; + +import type {StyleProp, ViewStyle} from 'react-native'; + +import {StyleSheet, View} from 'react-native'; + +type ConfirmationPageIllustrationProps = { + illustration?: DotLottieAnimation | IconAsset; + illustrationStyle?: StyleProp; +}; + +function ConfirmationPageIllustration({illustration = LottieAnimations.Fireworks, illustrationStyle}: ConfirmationPageIllustrationProps) { + const styles = useThemeStyles(); + const isReduceMotionEnabled = Accessibility.useReducedMotion(); + const illustrations = useMemoizedLazyIllustrations(['Fireworks']); + const isLottie = isIllustrationLottieAnimation(illustration); + const flattenedIllustrationStyle = StyleSheet.flatten(illustrationStyle); + const flattenedIllustrationWidth = flattenedIllustrationStyle?.width; + const flattenedIllustrationHeight = flattenedIllustrationStyle?.height; + const webIllustrationWidth = + typeof flattenedIllustrationWidth === 'string' || typeof flattenedIllustrationWidth === 'number' ? flattenedIllustrationWidth : styles.confirmationAnimation.width; + const webIllustrationHeight = + typeof flattenedIllustrationHeight === 'string' || typeof flattenedIllustrationHeight === 'number' ? flattenedIllustrationHeight : styles.confirmationAnimation.height; + + if (isReduceMotionEnabled && illustration === LottieAnimations.Fireworks) { + return ( + + + + ); + } + + if (isLottie) { + return ( + + ); + } + + return ( + + + + ); +} + +export default ConfirmationPageIllustration; diff --git a/src/components/ConfirmationPage/primitives/ConfirmationPagePrimaryButton.tsx b/src/components/ConfirmationPage/primitives/ConfirmationPagePrimaryButton.tsx new file mode 100644 index 000000000000..acac3acf560a --- /dev/null +++ b/src/components/ConfirmationPage/primitives/ConfirmationPagePrimaryButton.tsx @@ -0,0 +1,21 @@ +import Button from '@components/Button'; + +import CONST from '@src/CONST'; + +import type {ConfirmationPageButtonProps} from './ConfirmationPageButtonBase'; + +import ConfirmationPageButtonBase from './ConfirmationPageButtonBase'; + +function ConfirmationPagePrimaryButton(props: ConfirmationPageButtonProps) { + return ( + + + + ); +} + +export default ConfirmationPagePrimaryButton; diff --git a/src/components/ConfirmationPage/primitives/ConfirmationPageSecondaryButton.tsx b/src/components/ConfirmationPage/primitives/ConfirmationPageSecondaryButton.tsx new file mode 100644 index 000000000000..89a207aad0b1 --- /dev/null +++ b/src/components/ConfirmationPage/primitives/ConfirmationPageSecondaryButton.tsx @@ -0,0 +1,14 @@ +import type {ConfirmationPageButtonProps} from './ConfirmationPageButtonBase'; + +import ConfirmationPageButtonBase from './ConfirmationPageButtonBase'; + +function ConfirmationPageSecondaryButton(props: ConfirmationPageButtonProps) { + return ( + + ); +} + +export default ConfirmationPageSecondaryButton; diff --git a/src/hooks/useMergeResultConfirmationConfig.tsx b/src/hooks/useMergeResultConfirmationConfig.tsx new file mode 100644 index 000000000000..dead33c9c04a --- /dev/null +++ b/src/hooks/useMergeResultConfirmationConfig.tsx @@ -0,0 +1,155 @@ +import ConfirmationPage from '@components/ConfirmationPage'; +/** + * Builds the ConfirmationPage config (heading, description, CTA, buttons, illustration) for each merge-account result. + */ +import LottieAnimations from '@components/LottieAnimations'; +import type DotLottieAnimation from '@components/LottieAnimations/types'; +import RenderHTML from '@components/RenderHTML'; +import Text from '@components/Text'; +import TextLink from '@components/TextLink'; + +import {shouldHideOldAppRedirect} from '@libs/TryNewDotUtils'; + +import {closeReactNativeApp} from '@userActions/HybridApp'; +import {openOldDotLink} from '@userActions/Link'; + +import CONFIG from '@src/CONFIG'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import {DYNAMIC_ROUTES} from '@src/ROUTES'; +import {isTrackingSelector} from '@src/selectors/GPSDraftDetails'; +import type IconAsset from '@src/types/utils/IconAsset'; +import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; + +import type {StyleProp, ViewStyle} from 'react-native'; +import type {ValueOf} from 'type-fest'; + +import {emailSelector} from '@selectors/Session'; +import React from 'react'; +import {View} from 'react-native'; + +import useEnvironment from './useEnvironment'; +import {useMemoizedLazyIllustrations} from './useLazyAsset'; +import useLocalize from './useLocalize'; +import useOnyx from './useOnyx'; +import useScreenBoundDynamicRoute from './useScreenBoundDynamicRoute'; +import useThemeStyles from './useThemeStyles'; + +type MergeResultConfirmationConfig = { + heading?: string; + descriptionComponent?: React.ReactNode; + ctaComponent?: React.ReactNode; + onButtonPress?: () => void; + illustration?: DotLottieAnimation | IconAsset; + illustrationStyle?: StyleProp; + secondaryButtonText?: string; + onSecondaryButtonPress?: () => void; + shouldShowSecondaryButton?: boolean; +}; + +function DescriptionHTML({html}: {html: string}) { + const styles = useThemeStyles(); + + return ( + + + + ); +} + +function useMergeResultConfirmationConfig({result, login}: {result: ValueOf; login: string}): MergeResultConfirmationConfig { + const styles = useThemeStyles(); + const {translate} = useLocalize(); + const [userEmailOrPhone] = useOnyx(ONYXKEYS.SESSION, {selector: emailSelector}); + const [tryNewDot, tryNewDotMetadata] = useOnyx(ONYXKEYS.NVP_TRY_NEW_DOT); + const [isTrackingGPS = false] = useOnyx(ONYXKEYS.GPS_DRAFT_DETAILS, {selector: isTrackingSelector}); + const {environmentURL} = useEnvironment(); + const buildDynamicRoute = useScreenBoundDynamicRoute(); + const lazyIllustrations = useMemoizedLazyIllustrations(['RunningTurtle', 'LockClosedOrange']); + const isLoadingTryNewDot = isLoadingOnyxValue(tryNewDotMetadata); + const isClassicRedirectBlocked = shouldHideOldAppRedirect(tryNewDot, isLoadingTryNewDot, CONFIG.IS_HYBRID_APP); + + const defaultResult = { + illustration: lazyIllustrations.LockClosedOrange, + onButtonPress: () => {}, + }; + + const results: Record, MergeResultConfirmationConfig> = { + [CONST.MERGE_ACCOUNT_RESULTS.SUCCESS]: { + heading: translate('mergeAccountsPage.mergeSuccess.accountsMerged'), + descriptionComponent: , + illustration: LottieAnimations.Fireworks, + illustrationStyle: {width: 150, height: 150}, + }, + [CONST.MERGE_ACCOUNT_RESULTS.ERR_NO_EXIST]: { + descriptionComponent: ( + + ), + }, + [CONST.MERGE_ACCOUNT_RESULTS.ERR_2FA]: { + descriptionComponent: , + ctaComponent: ( + + {translate('mergeAccountsPage.mergeFailure2FA.learnMore')} + + ), + }, + [CONST.MERGE_ACCOUNT_RESULTS.ERR_SMART_SCANNER]: { + descriptionComponent: , + }, + [CONST.MERGE_ACCOUNT_RESULTS.ERR_SAML_DOMAIN_CONTROL]: { + descriptionComponent: , + }, + [CONST.MERGE_ACCOUNT_RESULTS.ERR_SAML_NOT_SUPPORTED]: { + heading: translate('mergeAccountsPage.mergePendingSAML.weAreWorkingOnIt'), + descriptionComponent: {translate('mergeAccountsPage.mergePendingSAML.limitedSupport')}, + ctaComponent: ( + + + + ), + secondaryButtonText: translate('mergeAccountsPage.mergePendingSAML.goToExpensifyClassic'), + onSecondaryButtonPress: () => { + if (CONFIG.IS_HYBRID_APP) { + closeReactNativeApp({shouldSetNVP: true, isTrackingGPS}); + return; + } + openOldDotLink(CONST.OLDDOT_URLS.INBOX, false); + }, + shouldShowSecondaryButton: !isClassicRedirectBlocked, + illustration: lazyIllustrations.RunningTurtle, + illustrationStyle: {width: 132, height: 150}, + }, + [CONST.MERGE_ACCOUNT_RESULTS.ERR_SAML_PRIMARY_LOGIN]: { + descriptionComponent: , + }, + [CONST.MERGE_ACCOUNT_RESULTS.ERR_ACCOUNT_LOCKED]: { + descriptionComponent: , + }, + [CONST.MERGE_ACCOUNT_RESULTS.ERR_INVOICING]: { + descriptionComponent: , + }, + [CONST.MERGE_ACCOUNT_RESULTS.TOO_MANY_ATTEMPTS]: { + heading: translate('mergeAccountsPage.mergeFailureTooManyAttempts.heading'), + descriptionComponent: ( + {translate('mergeAccountsPage.mergeFailureTooManyAttempts.description')} + ), + }, + [CONST.MERGE_ACCOUNT_RESULTS.ACCOUNT_UNVALIDATED]: { + descriptionComponent: ( + {translate('mergeAccountsPage.mergeFailureUnvalidatedAccount.description')} + ), + }, + [CONST.MERGE_ACCOUNT_RESULTS.ERR_MERGE_SELF]: { + descriptionComponent: ( + {translate('mergeAccountsPage.mergeFailureSelfMerge.description')} + ), + }, + }; + + return results[result] || defaultResult; +} + +export default useMergeResultConfirmationConfig; diff --git a/src/pages/AddPersonalBankAccountPage/substeps/SuccessStep.tsx b/src/pages/AddPersonalBankAccountPage/substeps/SuccessStep.tsx index 41214e456fa4..b1bdf97506bf 100644 --- a/src/pages/AddPersonalBankAccountPage/substeps/SuccessStep.tsx +++ b/src/pages/AddPersonalBankAccountPage/substeps/SuccessStep.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import ScrollView from '@components/ScrollView'; import useLocalize from '@hooks/useLocalize'; @@ -13,13 +13,11 @@ function SuccessStep({onNext}: SubPageProps) { return ( - onNext(true)} - containerStyle={styles.h100} /> ); diff --git a/src/pages/EnablePayments/Pay/Activate/ActivateStep.tsx b/src/pages/EnablePayments/Pay/Activate/ActivateStep.tsx index aca6ca5a4d90..eb113bdd8ef4 100644 --- a/src/pages/EnablePayments/Pay/Activate/ActivateStep.tsx +++ b/src/pages/EnablePayments/Pay/Activate/ActivateStep.tsx @@ -1,4 +1,5 @@ import ConfirmationPage from '@components/ConfirmationPage'; +import FixedFooter from '@components/FixedFooter'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {KYCWallContext} from '@components/KYCWall/KYCWallContext'; import LottieAnimations from '@components/LottieAnimations'; @@ -40,14 +41,21 @@ function ActivateStep({userWallet}: ActivateStepProps) { return ( <> - continueSetup(kycWallRef)} - /> + + + + {translate(`activateStep.${isActivatedWallet ? 'activated' : 'checkBackLater'}Title`)} + {translate(`activateStep.${isActivatedWallet ? 'activated' : 'checkBackLater'}Message`)} + + {!!isActivatedWallet && ( + + continueSetup(kycWallRef)} + /> + + )} + ); } diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx b/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx index b634068ca9e6..b8260c2973a9 100644 --- a/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx +++ b/src/pages/ReimbursementAccount/ReimbursementAccountPage.tsx @@ -1,6 +1,6 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {useSession} from '@components/OnyxListItemProvider'; @@ -702,10 +702,9 @@ function ReimbursementAccountPage({route, policy, isLoadingPolicy}: Reimbursemen title={translate('bankAccount.addBankAccount')} onBackButtonPress={() => Navigation.dismissModal()} /> - Navigation.dismissModal()} diff --git a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx index 0070cf7e283b..7566f84da8de 100644 --- a/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx +++ b/src/pages/ReimbursementAccount/USD/ConnectBankAccount/ConnectBankAccount.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ReimbursementAccountLoadingIndicator from '@components/ReimbursementAccountLoadingIndicator'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -93,10 +93,9 @@ function ConnectBankAccount({onBackButtonPress, setShouldShowConnectedVerifiedBa title={translate('bankAccount.addBankAccount')} onBackButtonPress={() => Navigation.dismissModal()} /> - Navigation.dismissModal()} diff --git a/src/pages/TransactionDuplicate/DynamicReviewPage.tsx b/src/pages/TransactionDuplicate/DynamicReviewPage.tsx index b053d14073b4..e46b32624900 100644 --- a/src/pages/TransactionDuplicate/DynamicReviewPage.tsx +++ b/src/pages/TransactionDuplicate/DynamicReviewPage.tsx @@ -1,6 +1,6 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import Button from '@components/Button'; -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import FixedFooter from '@components/FixedFooter'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ReportActionsSkeletonView from '@components/ReportActionsSkeletonView'; @@ -274,10 +274,9 @@ function DynamicReviewPage() { title={translate('iou.reviewDuplicates')} onBackButtonPress={() => Navigation.goBack(backPath, {compareParams: false})} /> - Navigation.goBack(backPath, {compareParams: false})} /> diff --git a/src/pages/domain/BaseDomainVerifiedPage.tsx b/src/pages/domain/BaseDomainVerifiedPage.tsx index a772a7d7fd24..935737e95a65 100644 --- a/src/pages/domain/BaseDomainVerifiedPage.tsx +++ b/src/pages/domain/BaseDomainVerifiedPage.tsx @@ -1,7 +1,7 @@ import ConfirmationPage from '@components/ConfirmationPage'; +import FixedFooter from '@components/FixedFooter'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import LottieAnimations from '@components/LottieAnimations'; import RenderHTML from '@components/RenderHTML'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -64,19 +64,21 @@ function BaseDomainVerifiedPage({domainAccountID, redirectTo, confirmDestination shouldShowOfflineIndicator={false} > - + + + {translate('domain.domainVerified.header')} - } - innerContainerStyle={styles.p10} - buttonText={translate('common.buttonConfirm')} - shouldShowButton - onButtonPress={() => Navigation.navigate(confirmDestination)} - /> + + + Navigation.navigate(confirmDestination)} + /> + + ); } diff --git a/src/pages/domain/DomainAccessRestrictedPage.tsx b/src/pages/domain/DomainAccessRestrictedPage.tsx index 7f57737bdbdd..068745da69aa 100644 --- a/src/pages/domain/DomainAccessRestrictedPage.tsx +++ b/src/pages/domain/DomainAccessRestrictedPage.tsx @@ -1,5 +1,5 @@ import ConfirmationPage from '@components/ConfirmationPage'; -import FormHelpMessage from '@components/FormHelpMessage'; +import FixedFooter from '@components/FixedFooter'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import RenderHTML from '@components/RenderHTML'; @@ -13,7 +13,6 @@ import useRedirectOnDomainAccessChange from '@hooks/useRedirectOnDomainAccessCha import useThemeStyles from '@hooks/useThemeStyles'; import {clearRequestAdminshipError, requestDomainAdminship} from '@libs/actions/Domain'; -import {getLatestErrorMessage} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {WorkspacesDomainModalNavigatorParamList} from '@libs/Navigation/types'; @@ -69,37 +68,35 @@ function DomainAccessRestrictedPage({route}: DomainAccessRestrictedPageProps) { title={translate('domain.accessRestricted.headerTitle')} onBackButtonPress={Navigation.goBack} /> - + + + {translate('domain.accessRestricted.title')} - } - footerComponent={ - !!requestError && ( - - ) - } - shouldShowSecondaryButton - secondaryButtonText={translate(hasPendingRequest ? 'domain.requestSent' : 'domain.accessRestricted.requestAdminAccess')} - isSecondaryButtonLoading={isRequestPending} - isSecondaryButtonDisabled={!isRequestPending && (!!hasPendingRequest || isOffline)} - onSecondaryButtonPress={() => { - if (!currentUserAccountID) { - return; - } - requestDomainAdminship(domainAccountID, currentUserAccountID, false); - }} - shouldShowButton - buttonText={translate('domain.accessRestricted.verifyYourself')} - onButtonPress={() => Navigation.navigate(ROUTES.WORKSPACES_VERIFY_DOMAIN.getRoute(domainAccountID))} - /> + + + { + if (!currentUserAccountID) { + return; + } + requestDomainAdminship(domainAccountID, currentUserAccountID, false); + }} + /> + Navigation.navigate(ROUTES.WORKSPACES_VERIFY_DOMAIN.getRoute(domainAccountID))} + /> + + )} diff --git a/src/pages/domain/DomainAddedPage.tsx b/src/pages/domain/DomainAddedPage.tsx index 7860f6a7354e..aa3aeac41b30 100644 --- a/src/pages/domain/DomainAddedPage.tsx +++ b/src/pages/domain/DomainAddedPage.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {loadIllustration} from '@components/Icon/IllustrationLoader'; @@ -47,14 +47,13 @@ function DomainAddedPage({route}: DomainAddedPageProps) { return ( - Navigation.navigate(ROUTES.DOMAIN_INITIAL.getRoute(domainAccountID))} /> diff --git a/src/pages/domain/DomainAlreadyExistsPage.tsx b/src/pages/domain/DomainAlreadyExistsPage.tsx index 85a94694c2cf..11a1db75624a 100644 --- a/src/pages/domain/DomainAlreadyExistsPage.tsx +++ b/src/pages/domain/DomainAlreadyExistsPage.tsx @@ -1,5 +1,5 @@ import ConfirmationPage from '@components/ConfirmationPage'; -import FormHelpMessage from '@components/FormHelpMessage'; +import FixedFooter from '@components/FixedFooter'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {loadIllustration} from '@components/Icon/IllustrationLoader'; @@ -13,7 +13,6 @@ import useRedirectOnDomainAccessChange from '@hooks/useRedirectOnDomainAccessCha import useThemeStyles from '@hooks/useThemeStyles'; import {clearRequestAdminshipError, requestDomainAdminship} from '@libs/actions/Domain'; -import {getLatestErrorMessage} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {WorkspacesDomainModalNavigatorParamList} from '@libs/Navigation/types'; @@ -80,36 +79,37 @@ function DomainAlreadyExistsPage({route}: DomainAlreadyExistsPageProps) { title={translate('domain.domainAlreadyExists.headerTitle')} onBackButtonPress={goToDomainsList} /> - - ) - } - shouldShowSecondaryButton - secondaryButtonText={translate('domain.common.neverMind')} - onSecondaryButtonPress={goToDomainsList} - shouldShowButton - buttonText={translate(hasPendingRequest ? 'domain.requestSent' : 'domain.domainAlreadyExists.requestAccess')} - isButtonLoading={isRequestPending} - isButtonDisabled={!isRequestPending && (!!hasPendingRequest || isOffline)} - onButtonPress={() => { - if (!currentUserAccountID) { - return; - } - setHasSubmittedRequest(true); - requestDomainAdminship(domainAccountID, currentUserAccountID, !!isTransientDomainEntry); - }} - /> + + + + {translate('domain.domainAlreadyExists.title')} + {translate('domain.domainAlreadyExists.description')} + + + + { + if (!currentUserAccountID) { + return; + } + setHasSubmittedRequest(true); + requestDomainAdminship(domainAccountID, currentUserAccountID, !!isTransientDomainEntry); + }} + /> + + ); } diff --git a/src/pages/inbox/report/DynamicReportDetailsExportPage.tsx b/src/pages/inbox/report/DynamicReportDetailsExportPage.tsx index ee4726346767..e268865c717a 100644 --- a/src/pages/inbox/report/DynamicReportDetailsExportPage.tsx +++ b/src/pages/inbox/report/DynamicReportDetailsExportPage.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {ModalActions} from '@components/Modal/Global/ModalContext'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -129,11 +129,10 @@ function DynamicReportDetailsExportPage({route}: DynamicReportDetailsExportPageP title={translate('common.export')} onBackButtonPress={() => Navigation.goBack(navigateBackFromExportPath)} /> - Navigation.goBack()} illustrationStyle={{width: 233, height: 162}} diff --git a/src/pages/settings/Security/LockAccount/FailedToLockAccountPage.tsx b/src/pages/settings/Security/LockAccount/FailedToLockAccountPage.tsx index a3a1f63e1105..ee4c354d83f5 100644 --- a/src/pages/settings/Security/LockAccount/FailedToLockAccountPage.tsx +++ b/src/pages/settings/Security/LockAccount/FailedToLockAccountPage.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; @@ -28,15 +28,13 @@ function FailedToLockAccountPage() { title={translate('lockAccountPage.lockAccount')} /> - Navigation.navigate(ROUTES.CONCIERGE)} - containerStyle={styles.h100} /> diff --git a/src/pages/settings/Security/LockAccount/UnlockAccountPage.tsx b/src/pages/settings/Security/LockAccount/UnlockAccountPage.tsx index 46c832e6941f..0aaa1e52da19 100644 --- a/src/pages/settings/Security/LockAccount/UnlockAccountPage.tsx +++ b/src/pages/settings/Security/LockAccount/UnlockAccountPage.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; @@ -32,18 +32,16 @@ function UnlockAccountPage() { title={translate('unlockAccountPage.accountLocked')} /> - { requestUnlockAccount(currentUserPersonalDetails.accountID); Navigation.navigate(ROUTES.CONCIERGE); }} - containerStyle={styles.h100} /> diff --git a/src/pages/settings/Security/MergeAccounts/MergeResultPage.tsx b/src/pages/settings/Security/MergeAccounts/MergeResultPage.tsx index 33ed8c4c1741..9d358526f20e 100644 --- a/src/pages/settings/Security/MergeAccounts/MergeResultPage.tsx +++ b/src/pages/settings/Security/MergeAccounts/MergeResultPage.tsx @@ -1,217 +1,31 @@ import ConfirmationPage from '@components/ConfirmationPage'; -import type {ConfirmationPageProps} from '@components/ConfirmationPage'; +import FixedFooter from '@components/FixedFooter'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import LottieAnimations from '@components/LottieAnimations'; -import RenderHTML from '@components/RenderHTML'; import ScreenWrapper from '@components/ScreenWrapper'; -import TextLink from '@components/TextLink'; -import useEnvironment from '@hooks/useEnvironment'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; -import useOnyx from '@hooks/useOnyx'; -import useScreenBoundDynamicRoute from '@hooks/useScreenBoundDynamicRoute'; +import useMergeResultConfirmationConfig from '@hooks/useMergeResultConfirmationConfig'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; import TransitionTracker from '@libs/Navigation/TransitionTracker'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; -import {shouldHideOldAppRedirect} from '@libs/TryNewDotUtils'; -import {closeReactNativeApp} from '@userActions/HybridApp'; -import {openOldDotLink} from '@userActions/Link'; - -import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; -import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES, {DYNAMIC_ROUTES} from '@src/ROUTES'; +import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; -import {isTrackingSelector} from '@src/selectors/GPSDraftDetails'; -import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; - -import type {ValueOf} from 'type-fest'; import {useRoute} from '@react-navigation/native'; -import {emailSelector} from '@selectors/Session'; -import React, {useEffect, useMemo} from 'react'; -import {View} from 'react-native'; +import {useEffect} from 'react'; function MergeResultPage() { const styles = useThemeStyles(); const {translate} = useLocalize(); - const [userEmailOrPhone] = useOnyx(ONYXKEYS.SESSION, {selector: emailSelector}); - const [tryNewDot, tryNewDotMetadata] = useOnyx(ONYXKEYS.NVP_TRY_NEW_DOT); - const [isTrackingGPS = false] = useOnyx(ONYXKEYS.GPS_DRAFT_DETAILS, {selector: isTrackingSelector}); + const lazyIllustrations = useMemoizedLazyIllustrations(['LockClosedOrange']); const {params} = useRoute>(); - const {environmentURL} = useEnvironment(); - const buildDynamicRoute = useScreenBoundDynamicRoute(); const {result, login, backTo} = params; - const lazyIllustrations = useMemoizedLazyIllustrations(['RunningTurtle', 'LockClosedOrange']); - const isLoadingTryNewDot = isLoadingOnyxValue(tryNewDotMetadata); - const isClassicRedirectBlocked = shouldHideOldAppRedirect(tryNewDot, isLoadingTryNewDot, CONFIG.IS_HYBRID_APP); - - const defaultResult = { - heading: translate('mergeAccountsPage.mergeFailureGenericHeading'), - buttonText: translate('common.buttonConfirm'), - illustration: lazyIllustrations.LockClosedOrange, - }; - - const results: Record, ConfirmationPageProps> = useMemo(() => { - return { - [CONST.MERGE_ACCOUNT_RESULTS.SUCCESS]: { - heading: translate('mergeAccountsPage.mergeSuccess.accountsMerged'), - descriptionComponent: ( - - - - ), - buttonText: translate('common.buttonConfirm'), - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - illustration: LottieAnimations.Fireworks, - illustrationStyle: {width: 150, height: 150}, - }, - [CONST.MERGE_ACCOUNT_RESULTS.ERR_NO_EXIST]: { - heading: translate('mergeAccountsPage.mergeFailureGenericHeading'), - descriptionComponent: ( - - - - ), - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - buttonText: translate('common.buttonConfirm'), - illustration: lazyIllustrations.LockClosedOrange, - }, - [CONST.MERGE_ACCOUNT_RESULTS.ERR_2FA]: { - heading: translate('mergeAccountsPage.mergeFailureGenericHeading'), - descriptionComponent: ( - - - - ), - cta: {translate('mergeAccountsPage.mergeFailure2FA.learnMore')}, - ctaStyle: {...styles.mt2, ...styles.textSupporting}, - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - buttonText: translate('common.buttonConfirm'), - illustration: lazyIllustrations.LockClosedOrange, - }, - [CONST.MERGE_ACCOUNT_RESULTS.ERR_SMART_SCANNER]: { - heading: translate('mergeAccountsPage.mergeFailureGenericHeading'), - descriptionComponent: ( - - - - ), - buttonText: translate('common.buttonConfirm'), - illustration: lazyIllustrations.LockClosedOrange, - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - }, - [CONST.MERGE_ACCOUNT_RESULTS.ERR_SAML_DOMAIN_CONTROL]: { - heading: translate('mergeAccountsPage.mergeFailureGenericHeading'), - descriptionComponent: ( - - - - ), - buttonText: translate('common.buttonConfirm'), - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - illustration: lazyIllustrations.LockClosedOrange, - }, - [CONST.MERGE_ACCOUNT_RESULTS.ERR_SAML_NOT_SUPPORTED]: { - heading: translate('mergeAccountsPage.mergePendingSAML.weAreWorkingOnIt'), - description: translate('mergeAccountsPage.mergePendingSAML.limitedSupport'), - ctaComponent: ( - - - - ), - secondaryButtonText: translate('mergeAccountsPage.mergePendingSAML.goToExpensifyClassic'), - onSecondaryButtonPress: () => { - if (CONFIG.IS_HYBRID_APP) { - closeReactNativeApp({shouldSetNVP: true, isTrackingGPS}); - return; - } - openOldDotLink(CONST.OLDDOT_URLS.INBOX, false); - }, - shouldShowSecondaryButton: !isClassicRedirectBlocked, - buttonText: translate('common.buttonConfirm'), - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - illustration: lazyIllustrations.RunningTurtle, - illustrationStyle: {width: 132, height: 150}, - }, - [CONST.MERGE_ACCOUNT_RESULTS.ERR_SAML_PRIMARY_LOGIN]: { - heading: translate('mergeAccountsPage.mergeFailureGenericHeading'), - descriptionComponent: ( - - - - ), - buttonText: translate('common.buttonConfirm'), - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - illustration: lazyIllustrations.LockClosedOrange, - }, - [CONST.MERGE_ACCOUNT_RESULTS.ERR_ACCOUNT_LOCKED]: { - heading: translate('mergeAccountsPage.mergeFailureGenericHeading'), - descriptionComponent: ( - - - - ), - buttonText: translate('common.buttonConfirm'), - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - illustration: lazyIllustrations.LockClosedOrange, - }, - [CONST.MERGE_ACCOUNT_RESULTS.ERR_INVOICING]: { - heading: translate('mergeAccountsPage.mergeFailureGenericHeading'), - descriptionComponent: ( - - - - ), - buttonText: translate('common.buttonConfirm'), - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - illustration: lazyIllustrations.LockClosedOrange, - }, - [CONST.MERGE_ACCOUNT_RESULTS.TOO_MANY_ATTEMPTS]: { - heading: translate('mergeAccountsPage.mergeFailureTooManyAttempts.heading'), - description: translate('mergeAccountsPage.mergeFailureTooManyAttempts.description'), - buttonText: translate('common.buttonConfirm'), - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - illustration: lazyIllustrations.LockClosedOrange, - }, - [CONST.MERGE_ACCOUNT_RESULTS.ACCOUNT_UNVALIDATED]: { - heading: translate('mergeAccountsPage.mergeFailureGenericHeading'), - description: translate('mergeAccountsPage.mergeFailureUnvalidatedAccount.description'), - buttonText: translate('common.buttonConfirm'), - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - illustration: lazyIllustrations.LockClosedOrange, - }, - [CONST.MERGE_ACCOUNT_RESULTS.ERR_MERGE_SELF]: { - heading: translate('mergeAccountsPage.mergeFailureGenericHeading'), - description: translate('mergeAccountsPage.mergeFailureSelfMerge.description'), - buttonText: translate('common.buttonConfirm'), - onButtonPress: () => Navigation.goBack(ROUTES.SETTINGS_SECURITY), - illustration: lazyIllustrations.LockClosedOrange, - }, - }; - }, [ - login, - translate, - userEmailOrPhone, - styles, - isTrackingGPS, - environmentURL, - buildDynamicRoute, - lazyIllustrations.LockClosedOrange, - lazyIllustrations.RunningTurtle, - isClassicRedirectBlocked, - ]); useEffect(() => { /** @@ -231,23 +45,8 @@ function MergeResultPage() { return () => handle.cancel(); }, [result]); - const { - heading, - headingStyle, - onButtonPress, - descriptionStyle, - illustration, - illustrationStyle, - description, - descriptionComponent, - buttonText, - secondaryButtonText, - onSecondaryButtonPress, - shouldShowSecondaryButton, - cta, - ctaComponent, - ctaStyle, - } = results[result] || defaultResult; + const {heading, onButtonPress, illustration, illustrationStyle, descriptionComponent, secondaryButtonText, onSecondaryButtonPress, shouldShowSecondaryButton, ctaComponent} = + useMergeResultConfirmationConfig({result, login}); return ( - + + + + {heading ?? translate('mergeAccountsPage.mergeFailureGenericHeading')} + {descriptionComponent} + {ctaComponent} + + + {!!shouldShowSecondaryButton && ( + + )} + Navigation.goBack(ROUTES.SETTINGS_SECURITY))} + /> + + ); } diff --git a/src/pages/settings/Security/TwoFactorAuth/SuccessPageBase.tsx b/src/pages/settings/Security/TwoFactorAuth/SuccessPageBase.tsx index 5c4329086174..66ced28c836b 100644 --- a/src/pages/settings/Security/TwoFactorAuth/SuccessPageBase.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/SuccessPageBase.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import LottieAnimations from '@components/LottieAnimations'; import useLocalize from '@hooks/useLocalize'; @@ -25,11 +25,10 @@ function SuccessPageBase({onButtonPress, onBackButtonPress}: SuccessPageBaseProp title={translate('twoFactorAuth.headerTitle')} onBackButtonPress={onBackButtonPress} > - - diff --git a/src/pages/settings/Wallet/CardAddedToWalletPage.tsx b/src/pages/settings/Wallet/CardAddedToWalletPage.tsx index b4f569bfe394..c2a7235c7f0a 100644 --- a/src/pages/settings/Wallet/CardAddedToWalletPage.tsx +++ b/src/pages/settings/Wallet/CardAddedToWalletPage.tsx @@ -1,4 +1,5 @@ import ConfirmationPage from '@components/ConfirmationPage'; +import FixedFooter from '@components/FixedFooter'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import Icon from '@components/Icon'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -47,11 +48,10 @@ function CardAddedToWalletPage({ title={translate('cardPage.cardAddedToWalletPage.title')} onBackButtonPress={goToCardDetails} /> - + + + {translate('cardPage.cardAddedToWalletPage.description')} {translate('cardPage.cardAddedToWalletPage.firstSupportingText')} {translate('cardPage.cardAddedToWalletPage.secondSupportingText')} @@ -73,11 +73,14 @@ function CardAddedToWalletPage({ /> - } - onButtonPress={goToCardDetails} - buttonText={translate('cardPage.cardAddedToWalletPage.buttonText')} - headingStyle={styles.ph8} - /> + + + + + ); } diff --git a/src/pages/settings/Wallet/CollectDepositAccount/subPages/Success.tsx b/src/pages/settings/Wallet/CollectDepositAccount/subPages/Success.tsx index b5aacd36731a..1452775d2ec8 100644 --- a/src/pages/settings/Wallet/CollectDepositAccount/subPages/Success.tsx +++ b/src/pages/settings/Wallet/CollectDepositAccount/subPages/Success.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import ScrollView from '@components/ScrollView'; import useLocalize from '@hooks/useLocalize'; @@ -14,13 +14,11 @@ function Success({onNext}: CustomSubPageProps) { return ( - ); diff --git a/src/pages/settings/Wallet/InternationalDepositAccount/subPages/Success.tsx b/src/pages/settings/Wallet/InternationalDepositAccount/subPages/Success.tsx index fbfbf359588f..c25480a6f10f 100644 --- a/src/pages/settings/Wallet/InternationalDepositAccount/subPages/Success.tsx +++ b/src/pages/settings/Wallet/InternationalDepositAccount/subPages/Success.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import ScrollView from '@components/ScrollView'; import useLocalize from '@hooks/useLocalize'; @@ -14,13 +14,11 @@ function Confirmation({onNext}: CustomSubPageProps) { return ( - ); diff --git a/src/pages/settings/Wallet/PersonalCards/PersonalCardsErrorConfirmation.tsx b/src/pages/settings/Wallet/PersonalCards/PersonalCardsErrorConfirmation.tsx index 531a6321918f..a54d06b1ab69 100644 --- a/src/pages/settings/Wallet/PersonalCards/PersonalCardsErrorConfirmation.tsx +++ b/src/pages/settings/Wallet/PersonalCards/PersonalCardsErrorConfirmation.tsx @@ -1,5 +1,5 @@ import ConfirmationPage from '@components/ConfirmationPage'; -import Text from '@components/Text'; +import FixedFooter from '@components/FixedFooter'; import TextLink from '@components/TextLink'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -43,10 +43,14 @@ function PersonalCardsErrorConfirmation({errorMessage}: PersonalCardsErrorConfir }; return ( - + + + + {translate('personalCard.bankConnectionError')} + {!!errorMessage && `${errorMessage} `} {translate('personalCard.bankConnectionDescription')}{' '} {translate('personalCard.connectWithPlaid')} - - } - illustration={illustrations.QuestionMark} - shouldShowButton - illustrationStyle={styles.errorStateCardIllustration} - onButtonPress={onButtonPress} - buttonText={translate('common.buttonConfirm')} - containerStyle={styles.h100} - /> + + + + + + ); } diff --git a/src/pages/settings/Wallet/PersonalCards/steps/SuccessStep.tsx b/src/pages/settings/Wallet/PersonalCards/steps/SuccessStep.tsx index 7d76c8784245..a8499cb735a3 100644 --- a/src/pages/settings/Wallet/PersonalCards/steps/SuccessStep.tsx +++ b/src/pages/settings/Wallet/PersonalCards/steps/SuccessStep.tsx @@ -1,5 +1,5 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; @@ -32,13 +32,11 @@ function SuccessStep() { onBackButtonPress={exitFlow} /> - diff --git a/src/pages/settings/Wallet/PersonalCards/upgrade/UpgradeConfirmation.tsx b/src/pages/settings/Wallet/PersonalCards/upgrade/UpgradeConfirmation.tsx index 64522d1ad1f4..36f52ab0a4a3 100644 --- a/src/pages/settings/Wallet/PersonalCards/upgrade/UpgradeConfirmation.tsx +++ b/src/pages/settings/Wallet/PersonalCards/upgrade/UpgradeConfirmation.tsx @@ -1,4 +1,5 @@ import ConfirmationPage from '@components/ConfirmationPage'; +import FixedFooter from '@components/FixedFooter'; import RenderHTML from '@components/RenderHTML'; import useEnvironment from '@hooks/useEnvironment'; @@ -28,21 +29,25 @@ function UpgradeConfirmation({addCompanyCard, addPersonalCard}: {addCompanyCard: }, [updateSubscriptionLink]); return ( - + + + {translate('personalCard.newWorkspace')} - } - shouldShowButton - shouldShowSecondaryButton - onSecondaryButtonPress={addCompanyCard} - secondaryButtonText={translate('personalCard.addCompanyCard')} - onButtonPress={addPersonalCard} - buttonText={translate('personalCard.addPersonalCard')} - containerStyle={styles.h100} - /> + + + + + + ); } diff --git a/src/pages/settings/Wallet/ShareBankAccount/ShareBankAccount.tsx b/src/pages/settings/Wallet/ShareBankAccount/ShareBankAccount.tsx index 92f2b0ca9951..eb72d66ab686 100644 --- a/src/pages/settings/Wallet/ShareBankAccount/ShareBankAccount.tsx +++ b/src/pages/settings/Wallet/ShareBankAccount/ShareBankAccount.tsx @@ -1,5 +1,5 @@ import BlockingView from '@components/BlockingViews/BlockingView'; -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import ErrorMessageRow from '@components/ErrorMessageRow'; import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -188,16 +188,14 @@ function ShareBankAccount({route}: ShareBankAccountProps) { /> {shouldShowSuccess ? ( - ) : ( diff --git a/src/pages/settings/Wallet/SuccessReportCardLost.tsx b/src/pages/settings/Wallet/SuccessReportCardLost.tsx index 8b0a0c8e57f0..28fafc198124 100644 --- a/src/pages/settings/Wallet/SuccessReportCardLost.tsx +++ b/src/pages/settings/Wallet/SuccessReportCardLost.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; @@ -18,11 +18,10 @@ function SuccessReportCardLost({cardID, isFromDomainCardDetail = false}: {cardID const illustrations = useMemoizedLazyIllustrations(['CardReplacementSuccess']); return ( - { // Going back with compareParams: false collapses the flow onto the deleted card route and // replaces its cardID with the replacement card instead of a stale/NotFound route. @@ -30,7 +29,6 @@ function SuccessReportCardLost({cardID, isFromDomainCardDetail = false}: {cardID Navigation.goBack(cardDetailRoute, {compareParams: false}); }} buttonText={translate('common.buttonConfirm')} - containerStyle={styles.h100} illustrationStyle={[styles.w100, StyleUtils.getSuccessReportCardLostIllustrationStyle()]} innerContainerStyle={styles.ph0} descriptionStyle={[styles.ph4, styles.textSupporting]} diff --git a/src/pages/settings/Wallet/TransferBalancePage.tsx b/src/pages/settings/Wallet/TransferBalancePage.tsx index a430844335f9..5ebbf6959324 100644 --- a/src/pages/settings/Wallet/TransferBalancePage.tsx +++ b/src/pages/settings/Wallet/TransferBalancePage.tsx @@ -1,5 +1,5 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import CurrentWalletBalance from '@components/CurrentWalletBalance'; import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -125,14 +125,13 @@ function TransferBalancePage() { title={translate('common.transferBalance')} onBackButtonPress={dismissSuccessfulTransferBalancePage} /> - - diff --git a/src/pages/settings/Wallet/WiseGlobalReimbursementsIntroPage.tsx b/src/pages/settings/Wallet/WiseGlobalReimbursementsIntroPage.tsx index 89bd5e4425bd..a2208077d5fd 100644 --- a/src/pages/settings/Wallet/WiseGlobalReimbursementsIntroPage.tsx +++ b/src/pages/settings/Wallet/WiseGlobalReimbursementsIntroPage.tsx @@ -1,5 +1,6 @@ import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import ConfirmationPage from '@components/ConfirmationPage'; +import FixedFooter from '@components/FixedFooter'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import Header from '@components/Header'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -72,23 +73,30 @@ function WiseGlobalReimbursementsIntroPage({route}: WiseGlobalReimbursementsIntr - { - // Starting onboarding for any account retires both banners for good - dismissProductTraining(CONST.WISE_GLOBAL_REIMBURSEMENTS_WALLET_BANNER); - dismissProductTraining(CONST.WISE_GLOBAL_REIMBURSEMENTS_WORKSPACE_BANNER); - }} - /> + + + + {translate('walletPage.wiseGlobalReimbursementsIntro.title')} + {translate('walletPage.wiseGlobalReimbursementsIntro.subtitle')} + + + + { + // Starting onboarding for any account retires both banners for good + dismissProductTraining(CONST.WISE_GLOBAL_REIMBURSEMENTS_WALLET_BANNER); + dismissProductTraining(CONST.WISE_GLOBAL_REIMBURSEMENTS_WORKSPACE_BANNER); + }} + /> + + ); diff --git a/src/pages/workspace/WorkspaceConfirmationSuccessPage.tsx b/src/pages/workspace/WorkspaceConfirmationSuccessPage.tsx index 6da83ce792a0..3ab5e1333431 100644 --- a/src/pages/workspace/WorkspaceConfirmationSuccessPage.tsx +++ b/src/pages/workspace/WorkspaceConfirmationSuccessPage.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -25,11 +25,10 @@ function WorkspaceConfirmationSuccessPage() { title={translate('workspace.new.confirmWorkspace')} onBackButtonPress={closePage} /> - diff --git a/src/pages/workspace/companyCards/BankConnection/index.native.tsx b/src/pages/workspace/companyCards/BankConnection/index.native.tsx index f0e0ea84804e..43a6d5f3da22 100644 --- a/src/pages/workspace/companyCards/BankConnection/index.native.tsx +++ b/src/pages/workspace/companyCards/BankConnection/index.native.tsx @@ -1,6 +1,6 @@ import ActivityIndicator from '@components/ActivityIndicator'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -217,13 +217,11 @@ function BankConnection({policyID, feed, title}: BankConnectionProps) { /> )} {hasImportError && ( - Navigation.goBack(ROUTES.WORKSPACE_COMPANY_CARDS.getRoute(policyID))} /> diff --git a/src/pages/workspace/companyCards/BankConnection/index.tsx b/src/pages/workspace/companyCards/BankConnection/index.tsx index a01e820cdaa1..0d649ed6cc9c 100644 --- a/src/pages/workspace/companyCards/BankConnection/index.tsx +++ b/src/pages/workspace/companyCards/BankConnection/index.tsx @@ -1,7 +1,7 @@ import ActivityIndicator from '@components/ActivityIndicator'; import BlockingView from '@components/BlockingViews/BlockingView'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; @@ -205,13 +205,11 @@ function BankConnection({policyID, feed, title}: BankConnectionProps) { const getContent = () => { if (hasImportError) { return ( - Navigation.closeRHPFlow()} /> diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsErrorConfirmation.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsErrorConfirmation.tsx index 7cbf7e0a8633..f01bd924eec8 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsErrorConfirmation.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsErrorConfirmation.tsx @@ -1,4 +1,5 @@ import ConfirmationPage from '@components/ConfirmationPage'; +import FixedFooter from '@components/FixedFooter'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; @@ -87,34 +88,40 @@ function WorkspaceCompanyCardsErrorConfirmation({policyID, newFeed, errorMessage }; return ( - - {!!errorMessage && `${errorMessage} `} - {translate('workspace.moreFeatures.companyCards.bankConnectionDescription')}{' '} - - {translate('workspace.moreFeatures.companyCards.connectWithPlaid')} - {' '} - {translate('common.or')}{' '} - - {translate('workspace.moreFeatures.companyCards.connectWithExpensifyCard')} - - - } - illustration={illustrations.BrokenCompanyCardBankConnection} - shouldShowButton - illustrationStyle={styles.errorStateCardIllustration} - onButtonPress={onButtonPress} - buttonText={translate('common.buttonConfirm')} - containerStyle={styles.h100} - /> + + + + {translate('workspace.moreFeatures.companyCards.bankConnectionError')} + + + {!!errorMessage && `${errorMessage} `} + {translate('workspace.moreFeatures.companyCards.bankConnectionDescription')}{' '} + + {translate('workspace.moreFeatures.companyCards.connectWithPlaid')} + {' '} + {translate('common.or')}{' '} + + {translate('workspace.moreFeatures.companyCards.connectWithExpensifyCard')} + + + + + + + + ); } diff --git a/src/pages/workspace/downgrade/DowngradeConfirmation.tsx b/src/pages/workspace/downgrade/DowngradeConfirmation.tsx index f1ac3f0ce609..fc90728acffb 100644 --- a/src/pages/workspace/downgrade/DowngradeConfirmation.tsx +++ b/src/pages/workspace/downgrade/DowngradeConfirmation.tsx @@ -1,10 +1,10 @@ import ConfirmationPage from '@components/ConfirmationPage'; +import FixedFooter from '@components/FixedFooter'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; -import useThemeStyles from '@hooks/useThemeStyles'; import {hasOtherControlWorkspaces as hasOtherControlWorkspacesPolicyUtils} from '@libs/PolicyUtils'; @@ -23,7 +23,6 @@ type Props = { function DowngradeConfirmation({onConfirmDowngrade, policyID}: Props) { const {translate} = useLocalize(); - const styles = useThemeStyles(); const illustrations = useMemoizedLazyIllustrations(['MushroomTopHat']); const {login} = useCurrentUserPersonalDetails(); const selector = useCallback( @@ -36,15 +35,19 @@ function DowngradeConfirmation({onConfirmDowngrade, policyID}: Props) { const hasOtherControlWorkspaces = hasOtherControlWorkspacesPolicyUtils(adminPolicies, policyID); return ( - + + + + {translate('workspace.downgrade.completed.headline')} + {hasOtherControlWorkspaces && {translate('workspace.downgrade.completed.description')}} + + + + + ); } diff --git a/src/pages/workspace/members/DynamicWorkspaceOwnerChangeSuccessPage.tsx b/src/pages/workspace/members/DynamicWorkspaceOwnerChangeSuccessPage.tsx index ab282547789f..2525d7b60eaa 100644 --- a/src/pages/workspace/members/DynamicWorkspaceOwnerChangeSuccessPage.tsx +++ b/src/pages/workspace/members/DynamicWorkspaceOwnerChangeSuccessPage.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import LottieAnimations from '@components/LottieAnimations'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -58,12 +58,11 @@ function DynamicWorkspaceOwnerChangeSuccessPage({route}: DynamicWorkspaceOwnerCh title={translate('workspace.changeOwner.changeOwnerPageTitle')} onBackButtonPress={closePage} /> - diff --git a/src/pages/workspace/receiptPartners/DynamicInviteReceiptPartnerPolicyPage.tsx b/src/pages/workspace/receiptPartners/DynamicInviteReceiptPartnerPolicyPage.tsx index 36c2c65450ed..04eb1be88d8e 100644 --- a/src/pages/workspace/receiptPartners/DynamicInviteReceiptPartnerPolicyPage.tsx +++ b/src/pages/workspace/receiptPartners/DynamicInviteReceiptPartnerPolicyPage.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; @@ -192,12 +192,11 @@ function DynamicInviteReceiptPartnerPolicyPage({route}: DynamicInviteReceiptPart title={translate('workspace.receiptPartners.uber.allSet')} onBackButtonPress={() => Navigation.goBack(backPath)} /> - Navigation.goBack(backPath)} descriptionStyle={styles.colorMuted} diff --git a/src/pages/workspace/upgrade/UpgradeConfirmation.tsx b/src/pages/workspace/upgrade/UpgradeConfirmation.tsx index 9733dfb85fc9..48235ec02faf 100644 --- a/src/pages/workspace/upgrade/UpgradeConfirmation.tsx +++ b/src/pages/workspace/upgrade/UpgradeConfirmation.tsx @@ -1,4 +1,5 @@ import ConfirmationPage from '@components/ConfirmationPage'; +import FixedFooter from '@components/FixedFooter'; import RenderHTML from '@components/RenderHTML'; import Text from '@components/Text'; @@ -71,14 +72,19 @@ function UpgradeConfirmation({policyName, planName, afterUpgradeAcknowledged, is }, [isCategorizing, isReporting, translate]); return ( - + + + + {heading} + {description} + + + + + ); } diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerSuccessPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerSuccessPage.tsx index 557f8d109bdc..126e209c3488 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPayerSuccessPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPayerSuccessPage.tsx @@ -1,4 +1,4 @@ -import ConfirmationPage from '@components/ConfirmationPage'; +import ConfirmationPageDefault from '@components/ConfirmationPage/composed/ConfirmationPageDefault'; import ScrollView from '@components/ScrollView'; import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; @@ -37,16 +37,14 @@ function WorkspaceWorkflowsPayerSuccessPage() { addBottomSafeAreaPadding contentContainerStyle={styles.flexGrow1} > - ); diff --git a/tests/ui/components/ConfirmationPageTest.tsx b/tests/ui/components/ConfirmationPageTest.tsx index ac6d11ce3976..351473ff3455 100644 --- a/tests/ui/components/ConfirmationPageTest.tsx +++ b/tests/ui/components/ConfirmationPageTest.tsx @@ -1,7 +1,6 @@ import {render} from '@testing-library/react-native'; import ConfirmationPage from '@components/ConfirmationPage'; -import type {ConfirmationPageProps} from '@components/ConfirmationPage'; import Lottie from '@components/Lottie'; import React from 'react'; @@ -14,17 +13,12 @@ jest.mock('@components/Lottie', () => ({ default: jest.fn(() => null), })); -function renderConfirmationAndGetWebStyle(illustrationStyle?: ConfirmationPageProps['illustrationStyle']) { - render( - , - ); +function renderConfirmationAndGetWebStyle(illustrationStyle?: React.ComponentProps['illustrationStyle']) { + render(); const lottieProps = jest.mocked(Lottie).mock.calls.at(-1)?.at(0); expect(lottieProps).toBeDefined(); if (!lottieProps) { - throw new Error('ConfirmationPage did not render Lottie'); + throw new Error('ConfirmationPage.Illustration did not render Lottie'); } return lottieProps.webStyle; } @@ -64,12 +58,7 @@ describe('ConfirmationPage Lottie web dimensions', () => { const animatedWidth = new Animated.Value(40); // When the shared component receives both animated and supported dimensions. - render( - , - ); + render(); const lottieProps = jest.mocked(Lottie).mock.calls.at(-1)?.at(0); expect(lottieProps).toBeDefined(); // Then only the web width falls back while the native animation keeps its style.