From 350517623ae64e2c5deae9b68440100c0e9a189f Mon Sep 17 00:00:00 2001 From: Andrew Trieu Date: Sun, 16 Jul 2023 20:14:44 +0300 Subject: [PATCH] Login and register page --- README.md | 1 + client/src/scenes/loginPage/Form.jsx | 276 ++++++++++++++++++++++++++ client/src/scenes/loginPage/index.jsx | 35 +++- 3 files changed, 309 insertions(+), 3 deletions(-) create mode 100644 client/src/scenes/loginPage/Form.jsx diff --git a/README.md b/README.md index 15ea86d..3ae2f1f 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,4 @@ Table: | 13.07.2023 | Setup frontend | 6 | | 13.07.2023 | Theme and styling | 10 | | 14.07.2023 | Navbar | 10 | +| 16.07.2023 | Login and register page | 20 | diff --git a/client/src/scenes/loginPage/Form.jsx b/client/src/scenes/loginPage/Form.jsx new file mode 100644 index 0000000..90106cf --- /dev/null +++ b/client/src/scenes/loginPage/Form.jsx @@ -0,0 +1,276 @@ +import { useState } from "react"; +import { + Box, + Typography, + Button, + TextField, + useTheme, + useMediaQuery, +} from "@mui/material"; +import EditOutlinedIcon from "@mui/icons-material/EditOutlined"; +import { Formik } from "formik"; +import * as yup from "yup"; +import { useNavigate } from "react-router-dom"; +import { useDispatch } from "react-redux"; +import { setLogin } from "state"; +import Dropzone from "react-dropzone"; +import FlexBetween from "components/FlexBetween"; + +const registerSchema = yup.object().shape({ + firstName: yup.string().required("First name is required"), + lastName: yup.string().required("Last name is required"), + email: yup.string().email("Invalid email").required("Email is required"), + password: yup.string().required("Password is required"), + location: yup.string(), + description: yup.string(), + profilePicture: yup.string(), +}); + +const loginSchema = yup.object().shape({ + email: yup.string().email("Invalid email").required("Email is required"), + password: yup.string().required("Password is required"), +}); + +const initialRegisterValues = { + firstName: "", + lastName: "", + email: "", + password: "", + location: "", + description: "", + profilePicture: "", +}; + +const initialLoginValues = { + email: "", + password: "", +}; + +const Form = () => { + const [pageType, setPageType] = useState("login"); + const { palette } = useTheme(); + const dispatch = useDispatch(); + const navigate = useNavigate(); + const isNotMobile = useMediaQuery("(min-width: 600px)"); + const isLogin = pageType === "login"; + const isRegister = pageType === "register"; + + const register = async (values, onSubmitProps) => { + const formData = new FormData(); + for (const key in values) { + formData.append(key, values[key]); + } + formData.append("profilePicturePath", values.profilePicture.name); + + const savedUserResponse = await fetch( + "http://localhost:3001/auth/register", + { + method: "POST", + body: formData, + } + ); + + const savedUser = await savedUserResponse.json(); + onSubmitProps.resetForm(); + + if (savedUser) { + setPageType("login"); + } + }; + + const login = async (values, onSubmitProps) => { + const loggedInUserResponse = await fetch( + "http://localhost:3001/auth/login", + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(values), + } + ); + + const loggedInUser = await loggedInUserResponse.json(); + onSubmitProps.resetForm(); + + if (loggedInUser) { + dispatch(setLogin({ user: loggedInUser, token: loggedInUser.token })); + navigate("/home"); + } + }; + + const handleFormSubmit = async (values, onSubmitProps) => { + if (isLogin) { + await login(values, onSubmitProps); + } + if (isRegister) { + await register(values, onSubmitProps); + } + }; + + return ( + + {({ + values, + errors, + touched, + handleChange, + handleBlur, + handleSubmit, + setFieldValue, + resetForm, + }) => ( +
+ div": { gridColumn: isNotMobile ? undefined : "span 4" }, + }} + > + {isRegister && ( + <> + + + + + + { + setFieldValue("profilePicture", acceptedFiles[0]); + }} + > + {({ getRootProps, getInputProps }) => ( + + + {!values.profilePicture ? ( +

Add your profile photo here

+ ) : ( + + + {values.profilePicture.name} + + + + )} +
+ )} +
+
+ + )} + + +
+ {/* Buttons */} + + + { + setPageType(isLogin ? "register" : "login"); + resetForm(); + }} + sx={{ + textDecoration: "underline", + color: palette.primary.main, + "&:hover": { cursor: "pointer", color: palette.primary.light }, + }} + > + {isLogin + ? "Don't have an account? Register here" + : "Already have an account? Login here"} + + +
+ )} +
+ ); +}; + +export default Form; diff --git a/client/src/scenes/loginPage/index.jsx b/client/src/scenes/loginPage/index.jsx index a33982d..4c57028 100644 --- a/client/src/scenes/loginPage/index.jsx +++ b/client/src/scenes/loginPage/index.jsx @@ -1,7 +1,36 @@ +import { Box, Typography, useTheme, useMediaQuery } from "@mui/material"; +import Form from "./Form"; + const LoginPage = () => { - return ( -
loginpage
- ) + const theme = useTheme(); + const isNotMobile = useMediaQuery("(min-width: 1000px)"); + + return ( + + + + ChatHive + + + + + Welcome to ChatHive, where great minds meet! + +
+ + + ); }; export default LoginPage;