diff --git a/front-end/peer-prep/src/components/UserPage/index.tsx b/front-end/peer-prep/src/components/UserPage/index.tsx index ac5393f0..1ee7ab1e 100644 --- a/front-end/peer-prep/src/components/UserPage/index.tsx +++ b/front-end/peer-prep/src/components/UserPage/index.tsx @@ -1,211 +1,299 @@ import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; -import * as Styles from "./styles" -import { TextField, Avatar, Snackbar, - IconButton, Button, Dialog, - DialogTitle, DialogActions, DialogContent, DialogContentText } from "@mui/material"; -import SaveIcon from '@mui/icons-material/Save'; -import CloseIcon from '@mui/icons-material/Close'; +import * as Styles from "./styles"; +import { + TextField, + Avatar, + Snackbar, + IconButton, + Button, + Dialog, + DialogTitle, + DialogActions, + DialogContent, + DialogContentText, +} from "@mui/material"; +import SaveIcon from "@mui/icons-material/Save"; +import CloseIcon from "@mui/icons-material/Close"; import { useDispatch, useSelector } from "react-redux"; -import * as UserSlice from "../redux/reducers/User/UserSlice" +import * as UserSlice from "../redux/reducers/User/UserSlice"; import axios from "axios"; import { auth } from "../Auth/Firebase"; const UserPage = () => { - // for dispatching actions - const dispatch = useDispatch() - const navigate = useNavigate() - - // State for pop up box after editing user profile. - const [isEditSuccess, setIsEditSuccess] = useState(false) - const [hasEmptyDetails, setHasEmptyDetails] = useState(false) - - // State for deletion conformation pop up. - const [deletionConfimation, setDeletionConfirmation] = useState(false) - - // Gets user details from firebase. - const user = auth.currentUser; - const authEmail = user?.providerData[0].email ?? "" - - const authUsername = user?.displayName ?? "" - const authUid = user?.uid - - const isNewUser = useSelector(UserSlice.selectIsFirstTimeLogin) - const currentUsername:string = useSelector(UserSlice.selectCurrentUsername) - const currentEmail:string = useSelector(UserSlice.selectCurrentEmail) - const currentFirstName:string = useSelector(UserSlice.selectCurrentFirstName) - const currentLastName:string = useSelector(UserSlice.selectCurrentLastName) - const currentAge:number = useSelector(UserSlice.selectCurrentAge) - - // Messages for user. - const EditUserSuccess = "User profile edited!" - const PromptUserDetails = "Please enter user details." - const EmptyDetailsWarning = "User details cannot be empty!" - - // Gets user profile data. - useEffect(() => { - axios({ - method: 'get', - url: `https://api.peerprepgroup51sem1y2023.xyz/users/${authUid}` - }).then((response) => { - const data = response.data.data; - dispatch(UserSlice.updateUserData(data)) - }).catch((error) => { - dispatch(UserSlice.updateCurrentEmail(authEmail)) - dispatch(UserSlice.updateCurrentUsername(authUsername)) - }) - },[]) - - const openEditSuccessSnackbar = () => { - setIsEditSuccess(true) - }; - - const closeEditSuccessSnackbar = () => { - setIsEditSuccess(false) - }; - - const openDeleteConfirmation = () => { - setDeletionConfirmation(true) - } - - const closeDeleteConfirmation = () => { - setDeletionConfirmation(false) - } - - // First time creation for new user if user does not exist. - const postUserData = () => { - axios.post(`https://api.peerprepgroup51sem1y2023.xyz/users/`, { - username: currentUsername, - email: currentEmail, - firstName: currentFirstName, - lastName: currentLastName, - age: currentAge, - uid: authUid - }) - .then(() => { - setHasEmptyDetails(false) - dispatch(UserSlice.setIsFirstTimeLogin(false)) - }) - .catch((error) => { - const code = error.request.status - if (code === 400) { - setHasEmptyDetails(true) - } - }); - } - - // Updates user data after editing. - const putUserData = () => axios.put(`https://api.peerprepgroup51sem1y2023.xyz/users/${authUid}`, - { - "username": currentUsername, - "email": currentEmail, - "firstName": currentFirstName, - "lastName": currentLastName, - "age": currentAge, - "uid": authUid - }).then(() => { - setHasEmptyDetails(false) - }) - .catch((error) => { - const code = error.request.status - if (code === 400) { - setHasEmptyDetails(true) - } - }) - - const handleEditUserData = () => { - isNewUser ? postUserData() : putUserData() - openEditSuccessSnackbar() - } - - // Deletes user data from postgres database. - const deleteUserData = () => { - axios.delete(`https://api.peerprepgroup51sem1y2023.xyz/users/${authUid}`) - .catch(() => {}) - } - - // Deletes user data from firebase. - const deleteFirebaseUserData = () => { - if (user) { - user.delete() - } - } - - const handleDeleteUser = () => { - closeDeleteConfirmation() - navigate("/delete") - deleteUserData() - deleteFirebaseUserData() - } - - return ( -
-
-
-
- -
- dispatch(UserSlice.updateCurrentUsername(event.target.value))}> - dispatch(UserSlice.updateCurrentEmail(event.target.value))}> - dispatch(UserSlice.updateCurrentFirstName(event.target.value))}> - dispatch(UserSlice.updateCurrentLastName(event.target.value))}> - dispatch(UserSlice.updateCurrentAge(event.target.value))}> - handleEditUserData()}> - - - - - - - }/> - - - - - {"Delete account?"} - - - - Are you sure you want to delete your account? - - - - - - - -
-
-
- ) -} + // for dispatching actions + const dispatch = useDispatch(); + const navigate = useNavigate(); + + // State for pop up box after editing user profile. + const [isEditSuccess, setIsEditSuccess] = useState(false); + const [hasEmptyDetails, setHasEmptyDetails] = useState(false); + + // State for deletion conformation pop up. + const [deletionConfimation, setDeletionConfirmation] = useState(false); + + // Gets user details from firebase. + const user = auth.currentUser; + const authEmail = user?.providerData[0].email ?? ""; + + const authUsername = user?.displayName ?? ""; + const authUid = user?.uid; + + const isNewUser = useSelector(UserSlice.selectIsFirstTimeLogin); + const currentUsername: string = useSelector( + UserSlice.selectCurrentUsername + ); + const currentEmail: string = useSelector(UserSlice.selectCurrentEmail); + const currentFirstName: string = useSelector( + UserSlice.selectCurrentFirstName + ); + const currentLastName: string = useSelector( + UserSlice.selectCurrentLastName + ); + const currentAge: number = useSelector(UserSlice.selectCurrentAge); + + // Messages for user. + const EditUserSuccess = "User profile edited!"; + const PromptUserDetails = "Please enter user details."; + const EmptyDetailsWarning = "User details cannot be empty!"; + + // Gets user profile data. + useEffect(() => { + axios({ + method: "get", + url: `https://api.peerprepgroup51sem1y2023.xyz/users/${authUid}`, + }) + .then((response) => { + const data = response.data.data; + dispatch(UserSlice.updateUserData(data)); + }) + .catch((error) => { + dispatch(UserSlice.updateCurrentEmail(authEmail)); + dispatch(UserSlice.updateCurrentUsername(authUsername)); + }); + }, []); + + const openEditSuccessSnackbar = () => { + setIsEditSuccess(true); + }; + + const closeEditSuccessSnackbar = () => { + setIsEditSuccess(false); + }; + + const openDeleteConfirmation = () => { + setDeletionConfirmation(true); + }; + + const closeDeleteConfirmation = () => { + setDeletionConfirmation(false); + }; + + // First time creation for new user if user does not exist. + const postUserData = () => { + axios + .post(`https://api.peerprepgroup51sem1y2023.xyz/users/`, { + username: currentUsername, + email: currentEmail, + firstName: currentFirstName, + lastName: currentLastName, + age: currentAge, + uid: authUid, + }) + .then(() => { + setHasEmptyDetails(false); + dispatch(UserSlice.setIsFirstTimeLogin(false)); + }) + .catch((error) => { + const code = error.request.status; + if (code === 400) { + setHasEmptyDetails(true); + } + }); + }; + + // Updates user data after editing. + const putUserData = () => + axios + .put(`https://api.peerprepgroup51sem1y2023.xyz/users/${authUid}`, { + username: currentUsername, + email: currentEmail, + firstName: currentFirstName, + lastName: currentLastName, + age: currentAge, + uid: authUid, + }) + .then(() => { + setHasEmptyDetails(false); + }) + .catch((error) => { + const code = error.request.status; + if (code === 400) { + setHasEmptyDetails(true); + } + }); + + const handleEditUserData = () => { + isNewUser ? postUserData() : putUserData(); + openEditSuccessSnackbar(); + }; + + // Deletes user data from postgres database. + const deleteUserData = () => { + axios + .delete(`https://api.peerprepgroup51sem1y2023.xyz/users/${authUid}`) + .catch(() => {}); + }; + + // Deletes user data from firebase. + const deleteFirebaseUserData = () => { + if (user) { + user.delete(); + } + }; + + const handleDeleteUser = () => { + closeDeleteConfirmation(); + navigate("/delete"); + deleteUserData(); + deleteFirebaseUserData(); + }; + + return ( +
+
+
+
+ +
+ + dispatch( + UserSlice.updateCurrentUsername( + event.target.value + ) + ) + } + > + + dispatch( + UserSlice.updateCurrentEmail(event.target.value) + ) + } + > + + dispatch( + UserSlice.updateCurrentFirstName( + event.target.value + ) + ) + } + > + + dispatch( + UserSlice.updateCurrentLastName( + event.target.value + ) + ) + } + > + + dispatch( + UserSlice.updateCurrentAge(event.target.value) + ) + } + > + handleEditUserData()} + > + + + + + + + } + /> + + + + + {"Delete account?"} + + + + Are you sure you want to delete your account? + + + + + + + +
+
+
+ ); +}; export default UserPage; diff --git a/services/profile-service/src/controller/user-controller.ts b/services/profile-service/src/controller/user-controller.ts index 0b5177f2..21ea0198 100644 --- a/services/profile-service/src/controller/user-controller.ts +++ b/services/profile-service/src/controller/user-controller.ts @@ -18,6 +18,7 @@ const ERR_MSG_BAD_REQUEST = const ERR_MSG_AGE_NEGATIVE = "Invalid age: Age cannot be negative."; const ERR_MSG_DUPLICATE = "Update a resource that already exists or has conflicting information"; +const ERR_MSG_AGE_TOO_LARGE = "Invalid age: too large"; //helper function to validate data async function validateData(userData: iUserData): Promise { @@ -39,6 +40,9 @@ async function validateData(userData: iUserData): Promise { if (userData.age < 0) { return ERR_MSG_AGE_NEGATIVE; } + if (userData.age >= 1000) { + return ERR_MSG_AGE_TOO_LARGE; + } return null; }