From 743db8f0e366b98f78be10b04501b60df5a752cc Mon Sep 17 00:00:00 2001 From: Amantur Date: Thu, 25 May 2023 08:20:43 +0600 Subject: [PATCH 01/10] Redesign reset-password --- .vscode/settings.json | 5 + client/src/assets/BigSideLogo.js | 24 ++ .../Forms/RecoverPassword/RecoverPassword.js | 146 ++++++------ .../RecoverPassword/RecoverPassword.styles.js | 220 ++++-------------- .../RecoverPassword/RecoverValidation.js | 2 +- .../CustomButton/CustomButon.styles.js | 3 +- 6 files changed, 150 insertions(+), 250 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 client/src/assets/BigSideLogo.js diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..dc8891d54 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + } +} \ No newline at end of file diff --git a/client/src/assets/BigSideLogo.js b/client/src/assets/BigSideLogo.js new file mode 100644 index 000000000..232720e83 --- /dev/null +++ b/client/src/assets/BigSideLogo.js @@ -0,0 +1,24 @@ +const BigSideLogo = () => { + return ( +
+ + + + +
+ ) +} + +export default BigSideLogo diff --git a/client/src/components/Forms/RecoverPassword/RecoverPassword.js b/client/src/components/Forms/RecoverPassword/RecoverPassword.js index dd18b700e..fbf1937f3 100644 --- a/client/src/components/Forms/RecoverPassword/RecoverPassword.js +++ b/client/src/components/Forms/RecoverPassword/RecoverPassword.js @@ -1,106 +1,98 @@ // * Modules import { useState } from 'react' -import { useNavigate, useParams } from 'react-router-dom' -import AppBar from '@mui/material/AppBar' -import Box from '@mui/material/Box' -import Snackbar from '@mui/material/Snackbar' +import { useNavigate } from 'react-router-dom' +import { Formik } from 'formik' -// * Api -import resetPassword from '../../../api/endpoints/reset' -import ArrowLeftReset from '../../../assets/ArrowLeftReset' // * Assets -import SiteLogo from '../../../assets/SiteLogo' +import ArrowNavigateBack from '../../../assets/Arrows/ArrowNavigateBack' +import SiteLogo from '../../../assets/BigSideLogo' import ROUTES from '../../../constants/routes' -import Alert from '../RegistrationPipeline/components/Alert/Alert' +import CustomButton from '../../../shared/components/CustomButton/CustomButton' +import CustomInput from '../../../shared/components/CustomInput/CustomInput' import { - BackButton, - ButtonContainer, + AccountActions, + ButtonsContainer, Container, - NavBar, + Navbar, + NavigationLink, RecoverBox, - RecoverButton, - RecoverContainer, - RecoverInput, - SubTitleText, - TextContainer, - TitleText, + RecoverText, + RecoverTitle, } from './RecoverPassword.styles' import emailValidation from './RecoverValidation' -function RecoverPassword() { +const RecoverPassword2 = () => { const navigate = useNavigate() const [email, setEmail] = useState('') - const [open, setOpen] = useState(false) + const [errors, setErrors] = useState([]) const handleReset = async () => { try { - await emailValidation.validate({ email }) - resetPassword.getRegistrationEmail(email) - navigate(ROUTES.passwordRecoverConfirm, { - replace: true, - state: { email }, - }) + const isValid = await emailValidation.validate({ email }) + + console.log(isValid) } catch (err) { setErrors(err.errors) - setOpen(true) - } - } - - const handleClose = (event, reason) => { - if (reason === 'clickaway') { - return } - setOpen(false) } return ( - - {errors.length > 0 && ( - - - {errors[0]} - - - )} - - - - - - - - + <> + + + + + Log in + Sign up + + - - Recover Password - - - - Enter the email address you used to register and we will send you the instructions - - - setEmail(e.target.value)} required /> - RESET PASSWORD - - - navigate(ROUTES.login, { replace: true })}> - BACK TO SIGN IN - - + Recover Password + + Enter the email you used to register and we will send you link to reset your password + + + {({ values }) => ( + <> + + + + + Reset password + + } + iconPosition="left" + border="2px solid #46A11B" + background="transparent" + fontSize="16px" + onClick={() => navigate(ROUTES.login, { replace: true })} + > + Back to Log in + + + + )} + - - + + ) } -export default RecoverPassword +export default RecoverPassword2 diff --git a/client/src/components/Forms/RecoverPassword/RecoverPassword.styles.js b/client/src/components/Forms/RecoverPassword/RecoverPassword.styles.js index 1d38b8b2a..efb3eb630 100644 --- a/client/src/components/Forms/RecoverPassword/RecoverPassword.styles.js +++ b/client/src/components/Forms/RecoverPassword/RecoverPassword.styles.js @@ -1,201 +1,79 @@ -import Toolbar from '@mui/material/Toolbar' +import { NavLink } from 'react-router-dom' import styled from 'styled-components' -import { device } from '../../../constants/breakpoints' -import { BLACK, GREY, LIME, WHITE } from '../../../constants/colors' - -export const NavBar = styled(Toolbar)` - &.css-hyum1k-MuiToolbar-root { - background: ${LIME.background}; - } -` +import { BLACK, GREEN, GREY, LIME, WHITE } from '../../../constants/colors' export const Container = styled.div` - display: flex; - flex-direction: column; -` - -export const RecoverContainer = styled.div` - width: 100%; - height: 91.4vh; + width: 100vw; + height: 100vh; display: flex; justify-content: center; align-items: center; - background: ${LIME.background}; + background: ${BLACK.background}; + position: relative; ` -export const RecoverBox = styled.div` +export const Navbar = styled.nav` + width: 100%; + height: 40px; display: flex; - flex-direction: column; - justify-content: center; + justify-content: space-between; align-items: center; - max-width: 520px; - width: 100%; - box-shadow: 0px 0px 4px 3px rgba(0, 0, 0, 0.15); - padding: 40px 23px; - border-radius: 24px; - background: ${WHITE.main}; - - @media ${device.tablet} { - max-width: 515px; - } - - @media ${device.mobileL} { - max-width: 325px; - padding: 50px 20px; - } - - @media ${device.mobileM} { - max-width: 290px; - } + position: absolute; + top: 0; + margin-top: 49px; + padding: 0 55px; ` -export const TextContainer = styled.div` +export const AccountActions = styled.div` display: flex; - justify-content: flex-start; - width: 100%; + column-gap: 16px; ` -export const TitleText = styled.h3` - font-weight: 700; - font-size: 30px; - color: ${BLACK.main}; - margin: ${(props) => props.margin || '0'}; - - @media ${device.tablet} { - font-size: 28px; - } - - @media ${device.mobileL} { - font-size: 22px; - } - - @media ${device.mobileM} { - font-size: 20px; - } +export const NavBarText = styled.a` + font-size: 20px; + font-weight: 500; + color: ${WHITE.main}; ` -export const SubTitleText = styled.h4` - font-weight: 400; - font-size: 22px; - color: ${GREY.text}; - margin: 0; - - @media ${device.tablet} { - font-size: 21px; - } - - @media ${device.mobileL} { - font-size: 19px; - } +export const NavigationLink = styled(NavLink)` + font-size: 20px; + font-weight: 500; + color: ${WHITE.main}; + text-decoration: none; - @media ${device.mobileM} { - font-size: 17px; + &.active { + color: ${GREEN.text}; + border-bottom: 1px solid ${GREEN.border}; } ` -export const RecoverInput = styled.input` - outline: none; - width: 96%; - height: 77px; - text-align: center; - border: 1px solid #000000; - border-radius: 3px; - margin: 44px 0 44px 0; - background: ${GREY.background}; +export const RecoverBox = styled.div` + max-width: 370px; + width: 100%; + min-height: 327px; + display: flex; + flex-direction: column; + align-items: center; +` +export const RecoverTitle = styled.h3` + font-size: 24px; font-weight: 600; - font-size: 22px; - color: ${BLACK.main}; - - &::placeholder { - font-weight: 600; - font-size: 24px; - - @media ${device.mobileL} { - font-size: 21px; - } - - @media ${device.mobileM} { - font-size: 20px; - } - } - - @media ${device.tablet} { - height: 70px; - } - - @media ${device.mobileL} { - font-size: 18px; - height: 67px; - } - - @media ${device.mobileM} { - font-size: 16px; - height: 64px; - } + color: ${WHITE.main}; + margin-bottom: 8px; ` - -export const RecoverButton = styled.button` - font-weight: 700; - font-size: 23px; - border: none; - width: 97%; - height: 77px; - background: ${BLACK.main}; +export const RecoverText = styled.p` + font-size: 16px; + font-weight: 400; color: ${WHITE.main}; text-align: center; - border: 1px solid ${BLACK.main}; - box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); - border-radius: 3px; - - &:hover { - border: none; - cursor: pointer; - transition: 0.4s; - color: ${BLACK.main}; - background: ${LIME.main}; - } - - @media ${device.tablet} { - height: 70px; - } - - @media ${device.mobileL} { - font-size: 18px; - height: 67px; - } - - @media ${device.mobileM} { - font-size: 16px; - height: 64px; - } -` - -export const BackButton = styled.button` - font-weight: 700; - font-size: 26px; - color: ${BLACK.main}; - background: none; - border: none; - - &:hover { - cursor: pointer; - transition: 0.4s; - color: ${LIME.main}; - } - - @media ${device.mobileL} { - font-size: 18px; - } - - @media ${device.mobileM} { - font-size: 17px; - } + margin-bottom: 48px; ` -export const ButtonContainer = styled.div` +export const ButtonsContainer = styled.div` + width: 100%; display: flex; - gap: 34px; - align-items: center; - margin-top: 50px; + flex-direction: column; + row-gap: 16px; + margin-top: 48px; ` diff --git a/client/src/components/Forms/RecoverPassword/RecoverValidation.js b/client/src/components/Forms/RecoverPassword/RecoverValidation.js index 32bc26329..ac9cfaaf6 100644 --- a/client/src/components/Forms/RecoverPassword/RecoverValidation.js +++ b/client/src/components/Forms/RecoverPassword/RecoverValidation.js @@ -2,7 +2,7 @@ import * as yup from 'yup' const emailValidation = yup.object().shape({ - email: yup.string().required('You forgot to input email 😁').email(), + email: yup.string().required('You forgot to input email 😁').email('Email is not valid.'), }) export default emailValidation diff --git a/client/src/shared/components/CustomButton/CustomButon.styles.js b/client/src/shared/components/CustomButton/CustomButon.styles.js index ef313967b..363aef47f 100644 --- a/client/src/shared/components/CustomButton/CustomButon.styles.js +++ b/client/src/shared/components/CustomButton/CustomButon.styles.js @@ -7,7 +7,8 @@ export const Button = styled.button` border: ${(props) => (props.border ? props.border : 'none')}; color: ${(props) => (props.transparent ? '#007bff' : '#fff')}; padding: 0.875rem 0; - width: 10.625rem; + width: ${(props) => props.width || '10.625rem'}; + font-size: ${(props) => props.fontSize}; border-radius: 10px; display: flex; align-items: center; From b07b6c2f6ab50228b9ff45e11a25b2b67d05054d Mon Sep 17 00:00:00 2001 From: Amantur Date: Wed, 31 May 2023 19:47:56 +0600 Subject: [PATCH 02/10] add toast notification --- client/src/api/endpoints/reset.js | 7 ++++-- .../RecoverPasswordForm.js | 25 +++++++++++-------- .../RecoverPasswordForm.styles.js | 4 +++ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/client/src/api/endpoints/reset.js b/client/src/api/endpoints/reset.js index 881510fa0..1382bf733 100644 --- a/client/src/api/endpoints/reset.js +++ b/client/src/api/endpoints/reset.js @@ -1,13 +1,16 @@ // * API import http from '../../http' +import { errorToaster } from '../../shared/components/Toasters/Error.toaster' const { api } = http const getRegistrationEmail = async (email) => { try { - await api.post('/reset-password', { email }) + await api.get(`/auth/reset-password/${email}`) } catch (err) { - console.log(err) + errorToaster(err.response.data.message) + + return err.response.data.message } } diff --git a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js index 77b9ccdc9..373604168 100644 --- a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js +++ b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js @@ -1,8 +1,8 @@ // * Modules -import { useState } from 'react' import { useNavigate } from 'react-router-dom' import { Formik } from 'formik' +import resetApi from '../../../api/endpoints/reset' // * Assets import ArrowNavigateBack from '../../../assets/Arrows/ArrowNavigateBack' import SiteLogo from '../../../assets/BigSideLogo' @@ -17,6 +17,7 @@ import { Navbar, NavigationLink, RecoverBox, + RecoverForm, RecoverText, RecoverTitle, } from './RecoverPasswordForm.styles' @@ -24,17 +25,19 @@ import emailValidation from './RecoverValidation' const RecoverPassword2 = () => { const navigate = useNavigate() - const [email, setEmail] = useState('') - const [errors, setErrors] = useState([]) - - const handleReset = async () => { + const handleReset = async ({ email }) => { try { - const isValid = await emailValidation.validate({ email }) + const isSuccess = await resetApi.getRegistrationEmail(email) - console.log(isValid) + if (!isSuccess) { + navigate(ROUTES.confirmEmail, { + replace: true, + state: { email }, + }) + } } catch (err) { - setErrors(err.errors) + console.log(err) } } @@ -59,9 +62,10 @@ const RecoverPassword2 = () => { email: '', }} validationSchema={emailValidation} + onSubmit={(values, _) => handleReset(values)} > {({ values }) => ( - <> + @@ -69,7 +73,6 @@ const RecoverPassword2 = () => { width="100%" fontSize="16px" disabled={!values.email} - onClick={handleReset} type="onSubmit" name="email" > @@ -87,7 +90,7 @@ const RecoverPassword2 = () => { Back to Log in - + )} diff --git a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js index cc28c2a27..d173ed5e3 100644 --- a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js +++ b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js @@ -1,4 +1,5 @@ import { NavLink } from 'react-router-dom' +import { Form } from 'formik' import styled from 'styled-components' import { BLACK, GREEN, GREY, LIME, WHITE } from '../../../constants/colors' @@ -12,6 +13,9 @@ export const Container = styled.div` background: ${BLACK.background}; position: relative; ` +export const RecoverForm = styled(Form)` + width: 100%; +` export const Navbar = styled.nav` width: 100%; From 648206bfb04a7de7b4a1423c8385a3845c22b583 Mon Sep 17 00:00:00 2001 From: Amantur Date: Thu, 1 Jun 2023 08:39:38 +0600 Subject: [PATCH 03/10] redesing email comfirmation page --- .../Forms/ConfirmEmailForm/ConfirmEmail.js | 12 ++++++------ .../Forms/ConfirmEmailForm/ConfirmEmail.styles.js | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.js b/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.js index 0d270e60d..7b857f1de 100644 --- a/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.js +++ b/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.js @@ -5,15 +5,15 @@ import { Container, ImgContainer, Text, TextContainer } from './ConfirmEmail.sty function ConfirmEmail() { return ( - - A verification link has been sent to you - - Please check your email - - + + Check your email + + We send you link to reset your password + + ) } diff --git a/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.styles.js b/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.styles.js index a6bc7bc88..10d008577 100644 --- a/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.styles.js +++ b/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.styles.js @@ -21,8 +21,8 @@ export const TextContainer = styled.div` ` export const Text = styled.h3` - font-weight: ${(props) => props.fontWeight || '700'}; - font-size: ${(props) => props.fontSize || '35px'}; + font-weight: ${(props) => props.fontWeight || '500'}; + font-size: ${(props) => props.fontSize || '24px'}; margin: ${(props) => props.margin || '0 0 20px 0'}; color: ${WHITE.main}; text-align: center; From d99593cd9f040310181524c6ebc13a1f331c6bd9 Mon Sep 17 00:00:00 2001 From: Amantur Date: Thu, 1 Jun 2023 09:47:07 +0600 Subject: [PATCH 04/10] add shared navbar for reset password pages --- .../RecoverPasswordForm.js | 12 ------ .../ResetPasswordPageLayout.js | 31 ++++++++++++++ .../ResetPasswordPageLayout.styles.js | 40 +++++++++++++++++++ client/src/routes/routes.js | 11 +++-- 4 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.js create mode 100644 client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.styles.js diff --git a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js index 373604168..c39ab97f1 100644 --- a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js +++ b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js @@ -5,17 +5,13 @@ import { Formik } from 'formik' import resetApi from '../../../api/endpoints/reset' // * Assets import ArrowNavigateBack from '../../../assets/Arrows/ArrowNavigateBack' -import SiteLogo from '../../../assets/BigSideLogo' import ROUTES from '../../../constants/routes' import CustomButton from '../../../shared/components/CustomButton/CustomButton' import CustomInput from '../../../shared/components/CustomInput/CustomInput' import { - AccountActions, ButtonsContainer, Container, - Navbar, - NavigationLink, RecoverBox, RecoverForm, RecoverText, @@ -44,14 +40,6 @@ const RecoverPassword2 = () => { return ( <> - - - - Log in - Sign up - - - Recover Password diff --git a/client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.js b/client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.js new file mode 100644 index 000000000..f3336ecf8 --- /dev/null +++ b/client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.js @@ -0,0 +1,31 @@ +import React from 'react' +import { NavLink, Outlet } from 'react-router-dom' + +import SideLogo from '../../assets/BigSideLogo' +import ROUTES from '../../constants/routes' + +import { + AccountActions, + Navbar, + NavigationLink, + NavigationLinkActive, +} from './ResetPasswordPageLayout.styles' + +const ResetPasswordPageLayout = () => { + return ( + <> + + + + + + Log in + Sign up + + + + + ) +} + +export default ResetPasswordPageLayout diff --git a/client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.styles.js b/client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.styles.js new file mode 100644 index 000000000..decf2ea06 --- /dev/null +++ b/client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.styles.js @@ -0,0 +1,40 @@ +import { NavLink } from 'react-router-dom' +import styled from 'styled-components' + +import { GREEN, WHITE } from '../../constants/colors' + +export const Navbar = styled.nav` + width: 100%; + height: 40px; + display: flex; + justify-content: space-between; + align-items: center; + position: absolute; + top: 0; + margin-top: 49px; + padding: 0 55px; + z-index: 999; +` + +export const AccountActions = styled.div` + display: flex; + column-gap: 16px; +` + +export const NavBarText = styled.a` + font-size: 20px; + font-weight: 500; + color: ${WHITE.main}; +` + +export const NavigationLink = styled(NavLink)` + font-size: 20px; + font-weight: 500; + color: ${WHITE.main}; + text-decoration: none; +` + +export const NavigationLinkActive = styled(NavigationLink)` + color: ${GREEN.text}; + border-bottom: 1px solid ${GREEN.border}; +` diff --git a/client/src/routes/routes.js b/client/src/routes/routes.js index 8d5156728..4818150b8 100644 --- a/client/src/routes/routes.js +++ b/client/src/routes/routes.js @@ -10,6 +10,7 @@ import ROUTES from '../constants/routes' // * Layouts import AuthLayout from '../layouts/AuthLayout/AuthLayout' import NavBarItemPageLayout from '../layouts/NavBarItemPageLayout/NavBarItemPageLayout' +import ResetPasswordPageLayout from '../layouts/ResetPasswordPageLayout/ResetPasswordPageLayout' import Screen404 from '../screens/404Screen/404Screen' // * Screens import ConfirmationScreen from '../screens/ConfirmationScreen/ConfirmationScreen' @@ -69,10 +70,12 @@ export const useRoutes = () => { } /> } /> - } /> - } /> - } /> - } /> + }> + } /> + } /> + } /> + } /> + } /> From f3622e527b4d8769044d8ee67a1d92c1b4b51502 Mon Sep 17 00:00:00 2001 From: Amantur Date: Sun, 25 Jun 2023 12:56:11 +0600 Subject: [PATCH 05/10] Implement desing of new password creation page. --- .../NewPasswordsForm/NewPasswordsForm.js | 132 ++++++------- .../NewPasswordsForm.styles.js | 182 ++---------------- .../RecoverPasswordForm.styles.js | 2 +- 3 files changed, 77 insertions(+), 239 deletions(-) diff --git a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js index 93ae42439..7dc7a45a1 100644 --- a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js +++ b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js @@ -1,39 +1,36 @@ // * Modules import React, { useEffect, useState } from 'react' import { useNavigate, useParams } from 'react-router-dom' -import Visibility from '@mui/icons-material/Visibility' -import VisibilityOff from '@mui/icons-material/VisibilityOff' +import VisibilityOff from '@mui/icons-material/VisibilityOffOutlined' +import Visibility from '@mui/icons-material/VisibilityOutlined' import AppBar from '@mui/material/AppBar' import Box from '@mui/material/Box' import Snackbar from '@mui/material/Snackbar' +import { Form, Formik } from 'formik' // * Api import resetPassword from '../../../api/endpoints/reset' // * Assets import SiteLogo from '../../../assets/Platform/TeameightsLogo' import ROUTES from '../../../constants/routes' +import CustomButton from '../../../shared/components/CustomButton/CustomButton' +import CustomInput from '../../../shared/components/CustomInput/CustomInput' +import { RecoverText, RecoverTitle } from '../RecoverPasswordForm/RecoverPasswordForm.styles' import { - AlertBox, Container, - InputContainer, + InputsContainer, NewPasswordBox, - NewPasswordButton, - NewPasswordContainer, - NewPasswordInput, PasswordContainer, ShowPass, - SubTitleText, - TextContainer, - TitleText, } from './NewPasswordsForm.styles' function NewPassword() { const navigate = useNavigate() - const Alert = React.forwardRef(function Alert(props, ref) { - return - }) + // const Alert = React.forwardRef(function Alert(props, ref) { + // return + // }) let { id, token } = useParams() const [password, setPassword] = useState('') @@ -64,64 +61,61 @@ function NewPassword() { return ( - - - - {error && ( - + Recover Password + + Enter a new password and confirm it by re-entering it in the appropriate fields + + - - {error} - - - )} - - - - Recover Password - - - - Create new, strong password that you don't use for the other - websites - - - - - setPassword(e.target.value)} - required - /> - setShowPassword(!showPassword)}> - {showPassword ? : } - - - - setRepeatPassword(e.target.value)} - required - /> - setShowPassword(!showPassword)}> - {showPassword ? : } - - - RESET PASSWORD - - - +
+ + + + setShowPassword(!showPassword)}> + {showPassword ? ( + + ) : ( + + )} + + + + + setShowPassword(!showPassword)}> + {showPassword ? ( + + ) : ( + + )} + + + +
+ + + navigate(ROUTES.login, { replace: true })} + > + Log in + +
) } diff --git a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js index e7b9e0f73..96b0148e7 100644 --- a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js +++ b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js @@ -8,172 +8,26 @@ import { BLACK, GREY, LIME, WHITE } from '../../../constants/colors' export const Container = styled.div` display: flex; - flex-direction: column; -` - -export const NewPasswordContainer = styled.div` + height: 100vh; width: 100%; - height: 91.4vh; - display: flex; + text-align: center; justify-content: center; align-items: center; - background: ${LIME.background}; ` export const NewPasswordBox = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - max-width: 520px; + max-width: 370px; width: 100%; - box-shadow: 0px 0px 4px 3px rgba(0, 0, 0, 0.15); - padding: 40px 23px; - border-radius: 24px; - background: ${WHITE.main}; - - @media ${device.tablet} { - max-width: 515px; - } - - @media ${device.mobileL} { - max-width: 325px; - padding: 50px 20px; - } - - @media ${device.mobileM} { - max-width: 290px; - } -` - -export const TextContainer = styled.div` + min-height: 337px; display: flex; - justify-content: flex-start; - width: 100%; -` - -export const TitleText = styled.h3` - font-weight: 700; - font-size: 30px; - color: ${BLACK.main}; - margin: ${(props) => props.margin || '0'}; - - @media ${device.tablet} { - font-size: 28px; - } - - @media ${device.mobileL} { - font-size: 22px; - } - - @media ${device.mobileM} { - font-size: 20px; - } -` - -export const SubTitleText = styled.h4` - font-weight: 400; - font-size: 22px; - color: ${GREY.text}; - margin: 0; - - @media ${device.tablet} { - font-size: 21px; - } - - @media ${device.mobileL} { - font-size: 19px; - } - - @media ${device.mobileM} { - font-size: 17px; - } -` - -export const NewPasswordInput = styled.input` - outline: none; - width: 98.5%; - height: 77px; - text-align: center; - border: 1px solid #000000; - border-radius: 3px; - background: ${GREY.background}; - font-weight: 600; - font-size: 22px; - color: ${BLACK.main}; - margin-bottom: 34px; - - &::placeholder { - font-weight: 600; - font-size: 23px; - - @media ${device.mobileL} { - font-size: 19px; - } - - @media ${device.mobileM} { - font-size: 18px; - } - } - - @media ${device.tablet} { - height: 70px; - } - - @media ${device.mobileL} { - font-size: 18px; - height: 67px; - } - - @media ${device.mobileM} { - font-size: 16px; - height: 64px; - } -` - -export const NewPasswordButton = styled.button` - font-weight: 700; - font-size: 23px; - border: none; - width: 100%; - height: 77px; - background: ${BLACK.main}; - color: ${WHITE.main}; - text-align: center; - border: 1px solid ${BLACK.main}; - box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); - border-radius: 3px; - - &:hover { - border: none; - cursor: pointer; - transition: 0.4s; - color: ${BLACK.main}; - background: ${LIME.main}; - } - - @media ${device.tablet} { - height: 70px; - } - - @media ${device.mobileL} { - font-size: 18px; - height: 67px; - } - - @media ${device.mobileM} { - font-size: 16px; - height: 64px; - } + flex-direction: column; ` - -export const InputContainer = styled.div` +export const InputsContainer = styled.div` + height: 112px; display: flex; flex-direction: column; - justify-content: center; - align-items: center; - width: 95%; - margin: 44px 0 0 0px; + justify-content: space-between; + margin-bottom: 48px; ` export const PasswordContainer = styled.div` @@ -182,13 +36,13 @@ export const PasswordContainer = styled.div` ` export const ShowPass = styled(IconButton)` - right: 15px; - top: 22px; + right: -2px; + top: -1px; && { position: absolute; } - @media ${device.mobileL} { + /* @media ${device.mobileL} { right: 0; top: 14px; } @@ -196,15 +50,5 @@ export const ShowPass = styled(IconButton)` @media ${device.mobileM} { right: 0; top: 13px; - } -` - -export const AlertBox = styled(MuiAlert)` - && { - background: ${BLACK.main}; - } - - @media ${device.tablet} { - max-width: 250px; - } + } */ ` diff --git a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js index d173ed5e3..4aff7b33f 100644 --- a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js +++ b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js @@ -63,7 +63,7 @@ export const RecoverBox = styled.div` export const RecoverTitle = styled.h3` font-size: 24px; font-weight: 500; - color: ${WHITE.main}; + color: ${GREEN.text}; margin-bottom: 8px; ` export const RecoverText = styled.p` From 8ea086058374c4aa1ec12a308d923642f768a2dd Mon Sep 17 00:00:00 2001 From: Amantur Date: Mon, 3 Jul 2023 00:08:07 +0600 Subject: [PATCH 06/10] implement desing of creating new password --- .../NewPasswordsForm/NewPasswordsForm.js | 127 ++++++++---------- .../NewPasswordsForm.styles.js | 29 ++-- .../NewPasswordsValidation.js | 10 ++ .../RecoverPasswordForm.styles.js | 1 + .../components/CustomInput/CustomInput.jsx | 8 +- 5 files changed, 82 insertions(+), 93 deletions(-) create mode 100644 client/src/components/Forms/NewPasswordsForm/NewPasswordsValidation.js diff --git a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js index 7dc7a45a1..9735c5e15 100644 --- a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js +++ b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js @@ -1,17 +1,13 @@ // * Modules -import React, { useEffect, useState } from 'react' +import React, { useState } from 'react' import { useNavigate, useParams } from 'react-router-dom' import VisibilityOff from '@mui/icons-material/VisibilityOffOutlined' import Visibility from '@mui/icons-material/VisibilityOutlined' -import AppBar from '@mui/material/AppBar' -import Box from '@mui/material/Box' -import Snackbar from '@mui/material/Snackbar' import { Form, Formik } from 'formik' // * Api import resetPassword from '../../../api/endpoints/reset' // * Assets -import SiteLogo from '../../../assets/Platform/TeameightsLogo' import ROUTES from '../../../constants/routes' import CustomButton from '../../../shared/components/CustomButton/CustomButton' import CustomInput from '../../../shared/components/CustomInput/CustomInput' @@ -19,46 +15,30 @@ import { RecoverText, RecoverTitle } from '../RecoverPasswordForm/RecoverPasswor import { Container, - InputsContainer, NewPasswordBox, PasswordContainer, + PasswordsContainer, ShowPass, } from './NewPasswordsForm.styles' +import newPasswordValidation from './NewPasswordsValidation' function NewPassword() { const navigate = useNavigate() - // const Alert = React.forwardRef(function Alert(props, ref) { - // return - // }) - let { id, token } = useParams() - const [password, setPassword] = useState('') - const [repeatPassword, setRepeatPassword] = useState('') const [showPassword, setShowPassword] = useState(false) - const [open, setOpen] = useState(false) - const [error, setError] = useState('') + const [error, setError] = useState({}) const handleReset = async () => { - const error = await resetPassword.updatePassword(id, token, password, repeatPassword) + // const error = await resetPassword.updatePassword(id, token, password, repeatPassword) if (!error) { navigate(ROUTES.login, { replace: true }) } else { - setOpen(true) setError(error) } } - const handleClose = (event, reason) => { - if (reason === 'clickaway') { - return - } - setOpen(false) - } - - useEffect(() => {}, [error]) - return ( @@ -68,53 +48,64 @@ function NewPassword() {
handleReset()} > -
- - - - setShowPassword(!showPassword)}> - {showPassword ? ( - - ) : ( - - )} - - - - - setShowPassword(!showPassword)}> - {showPassword ? ( - - ) : ( - + {({ values }) => ( + + + + + {!error?.isError && ( + setShowPassword(!showPassword)}> + {showPassword ? ( + + ) : ( + + )} + )} - - - -
+ + + + setShowPassword(!showPassword)}> + {showPassword ? ( + + ) : ( + + )} + + + + + Save + + + )}
- - navigate(ROUTES.login, { replace: true })} - > - Log in -
) diff --git a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js index 96b0148e7..6d95a7b47 100644 --- a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js +++ b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js @@ -1,16 +1,13 @@ -import MuiAlert from '@mui/material/Alert' import IconButton from '@mui/material/IconButton' -import Toolbar from '@mui/material/Toolbar' import styled from 'styled-components' -import { device } from '../../../constants/breakpoints' import { BLACK, GREY, LIME, WHITE } from '../../../constants/colors' export const Container = styled.div` display: flex; height: 100vh; width: 100%; - text-align: center; + justify-content: center; align-items: center; ` @@ -22,18 +19,18 @@ export const NewPasswordBox = styled.div` display: flex; flex-direction: column; ` -export const InputsContainer = styled.div` - height: 112px; - display: flex; - flex-direction: column; - justify-content: space-between; - margin-bottom: 48px; -` export const PasswordContainer = styled.div` position: relative; width: 100%; ` +export const PasswordsContainer = styled.div` + height: 149px; + display: flex; + flex-direction: column; + justify-content: space-between; + margin-bottom: 48px; +` export const ShowPass = styled(IconButton)` right: -2px; @@ -41,14 +38,4 @@ export const ShowPass = styled(IconButton)` && { position: absolute; } - - /* @media ${device.mobileL} { - right: 0; - top: 14px; - } - - @media ${device.mobileM} { - right: 0; - top: 13px; - } */ ` diff --git a/client/src/components/Forms/NewPasswordsForm/NewPasswordsValidation.js b/client/src/components/Forms/NewPasswordsForm/NewPasswordsValidation.js new file mode 100644 index 000000000..e792a0176 --- /dev/null +++ b/client/src/components/Forms/NewPasswordsForm/NewPasswordsValidation.js @@ -0,0 +1,10 @@ +import * as yup from 'yup' + +const newPasswordValidation = yup.object().shape({ + password: yup + .string() + .required('Must be at least 8 characters') + .min(8, 'Must be at least 8 characters'), +}) + +export default newPasswordValidation diff --git a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js index 4aff7b33f..d2648e5f1 100644 --- a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js +++ b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js @@ -65,6 +65,7 @@ export const RecoverTitle = styled.h3` font-weight: 500; color: ${GREEN.text}; margin-bottom: 8px; + text-align: center; ` export const RecoverText = styled.p` font-size: 16px; diff --git a/client/src/shared/components/CustomInput/CustomInput.jsx b/client/src/shared/components/CustomInput/CustomInput.jsx index 6cbd1cd42..36b001647 100644 --- a/client/src/shared/components/CustomInput/CustomInput.jsx +++ b/client/src/shared/components/CustomInput/CustomInput.jsx @@ -13,7 +13,7 @@ const CustomInput = ({ containerWidth = 'auto', inputWidth = '100%', onInputChange, - uniqueError, + uniqueError = false, uniqueErrorMessage, shouldFormatDate = false, shouldFormatYear = false, @@ -42,7 +42,7 @@ const CustomInput = ({ return ( - {label && } + {props?.inputValue && label && } - {(isError || uniqueError) && ( + {((meta.touched && isError) || (meta.touched && uniqueError)) && ( )} {isError && {meta.error}} - {uniqueError && {uniqueErrorMessage}} + {meta.touched && uniqueError && {uniqueErrorMessage}} ) } From bf0143486b97fd1734af50dfb3f4d4fa0350637f Mon Sep 17 00:00:00 2001 From: Nikita Mashchenko <52038455+exortme1ster@users.noreply.github.com> Date: Mon, 10 Jul 2023 02:43:03 -0500 Subject: [PATCH 07/10] fix: fixed pull request issues --- client/src/api/endpoints/reset.js | 30 - client/src/api/hooks/auth/useResetPassword.js | 33 + .../src/api/hooks/auth/useUpdatePassword.js | 41 + client/src/assets/Shared/SearchingPeople.js | 725 ++++-------------- .../Forms/ConfirmEmailForm/ConfirmEmail.js | 22 +- .../ConfirmEmailForm/ConfirmEmail.styles.js | 40 +- .../NewPasswordsForm/NewPasswordsForm.js | 102 +-- .../NewPasswordsForm.styles.js | 17 +- .../NewPasswordsValidation.js | 21 +- .../Forms/Page404Form/Page404Form.js | 55 +- .../Forms/Page404Form/Page404Form.styles.js | 59 +- .../Forms/Page404Form/ParticlesContainer.jsx | 154 ++++ .../RecoverConfirmationForm.js | 55 -- .../RecoverConfirmationForm.styles.js | 142 ---- .../RecoverPasswordForm.js | 119 +-- .../RecoverPasswordForm.styles.js | 33 +- .../RecoverPasswordForm/RecoverValidation.js | 5 +- client/src/components/Profile/Profile.jsx | 1 - .../UserStatusButtons/UserStatusButtons.jsx | 1 - .../InitialPart/ParticlesContainer.jsx | 5 +- .../NavigationButtons/NavigationButtons.jsx | 3 + .../ResetPasswordPageLayout.js | 15 +- .../ResetPasswordPageLayout.styles.js | 23 +- client/src/routes/routes.js | 2 - .../ResetPasswordConfirmationScreen.js | 15 - .../CustomButton/CustomButon.styles.js | 2 +- .../components/CustomButton/CustomButton.jsx | 10 +- .../components/FlexWrapper/FlexWrapper.js | 1 + .../Formik/CustomInput/CustomInput.jsx | 5 +- server/src/auth/auth.controller.ts | 19 +- server/src/auth/auth.service.ts | 6 - server/src/auth/guards/jwt-auth.guard.ts | 2 + 32 files changed, 673 insertions(+), 1090 deletions(-) delete mode 100644 client/src/api/endpoints/reset.js create mode 100644 client/src/api/hooks/auth/useResetPassword.js create mode 100644 client/src/api/hooks/auth/useUpdatePassword.js create mode 100644 client/src/components/Forms/Page404Form/ParticlesContainer.jsx delete mode 100644 client/src/components/Forms/RecoverConfirmationForm/RecoverConfirmationForm.js delete mode 100644 client/src/components/Forms/RecoverConfirmationForm/RecoverConfirmationForm.styles.js delete mode 100644 client/src/screens/ResetPasswordConfirmationScreen/ResetPasswordConfirmationScreen.js diff --git a/client/src/api/endpoints/reset.js b/client/src/api/endpoints/reset.js deleted file mode 100644 index 1382bf733..000000000 --- a/client/src/api/endpoints/reset.js +++ /dev/null @@ -1,30 +0,0 @@ -// * API -import http from '../../http' -import { errorToaster } from '../../shared/components/Toasters/Error.toaster' - -const { api } = http - -const getRegistrationEmail = async (email) => { - try { - await api.get(`/auth/reset-password/${email}`) - } catch (err) { - errorToaster(err.response.data.message) - - return err.response.data.message - } -} - -const updatePassword = async (id, token, password, repeatPassword) => { - try { - await api.post(`/reset-password/${id}/${token}`, { id, token, password, repeatPassword }) - } catch (err) { - return err.response.data.message - } -} - -const resetApi = Object.freeze({ - getRegistrationEmail, - updatePassword, -}) - -export default resetApi diff --git a/client/src/api/hooks/auth/useResetPassword.js b/client/src/api/hooks/auth/useResetPassword.js new file mode 100644 index 000000000..98d4cbb82 --- /dev/null +++ b/client/src/api/hooks/auth/useResetPassword.js @@ -0,0 +1,33 @@ +import { useMutation, useQueryClient } from 'react-query' +import { useNavigate } from 'react-router-dom' + +import ROUTES from '../../../constants/routes' +import http from '../../../http' +import { errorToaster } from '../../../shared/components/Toasters/Error.toaster' + +const { api } = http + +export const useResetPasssword = (successHandler) => { + const navigate = useNavigate() + + const updateUserPassword = async (email) => { + return await api.get(`/auth/reset-password/${email}`) + } + + return useMutation(updateUserPassword, { + mutationKey: 'updateUserPassword', + onSuccess: async () => { + if (successHandler) { + successHandler() + } + + navigate(ROUTES.confirmEmail, { + replace: true, + }) + }, + onError: (error) => { + // set error message + errorToaster(error, 'top-center') + }, + }) +} diff --git a/client/src/api/hooks/auth/useUpdatePassword.js b/client/src/api/hooks/auth/useUpdatePassword.js new file mode 100644 index 000000000..48cbee96c --- /dev/null +++ b/client/src/api/hooks/auth/useUpdatePassword.js @@ -0,0 +1,41 @@ +import { useMutation, useQueryClient } from 'react-query' +import { useNavigate } from 'react-router-dom' + +import ROUTES from '../../../constants/routes' +import http from '../../../http' +import { errorToaster } from '../../../shared/components/Toasters/Error.toaster' + +const { api } = http + +export const useUpdatePassword = (successHandler) => { + const navigate = useNavigate() + + const updateUserPassword = async ({ email, token, password }) => { + return await api.post(`/auth/update-password`, { email, token, password }) + } + + return useMutation(updateUserPassword, { + mutationKey: 'updateUserPassword', + onSuccess: async () => { + if (successHandler) { + successHandler() + } + + navigate(ROUTES.login, { + replace: true, + }) + }, + onError: (error) => { + // set error message + errorToaster(error, 'top-center') + + if (error?.response?.status === 403) { + setTimeout(() => { + navigate(ROUTES.login, { + replace: true, + }) + }, 1500) + } + }, + }) +} diff --git a/client/src/assets/Shared/SearchingPeople.js b/client/src/assets/Shared/SearchingPeople.js index d46c2be98..fdd2693a8 100644 --- a/client/src/assets/Shared/SearchingPeople.js +++ b/client/src/assets/Shared/SearchingPeople.js @@ -1,638 +1,227 @@ function NonFound() { return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -644,17 +233,17 @@ function NonFound() { result="hardAlpha" /> - + - + diff --git a/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.js b/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.js index 7b857f1de..8ee74a89c 100644 --- a/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.js +++ b/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.js @@ -1,8 +1,15 @@ +import { useNavigate } from 'react-router-dom' + +import ArrowNavigateBack from '../../../assets/Arrows/ArrowNavigateBack' import UserBehindPC from '../../../assets/Shared/UserBehindPC' +import ROUTES from '../../../constants/routes' +import CustomButton from '../../../shared/components/CustomButton/CustomButton' import { Container, ImgContainer, Text, TextContainer } from './ConfirmEmail.styles' function ConfirmEmail() { + const navigate = useNavigate() + return ( @@ -10,9 +17,20 @@ function ConfirmEmail() { Check your email - - We send you link to reset your password + + We sent you a link to reset your password + navigate(ROUTES.login)} + > + + Back to Log in + + ) diff --git a/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.styles.js b/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.styles.js index 10d008577..14f7be71c 100644 --- a/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.styles.js +++ b/client/src/components/Forms/ConfirmEmailForm/ConfirmEmail.styles.js @@ -4,7 +4,7 @@ import { BLACK, WHITE } from '../../../constants/colors' export const Container = styled.div` width: 100%; - height: 100vh; + min-height: calc(100dvh - 88px); display: flex; flex-direction: column; justify-content: center; @@ -17,45 +17,21 @@ export const TextContainer = styled.div` justify-content: center; flex-direction: column; align-items: center; - margin-bottom: 45px; + gap: 8px; + padding: 0 15px; ` export const Text = styled.h3` font-weight: ${(props) => props.fontWeight || '500'}; font-size: ${(props) => props.fontSize || '24px'}; - margin: ${(props) => props.margin || '0 0 20px 0'}; - color: ${WHITE.main}; + margin: ${(props) => props.margin || '0'}; + color: ${(props) => props.color || WHITE.main}; text-align: center; - - @media screen and (min-width: 620px) and (max-width: 840px) { - font-size: calc(${(props) => props.fontSize || '35px'} - 7px); - } - - @media screen and (min-width: 450px) and (max-width: 620px) { - font-size: calc(${(props) => props.fontSize || '35px'} - 14px); - } - - @media screen and (min-width: 0px) and (max-width: 450px) { - font-size: calc(${(props) => props.fontSize || '35px'} - 18px); - } ` export const ImgContainer = styled.div` - width: 621px; - height: 508px; - - @media screen and (min-width: 620px) and (max-width: 840px) { - width: 521px; - height: 408px; - } - - @media screen and (min-width: 450px) and (max-width: 620px) { - width: 421px; - height: 308px; - } + max-width: 621px; + width: 100%; - @media screen and (min-width: 0px) and (max-width: 450px) { - width: 321px; - height: 208px; - } + height: auto; ` diff --git a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js index 9735c5e15..a15abd3bf 100644 --- a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js +++ b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.js @@ -1,17 +1,22 @@ // * Modules import React, { useState } from 'react' -import { useNavigate, useParams } from 'react-router-dom' +import { ThreeDots } from 'react-loader-spinner' +import { useParams } from 'react-router-dom' import VisibilityOff from '@mui/icons-material/VisibilityOffOutlined' import Visibility from '@mui/icons-material/VisibilityOutlined' -import { Form, Formik } from 'formik' +import { Formik } from 'formik' +import { isEmpty } from 'lodash' -// * Api -import resetPassword from '../../../api/endpoints/reset' +import { useUpdatePassword } from '../../../api/hooks/auth/useUpdatePassword' // * Assets -import ROUTES from '../../../constants/routes' import CustomButton from '../../../shared/components/CustomButton/CustomButton' -import CustomInput from '../../../shared/components/CustomInput/CustomInput' -import { RecoverText, RecoverTitle } from '../RecoverPasswordForm/RecoverPasswordForm.styles' +import FlexWrapper from '../../../shared/components/FlexWrapper/FlexWrapper' +import CustomInput from '../../../shared/components/Formik/CustomInput/CustomInput' +import { + FormWrapper, + RecoverText, + RecoverTitle, +} from '../RecoverPasswordForm/RecoverPasswordForm.styles' import { Container, @@ -23,59 +28,48 @@ import { import newPasswordValidation from './NewPasswordsValidation' function NewPassword() { - const navigate = useNavigate() - - let { id, token } = useParams() + let { id: email, token } = useParams() + const { mutate: updateUserPassword, isLoading: isUpdating } = useUpdatePassword() const [showPassword, setShowPassword] = useState(false) - const [error, setError] = useState({}) - - const handleReset = async () => { - // const error = await resetPassword.updatePassword(id, token, password, repeatPassword) - - if (!error) { - navigate(ROUTES.login, { replace: true }) - } else { - setError(error) - } - } return ( - Recover Password - - Enter a new password and confirm it by re-entering it in the appropriate fields - + + Recover Password + + Enter a new password and confirm it by re-entering it in the appropriate fields + + handleReset()} + onSubmit={({ email, token, password }) => updateUserPassword({ email, token, password })} > - {({ values }) => ( -
+ {({ values, errors }) => ( + - {!error?.isError && ( - setShowPassword(!showPassword)}> - {showPassword ? ( - - ) : ( - - )} - - )} + setShowPassword(!showPassword)}> + {showPassword ? ( + + ) : ( + + )} + setShowPassword(!showPassword)}> {showPassword ? ( @@ -100,10 +90,28 @@ function NewPassword() { - - Save + + {isUpdating ? ( + + ) : ( + ' Save' + )} -
+ )}
diff --git a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js index 6d95a7b47..d767887b2 100644 --- a/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js +++ b/client/src/components/Forms/NewPasswordsForm/NewPasswordsForm.styles.js @@ -1,12 +1,14 @@ import IconButton from '@mui/material/IconButton' +import { Form } from 'formik' import styled from 'styled-components' import { BLACK, GREY, LIME, WHITE } from '../../../constants/colors' export const Container = styled.div` display: flex; - height: 100vh; + min-height: calc(100dvh - 88px); width: 100%; + padding: 48px 24px; justify-content: center; align-items: center; @@ -18,6 +20,9 @@ export const NewPasswordBox = styled.div` min-height: 337px; display: flex; flex-direction: column; + justify-content: center; + align-items: center; + gap: 48px; ` export const PasswordContainer = styled.div` @@ -25,17 +30,17 @@ export const PasswordContainer = styled.div` width: 100%; ` export const PasswordsContainer = styled.div` - height: 149px; display: flex; flex-direction: column; - justify-content: space-between; - margin-bottom: 48px; + gap: 36px; + width: 100%; ` export const ShowPass = styled(IconButton)` - right: -2px; - top: -1px; && { position: absolute; + right: 0; + top: 0; + transform: translate(5px, 20px); } ` diff --git a/client/src/components/Forms/NewPasswordsForm/NewPasswordsValidation.js b/client/src/components/Forms/NewPasswordsForm/NewPasswordsValidation.js index e792a0176..28393a8f7 100644 --- a/client/src/components/Forms/NewPasswordsForm/NewPasswordsValidation.js +++ b/client/src/components/Forms/NewPasswordsForm/NewPasswordsValidation.js @@ -3,8 +3,25 @@ import * as yup from 'yup' const newPasswordValidation = yup.object().shape({ password: yup .string() - .required('Must be at least 8 characters') - .min(8, 'Must be at least 8 characters'), + .required('Password is required') + .min(8, 'Password must be at least 8 characters') + .test('uppercase', 'Password must contain at least one uppercase letter', (value) => { + return /[A-Z]/.test(value) + }) + .test('lowercase', 'Password must contain at least one lowercase letter', (value) => { + return /[a-z]/.test(value) + }) + .test('digit', 'Password must contain at least one digit', (value) => { + return /\d/.test(value) + }) + .test('specialChar', 'Password must contain at least one special character', (value) => { + return /[@$!%*?&]/.test(value) + }), + + confirmPassword: yup + .string() + .required('Confirm is required') + .oneOf([yup.ref('password'), null], 'Passwords must match'), }) export default newPasswordValidation diff --git a/client/src/components/Forms/Page404Form/Page404Form.js b/client/src/components/Forms/Page404Form/Page404Form.js index 6057b1719..23e32a67f 100644 --- a/client/src/components/Forms/Page404Form/Page404Form.js +++ b/client/src/components/Forms/Page404Form/Page404Form.js @@ -1,40 +1,43 @@ // * Modules import { useNavigate } from 'react-router-dom' +import LongArrowLeft from '../../../assets/Arrows/LongArrowLeft' // * Assets import Page404 from '../../../assets/Shared/SearchingPeople' +import FlexWrapper from '../../../shared/components/FlexWrapper/FlexWrapper' // * Styles -import { - Button, - Container, - InfoContainer, - LeftContainer, - RightContainer, - Text, -} from './Page404Form.styles' +import { Button, Container, Text } from './Page404Form.styles' +import { ParticlesContainer } from './ParticlesContainer' -const Page404Form = ({ paddingLeft = '0', findText = `Couldn't find the requested page.` }) => { +const Page404Form = ({ + paddingLeft = '0', + findText = `Please check the URL or contact us for assistance`, +}) => { const navigate = useNavigate() return ( - - - - - 404 - - Oops... it looks like you're lost. - - {findText} - - - - - - - - + <> + + + + + + + Oops... it looks like you're lost. + + {findText} + + + + + + + + ) } diff --git a/client/src/components/Forms/Page404Form/Page404Form.styles.js b/client/src/components/Forms/Page404Form/Page404Form.styles.js index fbf3e25fd..afc9676f3 100644 --- a/client/src/components/Forms/Page404Form/Page404Form.styles.js +++ b/client/src/components/Forms/Page404Form/Page404Form.styles.js @@ -4,45 +4,16 @@ export const Container = styled.div` width: 100%; min-height: 100vh; display: flex; - background: #26292b; align-items: center; justify-content: center; padding-left: ${(props) => props.paddingLeft || '0'}; + flex-direction: column; + gap: 48px; @media screen and (max-width: 768px) { padding-left: 0; } ` -export const InfoContainer = styled.div` - display: flex; - flex-direction: row; - width: 100%; - height: 100%; - padding: 5rem 0; - align-items: center; - justify-content: center; - gap: 2rem; - - @media (max-width: 995px) { - flex-direction: column; - padding: 0; - } -` -export const LeftContainer = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - gap: 1rem; -` -export const RightContainer = styled.div` - display: flex; - flex-direction: column; - width: 45%; - @media (max-width: 995px) { - width: 75%; - } -` export const Text = styled.h1` font-weight: ${(props) => props.fontWeight || '500'}; @@ -54,20 +25,20 @@ export const Text = styled.h1` ` export const Button = styled.button` - width: 14rem; - height: 3.5rem; - background: #5d9d0b; - box-shadow: 0px 0px 50px rgba(93, 157, 11, 0.15); - border-radius: 5px; + width: 100%; + max-width: 160px; + height: 48px; + padding: 0px 16px; + background: #46a11b; + border-radius: 10px; color: white; - font-weight: 700; - font-size: 1rem; - border-style: none; + font-weight: 400; + font-size: 16px; + border: none; cursor: pointer; transition: all 0.2s linear; - margin-top: 1rem; - - :hover { - transform: scale(1.1); - } + display: flex; + justify-content: center; + align-items: center; + gap: 8px; ` diff --git a/client/src/components/Forms/Page404Form/ParticlesContainer.jsx b/client/src/components/Forms/Page404Form/ParticlesContainer.jsx new file mode 100644 index 000000000..db79f4fd4 --- /dev/null +++ b/client/src/components/Forms/Page404Form/ParticlesContainer.jsx @@ -0,0 +1,154 @@ +import React, { useCallback, useMemo } from 'react' +import { Particles } from 'react-particles' +import { loadFull } from 'tsparticles' + +export function ParticlesContainer() { + const particlesInit = useCallback(async (engine) => { + // you can initiate the tsParticles instance (engine) here, adding custom shapes or presets + // this loads the tsparticles package bundle, it's the easiest method for getting everything ready + // starting from v2 you can add only the features you need reducing the bundle size + await loadFull(engine) + }, []) + + const particlesLoaded = useCallback(async (container) => {}, []) + + // using useMemo is not mandatory, but it's recommended since this value can be memoized if static + const options = useMemo(() => { + // using an empty options object will load the default options, which are static particles with no background and 3px radius, opacity 100%, white color + // all options can be found here: https://particles.js.org/docs/interfaces/Options_Interfaces_IOptions.IOptions.html + return { + fullScreen: { + enable: true, + zIndex: -1, + }, + name: 'Among Us', + particles: { + groups: { + z5000: { + number: { + value: 70, + }, + zIndex: { + value: 50, + }, + }, + z7500: { + number: { + value: 30, + }, + zIndex: { + value: 75, + }, + }, + z2500: { + number: { + value: 50, + }, + zIndex: { + value: 25, + }, + }, + z1000: { + number: { + value: 40, + }, + zIndex: { + value: 10, + }, + }, + }, + number: { + value: 200, + }, + color: { + value: '#fff', + animation: { + enable: false, + speed: 20, + sync: true, + }, + }, + shape: { + type: 'circle', + }, + opacity: { + value: 1, + }, + size: { + value: 3, + }, + move: { + angle: { + value: 10, + offset: 0, + }, + enable: true, + speed: 5, + direction: 'right', + }, + zIndex: { + value: 5, + opacityRate: 0.5, + }, + }, + background: { + color: '#26292B', + }, + emitters: { + position: { + y: 55, + x: -5, + }, + rate: { + delay: 7, + quantity: 1, + }, + size: { + width: 0, + height: 0, + }, + particles: { + shape: { + type: 'images', + options: { + images: { + src: 'https://particles.js.org/images/cyan_amongus.png', + width: 500, + height: 634, + }, + }, + }, + size: { + value: 70, + }, + move: { + speed: 12, + outModes: { + default: 'none', + right: 'destroy', + }, + straight: true, + }, + zIndex: { + value: 0, + }, + rotate: { + value: { + min: 0, + max: 360, + }, + animation: { + enable: true, + speed: 10, + sync: true, + }, + }, + }, + }, + } + }, []) + + return ( + + ) +} diff --git a/client/src/components/Forms/RecoverConfirmationForm/RecoverConfirmationForm.js b/client/src/components/Forms/RecoverConfirmationForm/RecoverConfirmationForm.js deleted file mode 100644 index 037eea94c..000000000 --- a/client/src/components/Forms/RecoverConfirmationForm/RecoverConfirmationForm.js +++ /dev/null @@ -1,55 +0,0 @@ -// * Modules -import { useLocation, useNavigate } from 'react-router-dom' -import AppBar from '@mui/material/AppBar' -import Box from '@mui/material/Box' - -import ArrowLeftReset from '../../../assets/Arrows/ArrowLeftReset' -// * Assets -import SiteLogo from '../../../assets/Platform/TeameightsLogo' -import ROUTES from '../../../constants/routes' - -import { - BackButton, - ButtonContainer, - Container, - MiddleContainer, - MiddleText, - RecoverBox, - RecoverContainer, - TextContainer, - TitleText, -} from './RecoverConfirmationForm.styles' - -function RecoverPassword() { - const navigate = useNavigate() - const location = useLocation() - - return ( - - - - - - - - Recover Password - - - - If account “{location.state.email}” exists, an email will be sent with futher - instructions - - - - - navigate(ROUTES.login, { replace: true })}> - BACK TO SIGN IN - - - - - - ) -} - -export default RecoverPassword diff --git a/client/src/components/Forms/RecoverConfirmationForm/RecoverConfirmationForm.styles.js b/client/src/components/Forms/RecoverConfirmationForm/RecoverConfirmationForm.styles.js deleted file mode 100644 index 4e27b90f6..000000000 --- a/client/src/components/Forms/RecoverConfirmationForm/RecoverConfirmationForm.styles.js +++ /dev/null @@ -1,142 +0,0 @@ -import Toolbar from '@mui/material/Toolbar' -import styled from 'styled-components' - -import { device } from '../../../constants/breakpoints' -import { BLACK, GREEN, GREY, LIME, WHITE } from '../../../constants/colors' - -export const Container = styled.div` - display: flex; - flex-direction: column; -` - -export const RecoverContainer = styled.div` - width: 100%; - height: 91.4vh; - display: flex; - justify-content: center; - align-items: center; - background: ${LIME.background}; -` - -export const RecoverBox = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - max-width: 520px; - width: 100%; - box-shadow: 0px 0px 4px 3px rgba(0, 0, 0, 0.15); - padding: 40px 23px; - border-radius: 24px; - background: ${WHITE.main}; - - @media ${device.tablet} { - max-width: 515px; - } - - @media ${device.mobileL} { - max-width: 325px; - padding: 50px 20px; - } - - @media ${device.mobileM} { - max-width: 290px; - } -` - -export const TextContainer = styled.div` - display: flex; - justify-content: flex-start; - width: 100%; -` - -export const TitleText = styled.h3` - font-weight: 700; - font-size: 30px; - color: ${BLACK.main}; - margin: ${(props) => props.margin || '0'}; - - @media ${device.tablet} { - font-size: 28px; - } - - @media ${device.mobileL} { - font-size: 22px; - } - - @media ${device.mobileM} { - font-size: 20px; - } -` - -export const MiddleContainer = styled.div` - display: flex; - justify-content: center; - align-items: center; - margin: 25px 0 45px 0; - width: 420px; - height: 139px; - padding: 1px 20px; - background: rgba(123, 233, 128, 0.51); - border: 3px solid ${GREEN.border}; - border-radius: 20px; - - @media ${device.tablet} { - max-width: 380px; - } - - @media ${device.mobileL} { - max-width: 260px; - padding: 1px 14px; - margin: 15px 0 25px 0; - } -` - -export const MiddleText = styled.h4` - font-weight: 500; - font-size: 20px; - line-height: 24px; - text-align: start; - color: ${GREEN.text}; - - @media ${device.tablet} { - font-size: 19px; - } - - @media ${device.mobileL} { - font-size: 18px; - } - - @media ${device.mobileM} { - font-size: 17px; - } -` - -export const BackButton = styled.button` - font-weight: 700; - font-size: 28px; - color: ${BLACK.main}; - background: none; - border: none; - - &:hover { - cursor: pointer; - transition: 0.4s; - color: ${LIME.main}; - } - - @media ${device.mobileL} { - font-size: 18px; - } - - @media ${device.mobileM} { - font-size: 17px; - } -` - -export const ButtonContainer = styled.div` - display: flex; - gap: 34px; - align-items: center; - margin-top: 20px; -` diff --git a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js index c39ab97f1..5a2b65f92 100644 --- a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js +++ b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.js @@ -1,13 +1,16 @@ // * Modules +import { ThreeDots } from 'react-loader-spinner' import { useNavigate } from 'react-router-dom' import { Formik } from 'formik' +import { isEmpty } from 'lodash' -import resetApi from '../../../api/endpoints/reset' +import { useResetPasssword } from '../../../api/hooks/auth/useResetPassword' // * Assets import ArrowNavigateBack from '../../../assets/Arrows/ArrowNavigateBack' import ROUTES from '../../../constants/routes' import CustomButton from '../../../shared/components/CustomButton/CustomButton' -import CustomInput from '../../../shared/components/CustomInput/CustomInput' +import FlexWrapper from '../../../shared/components/FlexWrapper/FlexWrapper' +import CustomInput from '../../../shared/components/Formik/CustomInput/CustomInput' import { ButtonsContainer, @@ -22,68 +25,70 @@ import emailValidation from './RecoverValidation' const RecoverPassword2 = () => { const navigate = useNavigate() - const handleReset = async ({ email }) => { - try { - const isSuccess = await resetApi.getRegistrationEmail(email) - - if (!isSuccess) { - navigate(ROUTES.confirmEmail, { - replace: true, - state: { email }, - }) - } - } catch (err) { - console.log(err) - } - } + const { mutate: resetPassword, isLoading: isResetting } = useResetPasssword() return ( - <> - - + + + Recover Password Enter the email you used to register and we will send you link to reset your password - handleReset(values)} - > - {({ values }) => ( - - + + + resetPassword(email)} + > + {({ values, errors }) => ( + + + + + + {isResetting ? ( + + ) : ( + 'Reset password' + )} + - - - Reset password - - } - iconPosition="left" - border="2px solid #46A11B" - background="transparent" - fontSize="16px" - onClick={() => navigate(ROUTES.login, { replace: true })} - > - Back to Log in - - - - )} - - - - + } + iconPosition="left" + border="2px solid #46A11B" + background="transparent" + fontSize="16px" + onClick={() => navigate(ROUTES.login, { replace: true })} + > + Back to Log in + + + + )} + + + ) } diff --git a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js index d2648e5f1..dc5cf377e 100644 --- a/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js +++ b/client/src/components/Forms/RecoverPasswordForm/RecoverPasswordForm.styles.js @@ -5,30 +5,18 @@ import styled from 'styled-components' import { BLACK, GREEN, GREY, LIME, WHITE } from '../../../constants/colors' export const Container = styled.div` - width: 100vw; - height: 100vh; + width: 100%; + min-height: calc(100dvh - 88px); display: flex; justify-content: center; align-items: center; background: ${BLACK.background}; - position: relative; + padding: 48px 24px; ` export const RecoverForm = styled(Form)` width: 100%; ` -export const Navbar = styled.nav` - width: 100%; - height: 40px; - display: flex; - justify-content: space-between; - align-items: center; - position: absolute; - top: 0; - margin-top: 49px; - padding: 0 55px; -` - export const AccountActions = styled.div` display: flex; column-gap: 16px; @@ -53,9 +41,9 @@ export const NavigationLink = styled(NavLink)` ` export const RecoverBox = styled.div` - max-width: 370px; + max-width: 470px; width: 100%; - min-height: 327px; + gap: 48px; display: flex; flex-direction: column; align-items: center; @@ -64,7 +52,6 @@ export const RecoverTitle = styled.h3` font-size: 24px; font-weight: 500; color: ${GREEN.text}; - margin-bottom: 8px; text-align: center; ` export const RecoverText = styled.p` @@ -72,7 +59,6 @@ export const RecoverText = styled.p` font-weight: 400; color: ${WHITE.main}; text-align: center; - margin-bottom: 48px; ` export const ButtonsContainer = styled.div` @@ -82,3 +68,12 @@ export const ButtonsContainer = styled.div` row-gap: 16px; margin-top: 48px; ` + +export const FormWrapper = styled(Form)` + width: 100%; + display: flex; + justify-content: center; + align-items: center; + gap: 48px; + flex-direction: column; +` diff --git a/client/src/components/Forms/RecoverPasswordForm/RecoverValidation.js b/client/src/components/Forms/RecoverPasswordForm/RecoverValidation.js index ac9cfaaf6..fa010d8ce 100644 --- a/client/src/components/Forms/RecoverPasswordForm/RecoverValidation.js +++ b/client/src/components/Forms/RecoverPasswordForm/RecoverValidation.js @@ -2,7 +2,10 @@ import * as yup from 'yup' const emailValidation = yup.object().shape({ - email: yup.string().required('You forgot to input email 😁').email('Email is not valid.'), + email: yup + .string() + .required('You forgot to input email') + .email('Please enter a valid email address.'), }) export default emailValidation diff --git a/client/src/components/Profile/Profile.jsx b/client/src/components/Profile/Profile.jsx index b12f2b76c..b1dd1b79b 100644 --- a/client/src/components/Profile/Profile.jsx +++ b/client/src/components/Profile/Profile.jsx @@ -27,7 +27,6 @@ const Profile = () => { const { data: currentUser, isFetching } = useCheckAuth() const [isEditing, setIsEditing] = useState('') const [showingUser, setShowingUser] = useState(null) - const width = useGetScreenWidth() useEffect(() => { setShowingUser(data?.data) diff --git a/client/src/components/Profile/components/ProfileInfo/UserStatusButtons/UserStatusButtons.jsx b/client/src/components/Profile/components/ProfileInfo/UserStatusButtons/UserStatusButtons.jsx index d2206abc7..13d666c8d 100644 --- a/client/src/components/Profile/components/ProfileInfo/UserStatusButtons/UserStatusButtons.jsx +++ b/client/src/components/Profile/components/ProfileInfo/UserStatusButtons/UserStatusButtons.jsx @@ -1,6 +1,5 @@ import React from 'react' import { ThreeDots } from 'react-loader-spinner' -import { useFormikContext } from 'formik' import LongArrowLeft from '../../../../../assets/Arrows/LongArrowLeft' import AddUserIcon from '../../../../../assets/Shared/AddUserIcon' diff --git a/client/src/components/RegistrationPipeline/components/InitialPart/ParticlesContainer.jsx b/client/src/components/RegistrationPipeline/components/InitialPart/ParticlesContainer.jsx index 9b2e17af0..738de8a1b 100644 --- a/client/src/components/RegistrationPipeline/components/InitialPart/ParticlesContainer.jsx +++ b/client/src/components/RegistrationPipeline/components/InitialPart/ParticlesContainer.jsx @@ -4,16 +4,13 @@ import { loadFull } from 'tsparticles' export function ParticlesContainer() { const particlesInit = useCallback(async (engine) => { - console.log(engine) // you can initiate the tsParticles instance (engine) here, adding custom shapes or presets // this loads the tsparticles package bundle, it's the easiest method for getting everything ready // starting from v2 you can add only the features you need reducing the bundle size await loadFull(engine) }, []) - const particlesLoaded = useCallback(async (container) => { - await console.log(container) - }, []) + const particlesLoaded = useCallback(async (container) => {}, []) // using useMemo is not mandatory, but it's recommended since this value can be memoized if static const options = useMemo(() => { diff --git a/client/src/components/RegistrationPipeline/components/NavigationButtons/NavigationButtons.jsx b/client/src/components/RegistrationPipeline/components/NavigationButtons/NavigationButtons.jsx index f8e194649..7bcb14bc7 100644 --- a/client/src/components/RegistrationPipeline/components/NavigationButtons/NavigationButtons.jsx +++ b/client/src/components/RegistrationPipeline/components/NavigationButtons/NavigationButtons.jsx @@ -69,6 +69,7 @@ const NavigationButtons = ({ iconPosition="left" border="2px solid #46A11B" background="transparent" + maxWidth="170px" > {step === 1 ? 'Cancel' : 'Back'} @@ -85,6 +86,7 @@ const NavigationButtons = ({ icon={} iconPosition="right" background={GREEN.button} + maxWidth="170px" > {isOptionalStep && !oneOfOptionalFieldsHasValue ? 'Skip' @@ -100,6 +102,7 @@ const NavigationButtons = ({ icon={isFinishingRegistration ? null : } iconPosition="right" background={GREEN.button} + maxWidth="170px" > {isFinishingRegistration ? ( { return ( - <> + - - Log in - Sign up - - + ) } diff --git a/client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.styles.js b/client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.styles.js index decf2ea06..0892a7a0b 100644 --- a/client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.styles.js +++ b/client/src/layouts/ResetPasswordPageLayout/ResetPasswordPageLayout.styles.js @@ -1,19 +1,14 @@ import { NavLink } from 'react-router-dom' import styled from 'styled-components' -import { GREEN, WHITE } from '../../constants/colors' +import { BLACK, GREEN, WHITE } from '../../constants/colors' export const Navbar = styled.nav` width: 100%; - height: 40px; + height: 88px; display: flex; - justify-content: space-between; - align-items: center; - position: absolute; - top: 0; - margin-top: 49px; - padding: 0 55px; - z-index: 999; + justify-content: center; + align-items: end; ` export const AccountActions = styled.div` @@ -38,3 +33,13 @@ export const NavigationLinkActive = styled(NavigationLink)` color: ${GREEN.text}; border-bottom: 1px solid ${GREEN.border}; ` + +export const Container = styled.div` + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; + min-height: 100dvh; + width: 100%; + background: ${BLACK.background}; +` diff --git a/client/src/routes/routes.js b/client/src/routes/routes.js index dffd0971a..d7d60b8f7 100644 --- a/client/src/routes/routes.js +++ b/client/src/routes/routes.js @@ -19,7 +19,6 @@ import NoTeamScreen from '../screens/NoTeamScreen/NoTeamScreen' import ProfileScreen from '../screens/ProfileScreen/ProfileScreen' import RegistrationScreen from '../screens/RegistrationScreen/RegistrationScreen' import ResetNewPasswordsScreen from '../screens/ResetNewPasswordsScreen/ResetNewPasswordsScreen' -import ResetPasswordConfirmationScreen from '../screens/ResetPasswordConfirmationScreen/ResetPasswordConfirmationScreen' import ResetPasswordScreen from '../screens/ResetPasswordScreen/ResetPasswordScreen' import TeammatesScreen from '../screens/TeammatesScreen/TeammatesScreen' import TeamScreen from '../screens/TeamScreen/TeamScreen' @@ -55,7 +54,6 @@ export const useRoutes = () => { }> } /> } /> - } /> } /> diff --git a/client/src/screens/ResetPasswordConfirmationScreen/ResetPasswordConfirmationScreen.js b/client/src/screens/ResetPasswordConfirmationScreen/ResetPasswordConfirmationScreen.js deleted file mode 100644 index 61eeef62c..000000000 --- a/client/src/screens/ResetPasswordConfirmationScreen/ResetPasswordConfirmationScreen.js +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react' -import CssBaseline from '@mui/material/CssBaseline' - -import ResetFormConfirmation from '../../components/Forms/RecoverConfirmationForm/RecoverConfirmationForm' - -function ResetPasswordConfirmationScreen() { - return ( - <> - - - - ) -} - -export default ResetPasswordConfirmationScreen diff --git a/client/src/shared/components/CustomButton/CustomButon.styles.js b/client/src/shared/components/CustomButton/CustomButon.styles.js index b464e3df7..a4d01f07b 100644 --- a/client/src/shared/components/CustomButton/CustomButon.styles.js +++ b/client/src/shared/components/CustomButton/CustomButon.styles.js @@ -7,7 +7,7 @@ export const Button = styled.button` border: ${(props) => (props.border ? props.border : 'none')}; color: ${(props) => (props.transparent ? '#007bff' : '#fff')}; padding: 0.875rem 0; - max-width: 10.625rem; + max-width: ${(props) => props.maxWidth || 'none'}; width: 100%; border-radius: 10px; display: flex; diff --git a/client/src/shared/components/CustomButton/CustomButton.jsx b/client/src/shared/components/CustomButton/CustomButton.jsx index 9a39c8507..9e77493ea 100644 --- a/client/src/shared/components/CustomButton/CustomButton.jsx +++ b/client/src/shared/components/CustomButton/CustomButton.jsx @@ -8,10 +8,18 @@ const CustomButton = ({ icon, iconPosition, onClick, + maxWidth, ...props }) => { return ( -
- - - + Teameights - Find your first pet project! - + + + + body { diff --git a/client/src/assets/Shared/SearchingPeople.js b/client/src/assets/Shared/NonFound.js similarity index 100% rename from client/src/assets/Shared/SearchingPeople.js rename to client/src/assets/Shared/NonFound.js diff --git a/client/src/assets/Shared/SearchingPeople.jsx b/client/src/assets/Shared/SearchingPeople.jsx new file mode 100644 index 000000000..dc4ca01f0 --- /dev/null +++ b/client/src/assets/Shared/SearchingPeople.jsx @@ -0,0 +1,666 @@ +function SearchingPeople() { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ) +} + +export default SearchingPeople diff --git a/client/src/components/Forms/Page404Form/Page404Form.js b/client/src/components/Forms/Page404Form/Page404Form.js index 23e32a67f..64cd2890f 100644 --- a/client/src/components/Forms/Page404Form/Page404Form.js +++ b/client/src/components/Forms/Page404Form/Page404Form.js @@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom' import LongArrowLeft from '../../../assets/Arrows/LongArrowLeft' // * Assets -import Page404 from '../../../assets/Shared/SearchingPeople' +import Page404 from '../../../assets/Shared/NonFound' import FlexWrapper from '../../../shared/components/FlexWrapper/FlexWrapper' // * Styles diff --git a/client/src/components/Team/TeamsList/Teams/Teams.jsx b/client/src/components/Team/TeamsList/Teams/Teams.jsx index e2bc05f70..04336a50b 100644 --- a/client/src/components/Team/TeamsList/Teams/Teams.jsx +++ b/client/src/components/Team/TeamsList/Teams/Teams.jsx @@ -2,13 +2,15 @@ import { Fragment, useCallback, useEffect, useRef, useState } from 'react' import { useLoadTeams } from '../../../../api/hooks/team/useLoadTeams' import CardSkeleton from '../../../../shared/components/CardSkeleton/CardSkeleton' +import NotFound from '../../../Teammates/components/NotFound/NotFound' import { TeamsListBox, TeamsWrapper } from '../TeamsList.styles' import Desktop from './TeamData/TeamDataDesktop' import Mobile from './TeamData/TeamDataMobile' -const Teams = ({ handleClickOpen, setIsNotFound, isLoadingUserData, width }) => { +const Teams = ({ handleClickOpen, isLoadingUserData, width }) => { const intObserver = useRef() + const [isNotFound, setIsNotFound] = useState(false) const { fetchNextPage, @@ -73,11 +75,17 @@ const Teams = ({ handleClickOpen, setIsNotFound, isLoadingUserData, width }) => }) useEffect(() => { - if (isFetched && !content[0].length && !filtered) { + if (isFetched && !content[0].length) { setIsNotFound(true) + } else { + setIsNotFound(false) } }, [isFetched, content]) + if (isNotFound) { + return + } + return ( diff --git a/client/src/components/Team/TeamsList/TeamsList.js b/client/src/components/Team/TeamsList/TeamsList.js index f5f2b09b5..204c5ac68 100644 --- a/client/src/components/Team/TeamsList/TeamsList.js +++ b/client/src/components/Team/TeamsList/TeamsList.js @@ -28,11 +28,6 @@ function TeamsList() { let [changeModal, setChangeModal] = useState('') const { mutate: joinUser, isLoading: isUserTeamLoading } = useJoinTeam() - const [isNotFound, setIsNotFound] = useState(false) - - const handleComeback = () => { - setIsNotFound(false) - } const { leaveAndJoin, isLeaving, isJoining } = useLeaveAndJoin() @@ -75,14 +70,6 @@ function TeamsList() { await leaveAndJoin.mutateAsync({ leaveDetails, joinDetails }) } - // if (isUserTeamLoading || isLeaving || isJoining) { - // return ( - // - // - // - // ) - // } - return ( <> - {isNotFound ? ( - - - - ) : ( - - - - - )} + + + + ) } diff --git a/client/src/components/Team/TeamsList/TeamsList.styles.js b/client/src/components/Team/TeamsList/TeamsList.styles.js index 43d782169..a2b608fc1 100644 --- a/client/src/components/Team/TeamsList/TeamsList.styles.js +++ b/client/src/components/Team/TeamsList/TeamsList.styles.js @@ -134,17 +134,3 @@ export const TeamButton = styled.button` transform: translateY(-1.25px); } ` - -export const NotFoundContainer = styled.div` - display: flex; - justify-content: center; - align-items: center; - width: 100%; - min-height: calc(100vh - 238px); - /* height: 100%; */ - padding-left: 88px; - - @media screen and (max-width: 768px) { - padding-left: 0px; - } -` diff --git a/client/src/components/Teammates/Teammates.js b/client/src/components/Teammates/Teammates.js index 47257a901..e0aeb7184 100644 --- a/client/src/components/Teammates/Teammates.js +++ b/client/src/components/Teammates/Teammates.js @@ -29,11 +29,6 @@ function Teammates() { */ const [open, setOpen] = useState(false) const [showUser, setShowUser] = useState({}) - const [isNotFound, setIsNotFound] = useState(false) - - const handleComeback = () => { - setIsNotFound(false) - } /** * Get global state from redux @@ -79,25 +74,10 @@ function Teammates() { mobileProfile={open} handleClose={handleClose} /> - {/* If nothing was found, show user a NotFound container */} - {isNotFound ? ( - - - - ) : ( - - - - - - - - - )} + + + + ) } diff --git a/client/src/components/Teammates/components/Cards/Cards.js b/client/src/components/Teammates/components/Cards/Cards.js index 2b43db113..b534f3f36 100644 --- a/client/src/components/Teammates/components/Cards/Cards.js +++ b/client/src/components/Teammates/components/Cards/Cards.js @@ -1,5 +1,5 @@ // * Modules -import React, { useCallback, useEffect, useRef } from 'react' +import React, { useCallback, useEffect, useRef, useState } from 'react' // * Constants // * API import lookup from 'country-code-lookup' @@ -7,6 +7,9 @@ import lookup from 'country-code-lookup' import { useLoadUsers } from '../../../../api/hooks/temeights/useLoadUsers' import { useGetScreenWidth } from '../../../../hooks/useGetScreenWidth' import CardSkeleton from '../../../../shared/components/CardSkeleton/CardSkeleton' +import SliderToTop from '../../../../shared/components/SliderToTop/SliderToTop' +import { CardsContainer, GridContainer } from '../../Teammates.styles' +import NotFound from '../NotFound/NotFound' // * Components import UserCard from '../UserCard/UserCard' @@ -14,9 +17,9 @@ import UserCard from '../UserCard/UserCard' // * Styles import { CardContainer } from './Cards.styles' -const Cards = ({ handleOpen, isLoadingUseData, setIsNotFound }) => { +const Cards = ({ handleOpen, isLoadingUseData }) => { const intObserver = useRef() - const width = useGetScreenWidth() + const [isNotFound, setIsNotFound] = useState(false) const { fetchNextPage, @@ -103,21 +106,31 @@ const Cards = ({ handleOpen, isLoadingUseData, setIsNotFound }) => { }) }) - { - /* If nothing was found, show user a NotFound container */ - } - useEffect(() => { - if (isFetched && !content[0].length && !filtered) { + if (isFetched && !content[0].length) { setIsNotFound(true) + } else { + setIsNotFound(false) } }, [isFetched, content]) + { + /* If nothing was found, show user a NotFound container */ + } + if (isNotFound) { + return + } + return ( <> - {content} - {/* Load skeleton before showing real cards to improve performance of the app */} - {(isFetchingNextPage || isLoadingUseData || isLoading) && } + + + {content} + {/* Load skeleton before showing real cards to improve performance of the app */} + {(isFetchingNextPage || isLoadingUseData || isLoading) && } + + + ) } diff --git a/client/src/components/Teammates/components/NotFound/NotFound.js b/client/src/components/Teammates/components/NotFound/NotFound.js index 3824c97f8..7d7bf894e 100644 --- a/client/src/components/Teammates/components/NotFound/NotFound.js +++ b/client/src/components/Teammates/components/NotFound/NotFound.js @@ -1,32 +1,23 @@ // * Assets -import NonFound from '../../../../assets/Shared/SearchingPeople' // * Styles -import { - BotText, - Button, - Container, - InfoContainer, - NonFoundContainer, - TextContainer, - TopText, -} from './NotFound.styles' +import SearchingPeople from '../../../../assets/Shared/SearchingPeople' +import FlexWrapper from '../../../../shared/components/FlexWrapper/FlexWrapper' -const NotFound = ({ handleComeback }) => { +import { Container, NonFoundContainer, Text } from './NotFound.styles' + +const NotFound = () => { return ( - - No results found. - - - We can’t find any item matching your search - - - - - + + + {`No results found :(`} + + We can’t find any item matching your search + + ) } diff --git a/client/src/components/Teammates/components/NotFound/NotFound.styles.js b/client/src/components/Teammates/components/NotFound/NotFound.styles.js index c55cabeb7..4e7112183 100644 --- a/client/src/components/Teammates/components/NotFound/NotFound.styles.js +++ b/client/src/components/Teammates/components/NotFound/NotFound.styles.js @@ -3,120 +3,24 @@ import styled from 'styled-components' export const Container = styled.div` width: 100%; + min-height: calc(100vh - 238px); display: flex; - justify-content: center; align-items: center; - margin-bottom: 70px; - - @media screen and (max-width: 980px) { - display: flex; - flex-direction: column; - } -` - -export const TopText = styled.h2` - font-weight: 700; - color: white; - text-align: center; - font-size: 42px; - margin: 0 0 20px 0; - - @media screen and (min-width: 980px) and (max-width: 1250px) { - font-size: 32px; - } - - @media screen and (min-width: 510px) and (max-width: 980px) { - font-size: 30px; - margin: 20px 0 20px 0; - } - - @media screen and (min-width: 0) and (max-width: 510px) { - font-size: 23px; - } + flex-direction: column; + gap: 36px; + padding: 0 24px 48px 24px; ` -export const BotText = styled.h2` - font-weight: 400; +export const Text = styled.h2` + font-weight: ${(props) => props.fontWeight || '500'}; color: white; text-align: center; - font-size: 25px; - margin: 0 0 30px 0; - - @media screen and (min-width: 980px) and (max-width: 1250px) { - font-size: 23px; - } - - @media screen and (min-width: 510px) and (max-width: 980px) { - font-size: 20px; - } - - @media screen and (min-width: 0) and (max-width: 510px) { - font-size: 17px; - } -` - -export const Button = styled.button` - border: none; - cursor: pointer; - width: 211px; - height: 55px; - background: #5d9d0b; - box-shadow: 0px 0px 50px rgba(93, 157, 11, 0.15); - border-radius: 5px; - font-weight: 700; - color: white; - font-size: 16px; - transition: 0.3s ease; - - &:hover { - -webkit-transform: scale(1.05); - -ms-transform: scale(1.05); - transform: scale(1.05); - } -` - -export const InfoContainer = styled.div` - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - margin-right: 50px; - - @media screen and (min-width: 980px) and (max-width: 1250px) { - margin-right: 20px; - } - - @media screen and (min-width: 0) and (max-width: 980px) { - order: 2; - margin: 70px 0 0 0; - } -` - -export const TextContainer = styled.div` - max-width: 360px; + font-size: ${(props) => props.fontSize || '24px'}; + margin: 0; ` export const NonFoundContainer = styled.div` - width: 675px; - height: 400px; - margin-bottom: 20px; - - @media screen and (min-width: 980px) and (max-width: 1250px) { - width: 600px; - height: 350px; - } - - @media screen and (min-width: 510px) and (max-width: 980px) { - order: 1; - margin-bottom: 0; - width: 453px; - height: 257px; - } - - @media screen and (min-width: 0) and (max-width: 510px) { - order: 1; - margin-bottom: 0; - width: 310px; - height: 183px; - } + width: 100%; + max-width: 650px; + height: auto; ` diff --git a/client/src/layouts/NavBarItemPageLayout/NavbarItemPageLayout.styles.js b/client/src/layouts/NavBarItemPageLayout/NavbarItemPageLayout.styles.js index 8543b9492..739b5cfa6 100644 --- a/client/src/layouts/NavBarItemPageLayout/NavbarItemPageLayout.styles.js +++ b/client/src/layouts/NavBarItemPageLayout/NavbarItemPageLayout.styles.js @@ -9,5 +9,5 @@ export const Container = styled.div` align-items: center; min-height: 100vh; width: 100%; - background: ${BLACK.background}; + /* background: ${BLACK.background}; */ ` From f6b0124533dc0d43eee0ee89c063fe092a177b53 Mon Sep 17 00:00:00 2001 From: Nikita Mashchenko <52038455+exortme1ster@users.noreply.github.com> Date: Mon, 10 Jul 2023 05:25:49 -0500 Subject: [PATCH 09/10] fix: netlify error --- client/src/components/Team/TeamsList/TeamsList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/Team/TeamsList/TeamsList.js b/client/src/components/Team/TeamsList/TeamsList.js index 204c5ac68..8eceeb034 100644 --- a/client/src/components/Team/TeamsList/TeamsList.js +++ b/client/src/components/Team/TeamsList/TeamsList.js @@ -16,7 +16,7 @@ import NotFound from '../../Teammates/components/NotFound/NotFound' import Teams from './Teams/Teams' // * Styles -import { Container, NotFoundContainer, TeamCardModal } from './TeamsList.styles' +import { Container } from './TeamsList.styles' function TeamsList() { let { data: user, isLoading: isLoadingUserData } = useCheckAuth() From 961e391333b21f4d0bc0e5427727136be2457eb8 Mon Sep 17 00:00:00 2001 From: Nikita Mashchenko <52038455+exortme1ster@users.noreply.github.com> Date: Mon, 10 Jul 2023 05:29:42 -0500 Subject: [PATCH 10/10] fix: link tag --- client/public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/public/index.html b/client/public/index.html index 0a3072514..c0bd53ef4 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -20,7 +20,7 @@ property="og:image" content="https://i.ibb.co/y8MRSbY/Logo-T8-S-image.png" /> -