diff --git a/src/components/Layout/Navbar/Navbar.tsx b/src/components/Layout/Navbar/Navbar.tsx index efc17b87..54605b49 100644 --- a/src/components/Layout/Navbar/Navbar.tsx +++ b/src/components/Layout/Navbar/Navbar.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useContext, useState } from 'react'; import { AlignRightOutlined, @@ -11,12 +11,23 @@ import { Button, Col, Row, Space, Typography } from 'antd'; import styles from './Navbar.module.css'; import MenuDrawer from '../MenuDrawer/MenuDrawer'; import LoginModal from '../../LoginModal'; +import RegisterModal from '../../RegisterModal'; + +import { + UserContext, + type UserContextType, +} from './../../../contexts/UserContext'; +import LogoutModal from '../../LogoutModal'; const { Text } = Typography; const Navbar: React.FC = () => { const [openMenu, setOpenMenu] = useState(false); const [isLoginModalVisible, setIsLoginModalVisible] = useState(false); + const [isRegisterModalVisible, setIsRegisterModalVisible] = useState(false); + const [isLogoutModalVisible, setIsLogoutModalVisible] = useState(false); + + const { user } = useContext(UserContext) as UserContextType; const handleLoginModalClose = (): void => { setIsLoginModalVisible(false); @@ -26,6 +37,22 @@ const Navbar: React.FC = () => { setIsLoginModalVisible(true); }; + const handleRegisterModalClose = (): void => { + setIsRegisterModalVisible(false); + }; + + const handleRegisterModalOpen = (): void => { + setIsRegisterModalVisible(true); + }; + + const handleLogoutModalClose = (): void => { + setIsLogoutModalVisible(false); + }; + + const handleLogoutModalOpen = (): void => { + setIsLogoutModalVisible(true); + }; + return ( <> @@ -41,7 +68,7 @@ const Navbar: React.FC = () => { setOpenMenu(true); }} /> - +
@@ -99,19 +126,40 @@ const Navbar: React.FC = () => { - + {user === null ? ( + <> + + + + ) : ( + + )} {isLoginModalVisible ? ( - + + ) : null} + {isRegisterModalVisible ? ( + ) : null} + {isLogoutModalVisible && } ); }; diff --git a/src/components/LoginModal/index.tsx b/src/components/LoginModal/index.tsx index 10ba4bf6..9dfc4ab3 100644 --- a/src/components/LoginModal/index.tsx +++ b/src/components/LoginModal/index.tsx @@ -7,10 +7,10 @@ import closeIcon from '../../assets/svg/closeIcon.svg'; import styles from './LoginModal.module.css'; interface LoginModalProps { - onClose: () => void; + handleClose: () => void; } -const LoginModal: React.FC = ({ onClose }) => { +const LoginModal: React.FC = ({ handleClose }) => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const { setUserContext } = useContext(UserContext) as UserContextType; @@ -31,7 +31,7 @@ const LoginModal: React.FC = ({ onClose }) => { ) .then((response: AxiosResponse) => { setUserContext(response.data); - onClose(); + handleClose(); }) .catch((error) => { if (error.response.status !== 401) { @@ -64,7 +64,7 @@ const LoginModal: React.FC = ({ onClose }) => { > diff --git a/src/components/LogoutModal/index.tsx b/src/components/LogoutModal/index.tsx new file mode 100644 index 00000000..6434fdcc --- /dev/null +++ b/src/components/LogoutModal/index.tsx @@ -0,0 +1,73 @@ +import React, { useContext } from 'react'; +import { UserContext, type UserContextType } from '../../contexts/UserContext'; +import axios from 'axios'; +import { API_URL } from '../../constants'; + +interface LogoutModalProps { + onClose: () => void; +} + +const LogoutModal: React.FC = ({ onClose }) => { + const { setUserContext } = useContext(UserContext) as UserContextType; + + const handleLogoutConfirm = (): void => { + axios + .get(`${API_URL}/auth/logout`, { + withCredentials: true, + }) + .then(() => { + setUserContext(null); + onClose(); + }) + .catch((error) => { + if (error.response.status !== 401) { + console.error({ + message: 'Something went wrong during logout', + description: error.toString(), + }); + } else { + setUserContext(null); + onClose(); + } + }); + }; + + return ( +
+
+
+
+
+ +
+
+

+ Are you sure you want to logout from ScholarX? +

+ + +
+
+
+
+ ); +}; + +export default LogoutModal; diff --git a/src/components/RegisterModal/index.tsx b/src/components/RegisterModal/index.tsx new file mode 100644 index 00000000..dbc66594 --- /dev/null +++ b/src/components/RegisterModal/index.tsx @@ -0,0 +1,178 @@ +import React, { useState } from 'react'; +import axios from 'axios'; +import { API_URL } from '../../constants'; +import closeIcon from '../../assets/svg/closeIcon.svg'; + +interface RegisterModalProps { + handleClose: () => void; +} + +const RegisterModal: React.FC = ({ handleClose }) => { + const [firstName, setFirstName] = useState(''); + const [lastName, setLastName] = useState(''); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + const [error, setError] = useState(null); + + const handleRegister = (e: React.FormEvent): void => { + e.preventDefault(); + setError(null); + + axios + .post( + `${API_URL}/auth/register`, + { + email, + password, + first_name: firstName, + last_name: lastName, + }, + { + withCredentials: true, + } + ) + .then(() => { + handleClose(); + }) + .catch((error) => { + if (error.response.status !== 401) { + setError(error.response.data.message); + console.error({ + message: 'Something went wrong when registering the user', + description: error, + }); + } else { + console.error('Registration error:', error); + } + }); + }; + + return ( +
+
+
+
+
+ + ​ +
+ + +
+

+ Register to ScholarX +

+
+
+ +
+ { + setFirstName(e.target.value); + }} + required + /> + { + setLastName(e.target.value); + }} + required + /> +
+
+
+ + { + setEmail(e.target.value); + }} + required + /> +
+
+ + { + setPassword(e.target.value); + }} + required + /> +
+ + {error !== null ? ( +
+ {error} +
+ ) : null} + + +
+ Already have an account?{' '} + Login +
+
+
+
+
+
+ ); +}; + +export default RegisterModal;