diff --git a/components/auth/LoginView.tsx b/components/auth/LoginView.tsx new file mode 100644 index 000000000..e597c9d26 --- /dev/null +++ b/components/auth/LoginView.tsx @@ -0,0 +1,91 @@ +import { FC, useEffect, useState } from 'react' +import { Logo, Modal, Button, Input } from '@components/ui' +import useLogin from '@lib/bigcommerce/use-login' +import { useUI } from '@components/ui/context' +import { validate } from 'email-validator' + +interface Props {} + +const LoginView: FC = () => { + // Form State + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [loading, setLoading] = useState(false) + const [message, setMessage] = useState('') + const [dirty, setDirty] = useState(false) + const [disabled, setDisabled] = useState(false) + const { setModalView, closeModal } = useUI() + + const login = useLogin() + + const handleLogin = async () => { + if (!dirty && !disabled) { + setDirty(true) + handleValidation() + } + + try { + setLoading(true) + setMessage('') + await login({ + email, + password, + }) + setLoading(false) + closeModal() + } catch ({ errors }) { + setMessage(errors[0].message) + setLoading(false) + } + } + + const handleValidation = () => { + // Test for Alphanumeric password + const validPassword = /^(?=.*[a-zA-Z])(?=.*[0-9])/.test(password) + + // Unable to send form unless fields are valid. + if (dirty) { + setDisabled(!validate(email) || password.length < 7 || !validPassword) + } + } + + useEffect(() => { + handleValidation() + }, [email, password, dirty]) + + return ( +
+
+ +
+
+ {message && ( +
{message}
+ )} + + + + + + Don't have an account? + {` `} + setModalView('SIGNUP_VIEW')} + > + Sign Up + + +
+
+ ) +} + +export default LoginView diff --git a/components/auth/SignUpView.tsx b/components/auth/SignUpView.tsx new file mode 100644 index 000000000..f46184bd0 --- /dev/null +++ b/components/auth/SignUpView.tsx @@ -0,0 +1,96 @@ +import { FC, useEffect, useState } from 'react' +import { Logo, Button, Input } from '@components/ui' +import useSignup from '@lib/bigcommerce/use-signup' +import { useUI } from '@components/ui/context' +import { validate } from 'email-validator' + +interface Props {} + +const SignUpView: FC = () => { + // Form State + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [firstName, setFirstName] = useState('') + const [lastName, setLastName] = useState('') + const [loading, setLoading] = useState(false) + const [message, setMessage] = useState('') + const [dirty, setDirty] = useState(false) + const [disabled, setDisabled] = useState(false) + + const signup = useSignup() + const { setModalView, closeModal } = useUI() + + const handleSignup = async () => { + if (!dirty && !disabled) { + setDirty(true) + handleValidation() + } + + try { + setLoading(true) + setMessage('') + await signup({ + email, + firstName, + lastName, + password, + }) + setLoading(false) + closeModal() + } catch ({ errors }) { + setMessage(errors[0].message) + setLoading(false) + } + } + + const handleValidation = () => { + // Test for Alphanumeric password + const validPassword = /^(?=.*[a-zA-Z])(?=.*[0-9])/.test(password) + + // Unable to send form unless fields are valid. + if (dirty) { + setDisabled(!validate(email) || password.length < 7 || !validPassword) + } + } + + useEffect(() => { + handleValidation() + }, [email, password, dirty]) + + return ( +
+
+ +
+
+ {message && ( +
{message}
+ )} + + + + + + + Do you have an account? + {` `} + setModalView('LOGIN_VIEW')} + > + Log In + + +
+
+ ) +} + +export default SignUpView diff --git a/components/auth/index.ts b/components/auth/index.ts new file mode 100644 index 000000000..e0f739bc5 --- /dev/null +++ b/components/auth/index.ts @@ -0,0 +1,2 @@ +export { default as LoginView } from './LoginView' +export { default as SignUpView } from './SignUpView' diff --git a/components/core/Layout/Layout.tsx b/components/core/Layout/Layout.tsx index a1d96eb2c..f76eed877 100644 --- a/components/core/Layout/Layout.tsx +++ b/components/core/Layout/Layout.tsx @@ -1,14 +1,14 @@ -import { FC, useEffect, useState } from 'react' import cn from 'classnames' -import type { Page } from '@lib/bigcommerce/api/operations/get-all-pages' -import { CommerceProvider } from '@lib/bigcommerce' -import { Navbar, Featurebar, Footer } from '@components/core' -import { Container, Sidebar } from '@components/ui' -import Button from '@components/ui/Button' -import { CartSidebarView } from '@components/cart' -import { useUI } from '@components/ui/context' import s from './Layout.module.css' +import React, { FC, useEffect, useState } from 'react' +import { CartSidebarView } from '@components/cart' +import { Container, Sidebar, Button, Modal } from '@components/ui' +import { Navbar, Featurebar, Footer } from '@components/core' +import { LoginView, SignUpView } from '@components/auth' +import { useUI } from '@components/ui/context' import { usePreventScroll } from '@react-aria/overlays' +import { CommerceProvider } from '@lib/bigcommerce' +import type { Page } from '@lib/bigcommerce/api/operations/get-all-pages' interface Props { pageProps: { pages?: Page[] @@ -16,7 +16,13 @@ interface Props { } const Layout: FC = ({ children, pageProps }) => { - const { displaySidebar, displayDropdown, closeSidebar } = useUI() + const { + displaySidebar, + displayModal, + closeSidebar, + closeModal, + modalView, + } = useUI() const [acceptedCookies, setAcceptedCookies] = useState(false) const [hasScrolled, setHasScrolled] = useState(false) @@ -37,7 +43,7 @@ const Layout: FC = ({ children, pageProps }) => { }, []) usePreventScroll({ - isDisabled: !displaySidebar, + isDisabled: !(displaySidebar || displayModal), }) return ( @@ -55,11 +61,13 @@ const Layout: FC = ({ children, pageProps }) => {
{children}