diff --git a/client-mvp-04/src/components/createAccount/createAccount.scss b/client-mvp-04/src/components/createAccount/createAccount.scss new file mode 100644 index 000000000..f39b79416 --- /dev/null +++ b/client-mvp-04/src/components/createAccount/createAccount.scss @@ -0,0 +1,70 @@ +@import "../../sass/variables"; + +.create-account-container { + padding: 40px 60px; + + .text-field-container { + margin-top: 76px; + } + + .create-account-button { + margin: 50px auto 20px auto; + color: $accent-royal-blue-color; + line-height: 18px; + font-weight: $font-bold; + } + + .error-message { + margin: 25px 10px 10px; + + .redirect-link { + color: $link-accent-color; + } + } +} + +@media (max-height: 896px) { + .create-account-container { + height: calc(100vh - 160px); + } +} + +@media (max-width: 400px) { + .create-account-container { + padding: 25px 52px; + + .create-account-button { + margin: 40px 0 20px auto; + } + + .error-message { + margin: 25px 0 10px; + } + + .text-field-container { + margin-top: 55px; + } + } +} + +@media (max-width: 374px) { + .create-account-container { + height: calc(100vh - 180px); + } +} + +@media (max-width: 350px) { + .create-account-container { + padding: 15px 25px; + + .text-field-container { + margin-top: 25px; + } + .create-account-button { + margin: 15px 0 10px auto; + } + .error-message { + margin: 20px 0 5px; + } + } +} diff --git a/client-mvp-04/src/components/createAccount/createAccountContainer.js b/client-mvp-04/src/components/createAccount/createAccountContainer.js new file mode 100644 index 000000000..286862cfe --- /dev/null +++ b/client-mvp-04/src/components/createAccount/createAccountContainer.js @@ -0,0 +1,52 @@ +import React, { useState } from 'react'; +import CreateAccountView from './createAccountView'; +import { Email } from '../../utils/validation'; +import UserService from '../../services/user.service'; + +const CreateAccountContainer = (props) => { + // Local UI State + const [isDisabled, setIsDisabled] = useState(true); + const [userEmail, setUserEmail] = useState(''); + const [isEmailValid, setIsEmailValid] = useState(false); + const [errorMsgInvalidEmail, setErrorMsgInvalidEmail] = useState(false); + const [errorMsgRegisteredEmail, setErrorMsgRegisteredEmail] = useState(false); + + function handleInputChange(e) { + setErrorMsgInvalidEmail(false); + setErrorMsgRegisteredEmail(false); + const inputValue = e.currentTarget.value.toString(); + inputValue ? setIsDisabled(false) : setIsDisabled(true); + setUserEmail(inputValue); + } + + const handleSubmitForm = async (e) => { + e.preventDefault(); + if (Email.isValid(userEmail)) { + setIsEmailValid(true); + setErrorMsgInvalidEmail(false); + const userData = await UserService.getData(userEmail); + if ( !userData ) { + // user is not registered in app, redirect to dummy page + props.history.push('/page'); + } else { + setErrorMsgRegisteredEmail(true); + } + } else { + setIsEmailValid(false); + setErrorMsgInvalidEmail(true); + } + }; + + return ( + + ); +}; + +export default CreateAccountContainer; diff --git a/client-mvp-04/src/components/createAccount/createAccountView.js b/client-mvp-04/src/components/createAccount/createAccountView.js new file mode 100644 index 000000000..6ccf8e8e9 --- /dev/null +++ b/client-mvp-04/src/components/createAccount/createAccountView.js @@ -0,0 +1,59 @@ +import React from 'react'; +import './createAccount.scss'; +import Button from '../common/button/button'; +import Title from '../common/title/title'; +import Input from '../common/input/input'; +import ErrorMessage from '../common/errorMessage/errorMessage'; +import RedirectLink from '../common/link/link'; + +const CreateAccountView = ({ + handleSubmitForm, + handleInputChange, + isDisabled, + isEmailValid, + errorMsgInvalidEmail, + errorMsgRegisteredEmail, +}) => { + return ( +
+ + + <form + data-testid="create-account-form" + onSubmit={(e) => handleSubmitForm(e)} + > + <Input + dataTestid="create-account-input" + placeholder={'Enter your email'} + type={'email'} + onChange={(e) => handleInputChange(e)} + autoComplete={'email'} + /> + + <Button + type={'submit'} + content={`Create Account`} + className={'create-account-button'} + disabled={isDisabled} + /> + </form> + + {!isEmailValid && errorMsgInvalidEmail ? ( + <ErrorMessage content={'*Please enter a valid email address'} /> + ) : null} + + {errorMsgRegisteredEmail ? ( + <p className={'error-message'}> + *You already have an account for that email address. Want to + <RedirectLink path={'/login'} linkKey={'login'} content={' log in'} /> + ? + </p> + ) : null} + </section> + ); +}; + +export default CreateAccountView; diff --git a/client-mvp-04/src/components/createAccount/createAccountView.test.js b/client-mvp-04/src/components/createAccount/createAccountView.test.js new file mode 100644 index 000000000..cd4f5d783 --- /dev/null +++ b/client-mvp-04/src/components/createAccount/createAccountView.test.js @@ -0,0 +1,35 @@ +import React from 'react'; +import { cleanup, render, screen } from '@testing-library/react'; +import CreateAccountView from './createAccountView'; +import { BrowserRouter } from 'react-router-dom'; + +afterEach(cleanup); + +describe('Create Account', () => { + test('Should render component with props', () => { + const props = { + handleSubmitForm: () => {}, + handleInputChange: () => {}, + isDisabled: true, + isEmailValid: false, + errorMsgInvalidEmail: false, + errorMsgRegisteredEmail: false, + }; + + render( + <CreateAccountView + handleSubmitForm={props.handleSubmitForm} + handleInputChange={props.handleInputChange} + isDisabled={props.isDisabled} + isEmailValid={props.isEmailValid} + errorMsgInvalidEmail={props.errorMsgInvalidEmail} + errorMsgFailedEmail={props.errorMsgRegisteredEmail} + />, + { wrapper: BrowserRouter } + ); + expect(screen.getByTestId('create-account-container')).toBeInTheDocument(); + expect(screen.getByTestId('create-account-form')).toBeInTheDocument(); + expect(screen.getByTestId('create-account-input')).toBeInTheDocument(); + expect(screen.getByText('Create Account')).toBeInTheDocument(); + }); +}); diff --git a/client-mvp-04/src/components/home/home.js b/client-mvp-04/src/components/home/home.js index 760ac133e..c1c691deb 100644 --- a/client-mvp-04/src/components/home/home.js +++ b/client-mvp-04/src/components/home/home.js @@ -18,10 +18,10 @@ const Home = () => { <span className="home-text">or</span> <RedirectLink - path={'/page'} + path={'/create-account'} content={'Create account'} className={'accent-link'} - linkKey={'create-account-link'} + linkKey={'create-account'} /> </section> ); diff --git a/client-mvp-04/src/components/home/home.test.js b/client-mvp-04/src/components/home/home.test.js index 92bdd2793..74dac5191 100644 --- a/client-mvp-04/src/components/home/home.test.js +++ b/client-mvp-04/src/components/home/home.test.js @@ -36,7 +36,7 @@ describe('Home', () => { expect(history.location.pathname).toBe('/login'); }); - test('Should navigate to dummy page after click on `Create account` button', () => { + test('Should navigate to create account page after click on `Create account` button', () => { const history = createMemoryHistory(); render( <Router history={history}> @@ -44,8 +44,8 @@ describe('Home', () => { </Router> ); expect(screen.getByText('Create account')).toBeInTheDocument(); - expect(screen.getAllByTestId('link')[1]).toHaveAttribute('href', '/page'); + expect(screen.getAllByTestId('link')[1]).toHaveAttribute('href', '/create-account'); fireEvent.click(screen.getAllByTestId('link')[1]); - expect(history.location.pathname).toBe('/page'); + expect(history.location.pathname).toBe('/create-account'); }); }); diff --git a/client-mvp-04/src/components/login/loginView.js b/client-mvp-04/src/components/login/loginView.js index 294cc1977..4f125111e 100644 --- a/client-mvp-04/src/components/login/loginView.js +++ b/client-mvp-04/src/components/login/loginView.js @@ -43,8 +43,8 @@ const LoginView = ({ <p className={'error-message'}> *We don’t recognize your email address. Need to <RedirectLink - path={'/page'} - linkKey={'create-acc-link'} + path={'/create-account'} + linkKey={'create-account'} content={' create an account'} /> ? diff --git a/client-mvp-04/src/routes/index.js b/client-mvp-04/src/routes/index.js index b7079e61c..6bc957740 100644 --- a/client-mvp-04/src/routes/index.js +++ b/client-mvp-04/src/routes/index.js @@ -1,6 +1,7 @@ import Home from '../components/home/home'; import Dummy from '../components/dummy/dummy'; import Error from '../components/error/error'; +import CreateAccountContainer from '../components/createAccount/createAccountContainer'; import LoginContainer from '../components/login/loginContainer'; import DevUiKit from '../utils/uiKit/uiKit'; @@ -27,6 +28,11 @@ export const Routes = [ key: 'dev-ui-kit', component: DevUiKit, }, + { + path: '/create-account', + key: 'create-account', + component: CreateAccountContainer, + }, { key: 'error', component: Error, diff --git a/client-mvp-04/src/sass/elements/_buttons.scss b/client-mvp-04/src/sass/elements/_buttons.scss index 52f881ef2..e05c677af 100644 --- a/client-mvp-04/src/sass/elements/_buttons.scss +++ b/client-mvp-04/src/sass/elements/_buttons.scss @@ -19,7 +19,9 @@ button { background-color: $concrete-color; } &:disabled { - background-color: $silver-color; + border-color: $silver-color !important; + background-color: $button-primary-bg-color !important; + color: $gray-color !important; cursor: default; } }