From 1d8681b955c3c72c7f98c9bd67d6c11863b201b8 Mon Sep 17 00:00:00 2001 From: leora Date: Tue, 24 Oct 2023 11:22:39 -0600 Subject: [PATCH 01/41] feat(sofi): add header logo --- .../src/Images/Images.ts | 2 + .../src/Images/img/bc-sofi-logo.svg | 21 ++ .../layouts/Auth/components/Header/index.tsx | 16 +- .../src/layouts/Wallet/index.tsx | 8 + .../components/SofiSignupCard/index.tsx | 333 ++++++++++++++++++ .../src/scenes/app.tsx | 5 + 6 files changed, 380 insertions(+), 5 deletions(-) create mode 100644 packages/blockchain-info-components/src/Images/img/bc-sofi-logo.svg create mode 100644 packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupCard/index.tsx diff --git a/packages/blockchain-info-components/src/Images/Images.ts b/packages/blockchain-info-components/src/Images/Images.ts index a5560702bd0..5b0097f78d1 100644 --- a/packages/blockchain-info-components/src/Images/Images.ts +++ b/packages/blockchain-info-components/src/Images/Images.ts @@ -37,6 +37,7 @@ import barChart from './img/bar-chart.svg' import blockchainIcon from './img/bc-icon.svg' import blockchainLogo from './img/bc-logo.svg' import blockchainLogoCircle from './img/bc-logo-circle.svg' +import blockchainSofiLogo from './img/bc-sofi-logo.svg' import bgBannerPattern from './img/bg-banner-pattern.svg' import bgBannerPatternLg from './img/bg-banner-pattern-lg.svg' import bgModalGradient from './img/bg-modal-gradient.svg' @@ -239,6 +240,7 @@ const Images = { 'blockchain-logo': blockchainLogo, 'blockchain-logo-circle': blockchainLogoCircle, 'blockchain-silver': blockchainSilver, + 'blockchain-sofi-logo': blockchainSofiLogo, 'blue-verified': blueVerified, 'btc-clock': btcClock, 'btc-graph': btcGraph, diff --git a/packages/blockchain-info-components/src/Images/img/bc-sofi-logo.svg b/packages/blockchain-info-components/src/Images/img/bc-sofi-logo.svg new file mode 100644 index 00000000000..952221dbfeb --- /dev/null +++ b/packages/blockchain-info-components/src/Images/img/bc-sofi-logo.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx b/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx index 69d8a2a8d91..cc5751fbbe2 100644 --- a/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx @@ -8,6 +8,7 @@ import { media } from 'services/styles' const qsParams = new URLSearchParams(window.location.hash) const isLatam = qsParams.has('latam') +const isSofi = window.location.hash === '#/sofi' const NavbarStyled = styled(Public)<{ authProduct: string }>` padding: 0 16px; @@ -37,6 +38,13 @@ const BlockchainLogoImage = styled(Image)` width: 200px; `} ` +const BlockchainSofiLogoImage = styled(Image)` + width: 375px; + display: block; + ${media.tablet` + width: 200px; + `} +` const AuthBrand = styled.div` display: flex; flex-direction: row; @@ -57,11 +65,9 @@ const Header = (props) => { - {isLatam ? ( - - ) : ( - - )} + {isLatam && }{' '} + {isSofi && } + {!isLatam && !isSofi && } diff --git a/packages/blockchain-wallet-v4-frontend/src/layouts/Wallet/index.tsx b/packages/blockchain-wallet-v4-frontend/src/layouts/Wallet/index.tsx index fd265e968bc..58ed5b2db4b 100644 --- a/packages/blockchain-wallet-v4-frontend/src/layouts/Wallet/index.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/layouts/Wallet/index.tsx @@ -21,8 +21,16 @@ const WalletLayoutContainer: FC = ({ removeContentPadding, ...rest }: Props) => { + let isValidRoute = true + let coin + document.title = 'Blockchain.com Wallet' + if (path.includes('/transactions')) { + coin = computedMatch.params.coin + if (!window.coins[coin]) isValidRoute = false + } + // IMPORTANT: do not allow routes to load until window.coins is loaded if (!isCoinDataLoaded) return diff --git a/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupCard/index.tsx b/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupCard/index.tsx new file mode 100644 index 00000000000..bc3ec8aa54c --- /dev/null +++ b/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupCard/index.tsx @@ -0,0 +1,333 @@ +import React, { useEffect } from 'react' +import { FormattedMessage } from 'react-intl' +import { Field, InjectedFormProps } from 'redux-form' +import styled from 'styled-components' + +import { CountryScope } from '@core/types' +import { Button, HeartbeatLoader, Text, TextGroup } from 'blockchain-info-components' +import CheckBox from 'components/Form/CheckBox' +import Form from 'components/Form/Form' +import FormError from 'components/Form/FormError' +import FormGroup from 'components/Form/FormGroup' +import FormItem from 'components/Form/FormItem' +import FormLabel from 'components/Form/FormLabel' +import PasswordBox from 'components/Form/PasswordBox' +import SelectBox from 'components/Form/SelectBox' +import TextBox from 'components/Form/TextBox' +import Terms from 'components/Terms' +import { CountryType, SignUpGoalDataType, StateType } from 'data/types' +import { useCountryList, useUSStateList } from 'hooks' +import { + required, + stringContainsLowercaseLetter, + stringContainsNumber, + stringContainsSpecialChar, + stringContainsUppercaseLetter, + stringLengthBetween, + validEmail, + validPasswordConfirmation, + validStrongPassword +} from 'services/forms' +import { applyToUpperCase } from 'services/forms/normalizers' + +import { SIGNUP_FORM } from '../..' +import { SubviewProps } from '../../types' +import ContinueOnPhone from '../SignupForm/ContinueOnPhone' + +const StyledForm = styled(Form)` + margin-top: 20px; + + > div * { + max-height: 26rem; + transition: all 0.5s ease; + } +` +const FieldWrapper = styled.div` + margin-top: 0.25rem; + margin-right: 0 !important; +` +const FieldWithoutBottomRadius = styled(FormItem)<{ setBorder: boolean }>` + .bc__control { + border-radius: ${(props) => (props.setBorder ? '8px 8px 0 0 ' : '8px')}; + } + + .bc__menu { + overflow: hidden; + } +` +const FieldWithoutTopRadius = styled(FormItem)<{ setBorder: boolean }>` + .bc__control { + border-radius: ${(props) => (props.setBorder ? '0 0 8px 8px' : '8px')}; + } + .bc__menu { + overflow: hidden; + } +` +const PasswordRequirementText = styled(Text)<{ isValid?: boolean }>` + font-size: 12px; + font-weight: 400; + color: ${(props) => (props.isValid ? props.theme.grey800 : props.theme.red600)}; +` + +const validatePasswordConfirmation = validPasswordConfirmation('password') + +const getCountryElements = (countries: Array) => [ + { + group: '', + items: countries.map((country: CountryType) => ({ + text: country.name, + value: country.code + })) + } +] + +const getStateElements = (states: Array) => [ + { + group: '', + items: states.map((state: StateType) => ({ + text: state.name, + value: state.code + })) + } +] + +const SignupForm = (props: Props) => { + const { + formActions, + formValues, + goals, + initialValues, + invalid, + isFormSubmitting, + isReferralEnabled, + isValidReferralCode, + onCountrySelect, + onSignupSubmit, + setShowModal, + showState + } = props + + const passwordValue = formValues?.password || '' + const referralValue = formValues?.referral || '' + const isStateTexas = formValues?.state === 'US-TX' + + const showReferralError = + referralValue.length > 0 && isValidReferralCode !== undefined && !isValidReferralCode + + const { data: supportedCountries } = useCountryList({ scope: CountryScope.SIGNUP }) + const { data: supportedUSStates } = useUSStateList() + const dataGoal = goals.find((g) => g.name === 'signup') + const { email }: SignUpGoalDataType = dataGoal?.data || {} + + useEffect(() => { + if (email) { + formActions.change(SIGNUP_FORM, 'email', email) + } + }, [formActions, email]) + + if (!supportedCountries?.countries || !supportedUSStates?.states) { + return <> + } + + return ( + + + + + + + + + + + + + + + + + {passwordValue.length > 0 && !!validStrongPassword(passwordValue) && ( +
+ + + {' '} + + + + {', '} + + + + {', '} + + + + {', '} + + + {' '} + + + + + + {' '} + + + . + + +
+ )} +
+ + + + + + + + + + + + + + + + {showState ? ( + + + + ) : null} + {isStateTexas && ( + + + + )} + + {isReferralEnabled && ( + + + + + + + {showReferralError && ( + + + + )} + + + )} + + + + + + + + + +
+ ) +} + +type Props = InjectedFormProps<{}> & SubviewProps & { setShowModal?: (e) => void } + +export default SignupForm diff --git a/packages/blockchain-wallet-v4-frontend/src/scenes/app.tsx b/packages/blockchain-wallet-v4-frontend/src/scenes/app.tsx index 0872519d279..e1a5ad681bb 100644 --- a/packages/blockchain-wallet-v4-frontend/src/scenes/app.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/scenes/app.tsx @@ -188,6 +188,11 @@ const App = ({ component={TwoStepVerification} pageTitle={`${BLOCKCHAIN_TITLE} | Setup 2FA`} /> + Date: Tue, 24 Oct 2023 16:00:48 -0600 Subject: [PATCH 02/41] feat(sofi): signup landing and success page --- .../src/components/Terms/index.tsx | 44 ++- .../src/data/signup/sagas.ts | 3 + .../src/data/signup/slice.ts | 4 +- .../src/data/signup/types.ts | 1 + .../layouts/Auth/components/Header/index.tsx | 2 +- .../src/layouts/Auth/index.tsx | 3 + .../scenes/Signup/SofiSignupSuccess/index.tsx | 51 +++ .../components/SofiSignupCard/index.tsx | 362 +++--------------- .../components/SofiSignupForm/index.tsx | 221 +++++++++++ .../src/scenes/Signup/index.tsx | 11 +- .../src/scenes/app.tsx | 6 + 11 files changed, 391 insertions(+), 317 deletions(-) create mode 100644 packages/blockchain-wallet-v4-frontend/src/scenes/Signup/SofiSignupSuccess/index.tsx create mode 100644 packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupForm/index.tsx diff --git a/packages/blockchain-wallet-v4-frontend/src/components/Terms/index.tsx b/packages/blockchain-wallet-v4-frontend/src/components/Terms/index.tsx index 3f5da04bcd2..8615f8bf8c3 100644 --- a/packages/blockchain-wallet-v4-frontend/src/components/Terms/index.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/components/Terms/index.tsx @@ -4,9 +4,9 @@ import styled from 'styled-components' import { Link, Text } from 'blockchain-info-components' -const TermsContainer = styled.div<{ isCentered?: boolean }>` +const TermsContainer = styled.div<{ inline?: boolean; isCentered?: boolean }>` & > * { - display: inline-block; + display: ${(props) => (props.inline ? 'inline' : 'inline-block')}; } ${(props) => props.isCentered && @@ -15,7 +15,7 @@ const TermsContainer = styled.div<{ isCentered?: boolean }>` `}; ` const Terms = (props) => { - const { company, isCentered = null, recovery } = props + const { company, isCentered = null, recovery, sofi } = props switch (company) { case 'blockchain-kyc': return ( @@ -53,6 +53,44 @@ const Terms = (props) => { ) + case 'sofi': + return ( + + + + + + + +   + + & + +   + + + + . + + ) default: return ( diff --git a/packages/blockchain-wallet-v4-frontend/src/data/signup/sagas.ts b/packages/blockchain-wallet-v4-frontend/src/data/signup/sagas.ts index c47cbdd113e..4fa492f1453 100644 --- a/packages/blockchain-wallet-v4-frontend/src/data/signup/sagas.ts +++ b/packages/blockchain-wallet-v4-frontend/src/data/signup/sagas.ts @@ -383,8 +383,11 @@ export default ({ api, coreSagas, networks }) => { const product = queryParams.get('product') as ProductAuthOptions const platform = queryParams.get('platform') as PlatformTypes const signupRedirect = queryParams.get('redirect') as SignupRedirectTypes + const pathname = yield select(selectors.router.getPathname) + const isSofi = pathname.includes('sofi') yield put( actions.signup.setProductSignupMetadata({ + isSofi, platform, product, referrerUsername, diff --git a/packages/blockchain-wallet-v4-frontend/src/data/signup/slice.ts b/packages/blockchain-wallet-v4-frontend/src/data/signup/slice.ts index b106294ccce..c447c2a09f6 100644 --- a/packages/blockchain-wallet-v4-frontend/src/data/signup/slice.ts +++ b/packages/blockchain-wallet-v4-frontend/src/data/signup/slice.ts @@ -101,8 +101,10 @@ const signupSlice = createSlice({ state.kycReset = action.payload }, setProductSignupMetadata: (state, action: PayloadAction) => { - const { platform, product, referrerUsername, signupRedirect, tuneTid } = action.payload + const { isSofi, platform, product, referrerUsername, signupRedirect, tuneTid } = + action.payload state.productSignupMetadata = { + isSofi, platform: platform?.toUpperCase() as PlatformTypes, product: product?.toUpperCase() as ProductAuthOptions, referrerUsername, diff --git a/packages/blockchain-wallet-v4-frontend/src/data/signup/types.ts b/packages/blockchain-wallet-v4-frontend/src/data/signup/types.ts index 2f4b1f322aa..c52e65ed63d 100644 --- a/packages/blockchain-wallet-v4-frontend/src/data/signup/types.ts +++ b/packages/blockchain-wallet-v4-frontend/src/data/signup/types.ts @@ -8,6 +8,7 @@ export enum SignupRedirectTypes { } export type ProductSignupMetadata = { + isSofi?: boolean platform?: PlatformTypes product?: ProductAuthOptions referrerUsername?: string diff --git a/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx b/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx index cc5751fbbe2..da024d75ac4 100644 --- a/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx @@ -39,7 +39,7 @@ const BlockchainLogoImage = styled(Image)` `} ` const BlockchainSofiLogoImage = styled(Image)` - width: 375px; + width: 375 px; display: block; ${media.tablet` width: 200px; diff --git a/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/index.tsx b/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/index.tsx index 733fde8c8ea..bbfc305fcb5 100644 --- a/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/index.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/index.tsx @@ -66,6 +66,9 @@ const ContentContainer = styled.div` max-width: 100%; box-sizing: border-box; margin: 0 16px; + ${media.mobile` + margin: 0; +`} ` const AuthLayoutContainer = ({ diff --git a/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/SofiSignupSuccess/index.tsx b/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/SofiSignupSuccess/index.tsx new file mode 100644 index 00000000000..4b39cf37adb --- /dev/null +++ b/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/SofiSignupSuccess/index.tsx @@ -0,0 +1,51 @@ +import React from 'react' +import { FormattedMessage } from 'react-intl' +import { useDispatch } from 'react-redux' +import styled from 'styled-components' + +import { Button, Image, Text } from 'blockchain-info-components' +import { Wrapper } from 'components/Public' +import { isMobile } from 'services/styles' + +const ContentWrapper = styled.div` + display: flex; + text-align: center; + align-items: center; + flex-direction: column; +` + +const SofiSuccess = () => { + // Add check here to make sure that there is wallet data + // route should navigate to login if there's no wallet data + const sofiWalletRedirect = () => {} + return ( + + + + + + + + + + + + + + ) +} + +export default SofiSuccess diff --git a/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupCard/index.tsx b/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupCard/index.tsx index bc3ec8aa54c..70f9ac66937 100644 --- a/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupCard/index.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupCard/index.tsx @@ -1,333 +1,77 @@ -import React, { useEffect } from 'react' +import React, { useState } from 'react' import { FormattedMessage } from 'react-intl' -import { Field, InjectedFormProps } from 'redux-form' +import { text } from 'express' +import { InjectedFormProps } from 'redux-form' import styled from 'styled-components' -import { CountryScope } from '@core/types' -import { Button, HeartbeatLoader, Text, TextGroup } from 'blockchain-info-components' -import CheckBox from 'components/Form/CheckBox' -import Form from 'components/Form/Form' -import FormError from 'components/Form/FormError' -import FormGroup from 'components/Form/FormGroup' -import FormItem from 'components/Form/FormItem' -import FormLabel from 'components/Form/FormLabel' -import PasswordBox from 'components/Form/PasswordBox' -import SelectBox from 'components/Form/SelectBox' -import TextBox from 'components/Form/TextBox' -import Terms from 'components/Terms' -import { CountryType, SignUpGoalDataType, StateType } from 'data/types' -import { useCountryList, useUSStateList } from 'hooks' -import { - required, - stringContainsLowercaseLetter, - stringContainsNumber, - stringContainsSpecialChar, - stringContainsUppercaseLetter, - stringLengthBetween, - validEmail, - validPasswordConfirmation, - validStrongPassword -} from 'services/forms' -import { applyToUpperCase } from 'services/forms/normalizers' +import { Badge, Button, HeartbeatLoader, Text, TextGroup } from 'blockchain-info-components' +import { PlatformTypes } from 'data/types' +import { isMobile, media } from 'services/styles' -import { SIGNUP_FORM } from '../..' import { SubviewProps } from '../../types' -import ContinueOnPhone from '../SignupForm/ContinueOnPhone' - -const StyledForm = styled(Form)` - margin-top: 20px; - - > div * { - max-height: 26rem; - transition: all 0.5s ease; +import { Card, CardInfo, CardTitle, CardWrapper, InfoItem, InfoTitle, PaddingWrapper } from '..' +import QRsModal, { QRModalType } from '../SignupForm/QRsModal' +import SofiSignupForm from '../SofiSignupForm' + +const Bottom = styled.div` + margin: 2rem 0 0; + > a { + margin: 0 8px; } ` -const FieldWrapper = styled.div` - margin-top: 0.25rem; - margin-right: 0 !important; -` -const FieldWithoutBottomRadius = styled(FormItem)<{ setBorder: boolean }>` - .bc__control { - border-radius: ${(props) => (props.setBorder ? '8px 8px 0 0 ' : '8px')}; - } - .bc__menu { - overflow: hidden; - } -` -const FieldWithoutTopRadius = styled(FormItem)<{ setBorder: boolean }>` - .bc__control { - border-radius: ${(props) => (props.setBorder ? '0 0 8px 8px' : '8px')}; - } - .bc__menu { - overflow: hidden; - } -` -const PasswordRequirementText = styled(Text)<{ isValid?: boolean }>` - font-size: 12px; - font-weight: 400; - color: ${(props) => (props.isValid ? props.theme.grey800 : props.theme.red600)}; +const LinkAccountSpacer = styled.div` + height: 1rem; ` -const validatePasswordConfirmation = validPasswordConfirmation('password') - -const getCountryElements = (countries: Array) => [ - { - group: '', - items: countries.map((country: CountryType) => ({ - text: country.name, - value: country.code - })) - } -] - -const getStateElements = (states: Array) => [ - { - group: '', - items: states.map((state: StateType) => ({ - text: state.name, - value: state.code - })) - } -] - -const SignupForm = (props: Props) => { +const SofiSignupCard = (props: InjectedFormProps<{}> & SubviewProps) => { const { - formActions, - formValues, - goals, - initialValues, - invalid, isFormSubmitting, - isReferralEnabled, - isValidReferralCode, - onCountrySelect, onSignupSubmit, - setShowModal, - showState - } = props - - const passwordValue = formValues?.password || '' - const referralValue = formValues?.referral || '' - const isStateTexas = formValues?.state === 'US-TX' - - const showReferralError = - referralValue.length > 0 && isValidReferralCode !== undefined && !isValidReferralCode - - const { data: supportedCountries } = useCountryList({ scope: CountryScope.SIGNUP }) - const { data: supportedUSStates } = useUSStateList() - const dataGoal = goals.find((g) => g.name === 'signup') - const { email }: SignUpGoalDataType = dataGoal?.data || {} + showForm, - useEffect(() => { - if (email) { - formActions.change(SIGNUP_FORM, 'email', email) - } - }, [formActions, email]) + toggleSignupFormVisibility + } = props + const buttonSubmit = showForm ? onSignupSubmit : toggleSignupFormVisibility + const showOnlySignup = showForm - if (!supportedCountries?.countries || !supportedUSStates?.states) { - return <> - } + const [showModal, setShowModal] = useState(null) + const closeModal = () => setShowModal(null) return ( - - - - - - - - - - - - - - - - - {passwordValue.length > 0 && !!validStrongPassword(passwordValue) && ( -
- - - {' '} - - + <> + {showModal && } + + + + + - {', '} - - + + - {', '} - - - - {', '} - - - {' '} - - - - - - {' '} - - - . - - -
- )} -
- - - - - - - - - - - - - - - - {showState ? ( - - - - ) : null} - {isStateTexas && ( - - - - )} - - {isReferralEnabled && ( - - - - - - - {showReferralError && ( - - - - )} - - - )} - - - - - - - - - -
+ + + + + + + + + ) } -type Props = InjectedFormProps<{}> & SubviewProps & { setShowModal?: (e) => void } - -export default SignupForm +export default SofiSignupCard diff --git a/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupForm/index.tsx b/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupForm/index.tsx new file mode 100644 index 00000000000..b686affd019 --- /dev/null +++ b/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/components/SofiSignupForm/index.tsx @@ -0,0 +1,221 @@ +import React, { useEffect } from 'react' +import { FormattedMessage } from 'react-intl' +import { Field, InjectedFormProps } from 'redux-form' +import styled from 'styled-components' + +import { CountryScope } from '@core/types' +import { Button, HeartbeatLoader, Text, TextGroup } from 'blockchain-info-components' +import CheckBox from 'components/Form/CheckBox' +import Form from 'components/Form/Form' +import FormError from 'components/Form/FormError' +import FormGroup from 'components/Form/FormGroup' +import FormItem from 'components/Form/FormItem' +import FormLabel from 'components/Form/FormLabel' +import PasswordBox from 'components/Form/PasswordBox' +import SelectBox from 'components/Form/SelectBox' +import TextBox from 'components/Form/TextBox' +import Terms from 'components/Terms' +import { CountryType, SignUpGoalDataType, StateType } from 'data/types' +import { useCountryList, useUSStateList } from 'hooks' +import { + required, + stringContainsLowercaseLetter, + stringContainsNumber, + stringContainsSpecialChar, + stringContainsUppercaseLetter, + stringLengthBetween, + validEmail, + validPasswordConfirmation, + validStrongPassword +} from 'services/forms' +import { applyToUpperCase } from 'services/forms/normalizers' + +import { SIGNUP_FORM } from '../..' +import { SubviewProps } from '../../types' +import ContinueOnPhone from '../SignupForm/ContinueOnPhone' + +const StyledForm = styled(Form)` + margin-top: 20px; + + > div * { + max-height: 26rem; + transition: all 0.5s ease; + } +` +const FieldWrapper = styled.div` + margin-top: 0.25rem; + margin-right: 0 !important; +` + +const PasswordRequirementText = styled(Text)<{ isValid?: boolean }>` + font-size: 12px; + font-weight: 400; + color: ${(props) => (props.isValid ? props.theme.grey800 : props.theme.red600)}; +` + +const validatePasswordConfirmation = validPasswordConfirmation('password') + +const SofiSignupForm = (props: Props) => { + const { + formActions, + formValues, + goals, + initialValues, + invalid, + isFormSubmitting, + onSignupSubmit, + setShowModal + } = props + + const passwordValue = formValues?.password || '' + const isStateTexas = formValues?.state === 'US-TX' + + const dataGoal = goals.find((g) => g.name === 'signup') + const email = 'leora@blockchain.com' + + useEffect(() => { + if (email) { + formActions.change(SIGNUP_FORM, 'email', email) + } + }, [formActions, email]) + + return ( + + + + + + + + + + + + + + + + + {passwordValue.length > 0 && !!validStrongPassword(passwordValue) && ( +
+ + + {' '} + + + + {', '} + + + + {', '} + + + + {', '} + + + {' '} + + + + + + {' '} + + + . + + +
+ )} +
+ + + + + + + + + + {isStateTexas && ( + + + + )} + + + + + + + + + + + +
+ ) +} + +type Props = InjectedFormProps<{}> & SubviewProps & { setShowModal?: (e) => void } + +export default SofiSignupForm diff --git a/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/index.tsx b/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/index.tsx index d8bfdc228fc..5a704c56805 100644 --- a/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/index.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/scenes/Signup/index.tsx @@ -17,6 +17,7 @@ import { ProductAuthMetadata, ProductSignupMetadata } from 'data/types' import BuyGoal from './BuyGoal' import Header from './components/Header' import SignupCard from './components/SignupCard' +import SofiSignupCard from './components/SofiSignupCard' import ExchangeLinkGoal from './ExchangeLinkGoal' import { GoalDataType, SignupFormInitValuesType, SignupFormType } from './types' @@ -118,7 +119,7 @@ class SignupContainer extends React.PureComponent< } render() { - const { formValues, goals, isLoadingR, productAuthMetadata } = this.props + const { formValues, goals, isLoadingR, productAuthMetadata, signupMetadata } = this.props const isFormSubmitting = Remote.Loading.is(isLoadingR) const isUserInUK = productAuthMetadata?.ipCountry === 'GB' const userSelectedUK = formValues?.country === 'GB' @@ -130,6 +131,7 @@ class SignupContainer extends React.PureComponent< const signupInitialValues = (email ? { email } : {}) as SignupFormInitValuesType const isLinkAccountGoal = !!find(propEq('name', 'linkAccount'), goals) const isBuyGoal = !!find(propEq('name', 'buySell'), goals) + const isSofi = signupMetadata?.isSofi const subviewProps = { isFormSubmitting, @@ -155,8 +157,11 @@ class SignupContainer extends React.PureComponent< {isLatam &&
} {isLinkAccountGoal && } {isBuyGoal && } - {!isLinkAccountGoal && !isBuyGoal && !isLatam && } - {!isLinkAccountGoal && !isBuyGoal && isLatam && ( + {isSofi && } + {!isLinkAccountGoal && !isBuyGoal && !isLatam && !isSofi && ( + + )} + {!isLinkAccountGoal && !isBuyGoal && !isSofi && isLatam && ( diff --git a/packages/blockchain-wallet-v4-frontend/src/scenes/app.tsx b/packages/blockchain-wallet-v4-frontend/src/scenes/app.tsx index e1a5ad681bb..8fcfd40af33 100644 --- a/packages/blockchain-wallet-v4-frontend/src/scenes/app.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/scenes/app.tsx @@ -43,6 +43,7 @@ const RecoverWallet = React.lazy(() => import('./RecoverWallet')) const Signup = React.lazy(() => import('./Signup')) const ResetWallet2fa = React.lazy(() => import('./ResetWallet2fa')) const ResetWallet2faToken = React.lazy(() => import('./ResetWallet2faToken')) +const SofiSignupSuccess = React.lazy(() => import('./Signup/SofiSignupSuccess')) // need to be authed to see this, but uses public layout const ContinueOnPhone = React.lazy(() => import('./ContinueOnPhone')) const TwoStepVerification = React.lazy(() => import('./TwoStepVerification')) @@ -193,6 +194,11 @@ const App = ({ component={Signup} pageTitle={`${BLOCKCHAIN_TITLE} | SoFi Signup`} /> + Date: Wed, 25 Oct 2023 13:13:49 -0600 Subject: [PATCH 03/41] feat(sofi): add landing page --- .../layouts/Auth/components/Header/index.tsx | 9 +- .../src/layouts/Auth/index.tsx | 24 +++-- .../components/SofiSignupCard/index.tsx | 8 +- .../src/scenes/Signup/index.tsx | 2 +- .../src/scenes/SofiLanding/index.tsx | 95 +++++++++++++++++++ .../src/scenes/app.tsx | 18 +++- 6 files changed, 139 insertions(+), 17 deletions(-) create mode 100644 packages/blockchain-wallet-v4-frontend/src/scenes/SofiLanding/index.tsx diff --git a/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx b/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx index da024d75ac4..9b2e17afe79 100644 --- a/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/components/Header/index.tsx @@ -4,11 +4,11 @@ import styled from 'styled-components' import { Image, Link } from 'blockchain-info-components' import Announcements from 'components/Announcements' import { Brand, Public } from 'components/Navbar' -import { media } from 'services/styles' +import { isMobile, media } from 'services/styles' const qsParams = new URLSearchParams(window.location.hash) const isLatam = qsParams.has('latam') -const isSofi = window.location.hash === '#/sofi' +const isSofi = window.location.hash === '#/signup/sofi' const NavbarStyled = styled(Public)<{ authProduct: string }>` padding: 0 16px; @@ -42,7 +42,7 @@ const BlockchainSofiLogoImage = styled(Image)` width: 375 px; display: block; ${media.tablet` - width: 200px; + width: 275px; `} ` const AuthBrand = styled.div` @@ -59,9 +59,10 @@ const HeaderLink = styled(Link)` ` const Header = (props) => { + const nabvarHeight = isSofi && isMobile() ? '55px' : '112px' return ( <> - + diff --git a/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/index.tsx b/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/index.tsx index bbfc305fcb5..aac988eb849 100644 --- a/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/index.tsx +++ b/packages/blockchain-wallet-v4-frontend/src/layouts/Auth/index.tsx @@ -8,7 +8,7 @@ import { selectors } from 'data' import { LOGIN_FORM } from 'data/auth/model' import { useDefer3rdPartyScript } from 'hooks' import ErrorBoundary from 'providers/ErrorBoundaryProvider' -import { media } from 'services/styles' +import { isMobile, media } from 'services/styles' import Modals from '../../modals' import Footer from './components/Footer' @@ -16,6 +16,8 @@ import Header from './components/Header' const qsParams = new URLSearchParams(window.location.hash) const isLatam = qsParams.has('latam') +const isSofi = window.location.hash === '#/signup/sofi' +const isSofiOnMobile = isSofi && isMobile() const FooterContainer = styled.div` display: flex; @@ -108,15 +110,17 @@ const AuthLayoutContainer = ({ - -