diff --git a/src/ReturnUserExperience/ReturnUserExperience.tsx b/src/ReturnUserExperience/ReturnUserExperience.tsx
index 7e594ef3d7..ae23b12137 100644
--- a/src/ReturnUserExperience/ReturnUserExperience.tsx
+++ b/src/ReturnUserExperience/ReturnUserExperience.tsx
@@ -1,8 +1,9 @@
import React from 'react'
-import { useSelector } from 'react-redux'
+import { useDispatch, useSelector } from 'react-redux'
import styles from './returnUserExperience.module.css'
import RuxInfo from 'src/ReturnUserExperience/RuxInfo'
+import { RuxPhoneNumber } from 'src/ReturnUserExperience/RuxPhoneNumber'
import { Stack } from '@mui/material'
import { Icon } from '@mxenabled/mxui'
@@ -12,6 +13,8 @@ import useAnalyticsEvent from 'src/hooks/useAnalyticsEvent'
import { __ } from 'src/utilities/Intl'
import { AnalyticEvents } from 'src/const/Analytics'
import { RootState } from 'src/redux/Store'
+import { ActionTypes } from 'src/redux/actions/Connect'
+import { selectInitialConfig } from 'src/redux/reducers/configSlice'
import { ClientLogo } from 'src/components/ClientLogo'
export const RUXViews = {
@@ -23,7 +26,10 @@ export const RUXViews = {
export const ReturnUserExperience = React.forwardRef(() => {
const [view, setView] = React.useState<(typeof RUXViews)[keyof typeof RUXViews]>(RUXViews.INFO)
+ const [userEnteredPhone, setUserEnteredPhone] = React.useState('')
const clientGuid = useSelector((state: RootState) => state.profiles.client.guid)
+ const connectConfig = useSelector(selectInitialConfig)
+ const dispatch = useDispatch()
const sendAnalyticsEvent = useAnalyticsEvent()
const handleRuxInfoContinue = () => {
@@ -31,15 +37,21 @@ export const ReturnUserExperience = React.forwardRef(() => {
sendAnalyticsEvent(AnalyticEvents.RUX_INFO_CONTINUE_CLICKED)
setView(RUXViews.PHONE_NUMBER)
}
+ const handleContinueWithoutPhone = () =>
+ dispatch({ type: ActionTypes.RESET_WIDGET_MFA_STEP, payload: connectConfig })
return (
{view !== RUXViews.LIST && (
-
-
-
-
+ {view === RUXViews.INFO && (
+ <>
+
+
+
+
+ >
+ )}
@@ -47,6 +59,18 @@ export const ReturnUserExperience = React.forwardRef(() => {
)}
{view === RUXViews.INFO && }
+
+ {view === RUXViews.PHONE_NUMBER && (
+ {
+ // sendAnalyticsEvent(AnalyticEvents.RUX_PHONE_NUMBER_CONTINUE_CLICKED)
+ setView(RUXViews.OTP)
+ }}
+ setUserEnteredPhone={setUserEnteredPhone}
+ userEnteredPhone={userEnteredPhone}
+ />
+ )}
)
})
diff --git a/src/ReturnUserExperience/RuxPhoneNumber.tsx b/src/ReturnUserExperience/RuxPhoneNumber.tsx
new file mode 100644
index 0000000000..b3023846f3
--- /dev/null
+++ b/src/ReturnUserExperience/RuxPhoneNumber.tsx
@@ -0,0 +1,130 @@
+import React from 'react'
+
+import { useTheme } from '@mui/material'
+import InputAdornment from '@mui/material/InputAdornment'
+import Stack from '@mui/material/Stack'
+import Button from '@mui/material/Button'
+import { Text } from '@mxenabled/mxui'
+import { Link } from '@mui/material'
+
+import { __ } from 'src/utilities/Intl'
+import useAnalyticsPath from 'src/hooks/useAnalyticsPath'
+import { TextField } from 'src/privacy/input'
+import { PageviewInfo } from 'src/const/Analytics'
+import styles from './returnUserExperience.module.css'
+
+export const RuxPhoneNumber = ({
+ handleContinueWithoutPhone,
+ handleRuxContinue,
+ userEnteredPhone,
+ setUserEnteredPhone,
+}: {
+ handleContinueWithoutPhone: () => void
+ handleRuxContinue: () => void
+ userEnteredPhone: string
+ setUserEnteredPhone: (phone: string) => void
+}) => {
+ useAnalyticsPath(...PageviewInfo.CONNECT_RUX_PHONE_NUMBER)
+ const { palette } = useTheme()
+
+ return (
+ <>
+
+
+ {__('Connect faster with your phone number')}
+
+
+ {__('Login or sign up with MX to securely access your saved accounts. ')}
+
+ {__('Learn more about MX.')}
+
+
+
+
+
+
+
+ Phone
+
+
+ +1
+
+
+
+ ),
+ style: {
+ paddingRight: '14px',
+ margin: '40px 0',
+ fontSize: '23px',
+ fontWeight: '400',
+ height: 'auto',
+ maxHeight: '60px',
+ },
+ }}
+ fullWidth={true}
+ name="phoneNumber"
+ onChange={(e: React.ChangeEvent) =>
+ setUserEnteredPhone(e.target.value.replace(/\D/g, '').slice(0, 10))
+ }
+ required={true}
+ value={formatPhone(userEnteredPhone)}
+ />
+
+
+
+ {/* --TR: Full string 'By selecting "Get code", you agree to MX's Terms & Conditions' */}
+ {__('By selecting "Continue", you agree to ')}
+
+ {/* TODO: Do we translate this below? */}
+ {__("MX's Terms & Conditions")}
+
+
+
+
+
+ >
+ )
+}
+
+export default RuxPhoneNumber
+
+const formatPhone = (value: string) => {
+ const digits = value.replace(/\D/g, '').slice(0, 10)
+
+ if (digits.length === 0) return digits
+ if (digits.length <= 3) return `(${digits}`
+ if (digits.length <= 6) return `(${digits.slice(0, 3)}) ${digits.slice(3)}`
+ return `(${digits.slice(0, 3)}) ${digits.slice(3, 6)} - ${digits.slice(6)}`
+}
diff --git a/src/ReturnUserExperience/__tests__/RuxPhoneNumber-test.tsx b/src/ReturnUserExperience/__tests__/RuxPhoneNumber-test.tsx
new file mode 100644
index 0000000000..3b03246f0e
--- /dev/null
+++ b/src/ReturnUserExperience/__tests__/RuxPhoneNumber-test.tsx
@@ -0,0 +1,99 @@
+import React from 'react'
+import { RuxPhoneNumber } from 'src/ReturnUserExperience/RuxPhoneNumber'
+import { render, screen } from 'src/utilities/testingLibrary'
+
+describe('RuxPhoneNumber', () => {
+ it('renders the main heading', () => {
+ render(
+ {}}
+ handleRuxContinue={() => {}}
+ setUserEnteredPhone={() => {}}
+ userEnteredPhone=""
+ />,
+ )
+ const heading = screen.getByText('Connect faster with your phone number')
+ expect(heading).toBeInTheDocument()
+ })
+
+ it('renders the subtitle with a learn more link', () => {
+ render(
+ {}}
+ handleRuxContinue={() => {}}
+ setUserEnteredPhone={() => {}}
+ userEnteredPhone=""
+ />,
+ )
+ const subtitle = screen.getByText(
+ /Login or sign up with MX to securely access your saved accounts./i,
+ )
+ expect(subtitle).toBeInTheDocument()
+
+ const link = screen.getByRole('link', { name: /learn more about mx/i })
+ expect(link).toBeInTheDocument()
+ expect(link).toHaveAttribute('href', 'https://mx.com/learn-more')
+ expect(link).toHaveAttribute('target', '_blank')
+ expect(link).toHaveAttribute('rel', 'noopener noreferrer')
+ })
+
+ it('renders the phone number input with correct label', () => {
+ render(
+ {}}
+ handleRuxContinue={() => {}}
+ setUserEnteredPhone={() => {}}
+ userEnteredPhone=""
+ />,
+ )
+ const phoneInput = screen.getByRole('textbox')
+ expect(phoneInput).toBeInTheDocument()
+ })
+
+ it('renders the continue without phone number button', () => {
+ render(
+ {}}
+ handleRuxContinue={() => {}}
+ setUserEnteredPhone={() => {}}
+ userEnteredPhone=""
+ />,
+ )
+ const continueWithoutPhoneButton = screen.getByRole('button', {
+ name: 'Continue without phone number',
+ })
+ expect(continueWithoutPhoneButton).toBeInTheDocument()
+ })
+
+ it('calls handleContinueWithoutPhone when the continue without phone number button is clicked', () => {
+ const handleContinueWithoutPhoneMock = vi.fn()
+ render(
+ {}}
+ setUserEnteredPhone={() => {}}
+ userEnteredPhone=""
+ />,
+ )
+ const continueWithoutPhoneButton = screen.getByRole('button', {
+ name: 'Continue without phone number',
+ })
+ continueWithoutPhoneButton.click()
+ expect(handleContinueWithoutPhoneMock).toHaveBeenCalledTimes(1)
+ })
+
+ it('calls handleRuxContinue when the continue button is clicked', () => {
+ const handleRuxContinueMock = vi.fn()
+ render(
+ {}}
+ handleRuxContinue={handleRuxContinueMock}
+ setUserEnteredPhone={() => {}}
+ userEnteredPhone=""
+ />,
+ )
+ const continueButton = screen.getByRole('button', { name: 'Continue' })
+ continueButton.click()
+ expect(handleRuxContinueMock).toHaveBeenCalledTimes(1)
+ })
+})
diff --git a/src/ReturnUserExperience/returnUserExperience.module.css b/src/ReturnUserExperience/returnUserExperience.module.css
index fc76276baf..0e462743a7 100644
--- a/src/ReturnUserExperience/returnUserExperience.module.css
+++ b/src/ReturnUserExperience/returnUserExperience.module.css
@@ -71,6 +71,6 @@
.titleContainer {
padding-top: 16px;
- padding-right: 16px;
- padding-left: 16px;
+ margin-right: -8px;
+ margin-left: -8px;
}
diff --git a/src/const/Analytics.js b/src/const/Analytics.js
index 03405a3d45..f73a55b8ce 100644
--- a/src/const/Analytics.js
+++ b/src/const/Analytics.js
@@ -117,6 +117,7 @@ export const PageviewInfo = {
CONNECT_OAUTH_ERROR: ['Connect Oauth Error', '/oauth_error'],
CONNECT_NO_ELIGIBLE_ACCOUNTS: ['Connect No Eligible Accounts', '/no_eligible_accounts'],
CONNECT_RUX_INFO: ['Connect RUX Info', '/rux_info'],
+ CONNECT_RUX_PHONE_NUMBER: ['Connect RUX Phone Number', '/rux_phone_number'],
CONNECT_SEARCH: ['Connect Search', '/search'],
CONNECT_SEARCH_FAILED: ['Connect Search Failed', '/search_failed'],
CONNECT_SEARCH_NO_RESULTS: ['Connect Search No Results', '/no_results'],
diff --git a/src/const/language/es.json b/src/const/language/es.json
index e047c29e00..657366ed0e 100644
--- a/src/const/language/es.json
+++ b/src/const/language/es.json
@@ -433,6 +433,11 @@
"Connect your accounts": "Conecta tus cuentas",
"%1 uses MX to connect your accounts. ": "%1 usa MX para conectar tus cuentas. ",
"Learn more about MX.": "Obtén más información sobre MX.",
+ "Connect faster with your phone number": "Conéctate más rápido con tu número de teléfono",
+ "Login or sign up with MX to securely access your saved accounts. ": "Inicia sesión o regístrate con MX para acceder de forma segura a tus cuentas guardadas. ",
+ "By selecting \"Continue\", you agree to ": "Al seleccionar \"Continuar\", aceptas ",
+ "MX's Terms & Conditions": "los Términos y Condiciones de MX",
+ "Continue without phone number": "Continuar sin número de teléfono",
"connect/disclosure/button\u0004Continue": "Continuar",
"connect/disclosure/policy/text\u0004By clicking Continue, you agree to the ": "Al hacer clic en Continuar, tu aceptas la ",
"connect/disclosure/policy/link\u0004MX Privacy Policy.": "Política de privacidad de Money Experience.",
diff --git a/src/const/language/es.po b/src/const/language/es.po
index 351207f983..dfc041ec9d 100644
--- a/src/const/language/es.po
+++ b/src/const/language/es.po
@@ -169,9 +169,11 @@ msgstr "Continuar"
#: src/components/support/GeneralSupport.js
#: src/components/support/SupportSuccess.js
#: src/components/ConnectSuccessSurvey.tsx src/components/FindAccountInfo.js
-#: src/components/LeavingNoticeFlat.js src/ReturnUserExperience/RuxInfo.tsx
-#: src/views/mfa/DefaultMFA.js src/views/mfa/MFAImages.js
-#: src/views/mfa/MFAOptions.js src/views/microdeposits/VerifyDeposits.js
+#: src/components/LeavingNoticeFlat.js
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+#: src/ReturnUserExperience/RuxInfo.tsx src/views/mfa/DefaultMFA.js
+#: src/views/mfa/MFAImages.js src/views/mfa/MFAOptions.js
+#: src/views/microdeposits/VerifyDeposits.js
#: src/views/microdeposits/HowItWorks.js
#: src/views/microdeposits/MicrodepositErrors.js
#: src/views/microdeposits/PersonalInfoForm.js
@@ -2165,7 +2167,8 @@ msgstr "Privado"
#: src/ReturnUserExperience/RuxInfo.tsx
msgid "We never sell your phone number or use it for marketing."
-msgstr "Nunca vendemos tu número de teléfono ni lo usamos con fines de mercadotecnia."
+msgstr ""
+"Nunca vendemos tu número de teléfono ni lo usamos con fines de mercadotecnia."
#: src/ReturnUserExperience/RuxInfo.tsx
msgid "Connect your accounts"
@@ -2175,6 +2178,30 @@ msgstr "Conecta tus cuentas"
msgid "%1 uses MX to connect your accounts. "
msgstr "%1 usa MX para conectar tus cuentas. "
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
#: src/ReturnUserExperience/RuxInfo.tsx
msgid "Learn more about MX."
msgstr "Obtén más información sobre MX."
+
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+msgid "Connect faster with your phone number"
+msgstr "Conéctate más rápido con tu número de teléfono"
+
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+msgid "Login or sign up with MX to securely access your saved accounts. "
+msgstr ""
+"Inicia sesión o regístrate con MX para acceder de forma segura a tus cuentas "
+"guardadas. "
+
+#. TR: Full string 'By selecting "Get code", you agree to MX's Terms & Conditions' */}
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+msgid "By selecting \"Continue\", you agree to "
+msgstr "Al seleccionar \"Continuar\", aceptas "
+
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+msgid "MX's Terms & Conditions"
+msgstr "los Términos y Condiciones de MX"
+
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+msgid "Continue without phone number"
+msgstr "Continuar sin número de teléfono"
diff --git a/src/const/language/frCa.json b/src/const/language/frCa.json
index cff752cd1c..cb4129e26b 100644
--- a/src/const/language/frCa.json
+++ b/src/const/language/frCa.json
@@ -436,6 +436,11 @@
"Connect your accounts": "Connectez vos comptes",
"%1 uses MX to connect your accounts. ": "%1 utilise MX pour connecter vos comptes. ",
"Learn more about MX.": "En savoir plus sur MX.",
+ "Connect faster with your phone number": "Connectez-vous plus rapidement avec votre numéro de téléphone",
+ "Login or sign up with MX to securely access your saved accounts. ": "Connectez-vous ou inscrivez-vous avec MX pour accéder en toute sécurité à vos comptes enregistrés. ",
+ "By selecting \"Continue\", you agree to ": "En sélectionnant \"Continuer\", vous acceptez ",
+ "MX's Terms & Conditions": "les conditions générales de MX",
+ "Continue without phone number": "Continuer sans numéro de téléphone",
"connect/disclosure/policy/text\u0004By clicking Continue, you agree to the ": "En cliquant sur Continuer, vous acceptez la ",
"connect/disclosure/policy/link\u0004MX Privacy Policy.": "Politique de confidentialité de MX.",
"connect/disclosure/policy/link\u0004MX Privacy Policy": "Politique de confidentialité de MX.",
diff --git a/src/const/language/frCa.po b/src/const/language/frCa.po
index 7fac8eb59d..a3cc46c401 100644
--- a/src/const/language/frCa.po
+++ b/src/const/language/frCa.po
@@ -69,9 +69,11 @@ msgstr "Continuer"
#: src/components/support/GeneralSupport.js
#: src/components/support/SupportSuccess.js
#: src/components/ConnectSuccessSurvey.tsx src/components/FindAccountInfo.js
-#: src/components/LeavingNoticeFlat.js src/ReturnUserExperience/RuxInfo.tsx
-#: src/views/mfa/DefaultMFA.js src/views/mfa/MFAImages.js
-#: src/views/mfa/MFAOptions.js src/views/microdeposits/VerifyDeposits.js
+#: src/components/LeavingNoticeFlat.js
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+#: src/ReturnUserExperience/RuxInfo.tsx src/views/mfa/DefaultMFA.js
+#: src/views/mfa/MFAImages.js src/views/mfa/MFAOptions.js
+#: src/views/microdeposits/VerifyDeposits.js
#: src/views/microdeposits/HowItWorks.js
#: src/views/microdeposits/MicrodepositErrors.js
#: src/views/microdeposits/PersonalInfoForm.js
@@ -2258,7 +2260,9 @@ msgstr "Privé"
#: src/ReturnUserExperience/RuxInfo.tsx
msgid "We never sell your phone number or use it for marketing."
-msgstr "Nous ne vendons jamais votre numéro de téléphone ni ne l’utilisons pour le marketing."
+msgstr ""
+"Nous ne vendons jamais votre numéro de téléphone ni ne l’utilisons pour le "
+"marketing."
#: src/ReturnUserExperience/RuxInfo.tsx
msgid "Connect your accounts"
@@ -2268,6 +2272,30 @@ msgstr "Connectez vos comptes"
msgid "%1 uses MX to connect your accounts. "
msgstr "%1 utilise MX pour connecter vos comptes. "
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
#: src/ReturnUserExperience/RuxInfo.tsx
msgid "Learn more about MX."
msgstr "En savoir plus sur MX."
+
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+msgid "Connect faster with your phone number"
+msgstr "Connectez-vous plus rapidement avec votre numéro de téléphone"
+
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+msgid "Login or sign up with MX to securely access your saved accounts. "
+msgstr ""
+"Connectez-vous ou inscrivez-vous avec MX pour accéder en toute sécurité à "
+"vos comptes enregistrés. "
+
+#. TR: Full string 'By selecting "Get code", you agree to MX's Terms & Conditions' */}
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+msgid "By selecting \"Continue\", you agree to "
+msgstr "En sélectionnant \"Continuer\", vous acceptez "
+
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+msgid "MX's Terms & Conditions"
+msgstr "les conditions générales de MX"
+
+#: src/ReturnUserExperience/RuxPhoneNumber.tsx
+msgid "Continue without phone number"
+msgstr "Continuer sans numéro de téléphone"