diff --git a/src/App.tsx b/src/App.tsx index 7e653dd89733f63f5054024644fdfcad2b199131..fb97289880e8f9997f3b30b3718fbc7fc1240fd5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -19,7 +19,7 @@ function App() { const isRegisterPage = location.pathname === '/register'; return ( <div className="App"> - {!isLoginPage && !isRegisterPage && <Navbar/>} + {<Navbar/>} <Routes> <Route path="/" element={<Home />} /> <Route path="/consultation" element={<Consultation />} /> diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 43f3c8351bb7c91811c00bf01ec7d87b9227f385..63750654d77deecbbc9a1c8d283577a5e991254b 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1,24 +1,77 @@ -import React from 'react' -import { Link } from 'react-router-dom' +import React, { useState } from 'react'; +import { Link, useNavigate } from 'react-router-dom'; +import { Avatar, Menu, MenuItem } from '@mui/material'; import '../styles/Navbar.css'; const Navbar = () => { + const navigate = useNavigate(); + const [dropdownVisible, setDropdownVisible] = useState(false); + const closeDropdown = () => { + setDropdownVisible(false); + }; + const toggleDropdown = () => { + setDropdownVisible(!dropdownVisible); + }; + + const user = localStorage.getItem('user') || 'null'; + + const handleLogout = () => { + localStorage.removeItem('user'); + localStorage.removeItem('jwt'); + console.log('Logging out...'); + console.log('User:', localStorage.getItem('user')); + console.log('Token:', localStorage.getItem('jwt')); + navigate('/login'); + }; + + + return ( <nav className="navbar"> - <div className="logo"> - <img src="SayIt.svg" alt="logo" /> - </div> - <div className="nav-links"> - <ul> - <li><Link to="/">Home</Link></li> - <li><Link to="/consultation">Consultation</Link></li> - <li><Link to="/report">History</Link></li> - <button className='signinButton'><Link to="/login">Signin</Link></button> - - </ul> - </div> - </nav> - ) -} + <div className='navbarContainer'> + <div className="logo"> + <img src="SayIt.svg" alt="logo" /> + </div> + <div className="nav-links"> + <ul> + <li><Link to="/">Home</Link></li> + <li><Link to="/consultation">Consultation</Link></li> + <li><Link to="/report">History</Link></li> + {localStorage.getItem('user') !== null ? ( + <> + + <div className="avatarContainer" > + <button className='avatarButton' onClick={() => toggleDropdown()}> + <Avatar + className="avatar" + + + > + {user.charAt(0).toUpperCase()} + </Avatar> + </button> + {dropdownVisible && ( + <div className="dropdownWrap"> + <div className="dropdown" onClick={() => closeDropdown()}> + <button onClick={() => navigate('/profile')}>Profile</button> + <button onClick={handleLogout}>Sign Out</button> + </div> + </div> + )} + </div> + </> + ) : ( + <li> + <button className='signinButton'> + <Link to="/login">Sign In</Link> + </button> + </li> + )} + </ul> + </div> + </div> + </nav> + ); +}; -export default Navbar \ No newline at end of file +export default Navbar; diff --git a/src/pages/Consultation.tsx b/src/pages/Consultation.tsx index e151a3bf34fcfbf4d36361e491f7a7c0a688e88f..07ba5a088be6eb6aa76633f6b85908eae487d2c2 100644 --- a/src/pages/Consultation.tsx +++ b/src/pages/Consultation.tsx @@ -1,13 +1,14 @@ -import React, { useEffect, useState } from 'react'; -import { Link } from 'react-router-dom'; +import React, { useEffect, useState} from 'react'; import axios from 'axios'; import DatePicker from 'react-datepicker'; import 'react-datepicker/dist/react-datepicker.css'; import '../styles/Consultation.css'; import Modal from '@mui/material/Modal'; import Box from '@mui/material/Box'; -import { Alert, AlertIcon, AlertTitle, Flex, ModalHeader, Text, Button} from '@chakra-ui/react'; +import {Flex, Text, Button} from '@chakra-ui/react'; import { Snackbar } from '@mui/material'; +import { Link, useNavigate } from 'react-router-dom'; + type Psychologist = { @@ -20,26 +21,57 @@ type Psychologist = { }; const Consultation = () => { - const [psychologists, setPsychologists] = useState<Psychologist[]>([]); - const [selectedPsychologist, setSelectedPsychologist] = useState<Psychologist | null>(null); - const [selectedDate, setSelectedDate] = useState<Date | null>(null); - const [selectedTime, setSelectedTime] = useState<string>(''); - - const fetchPsiko = () => { - return axios.get('http://localhost:3000/psikolog/consultation') - .then((response) => setPsychologists(response.data.data)); - }; - - useEffect(() => { - fetchPsiko(); - }, []); - - const handleBookClick = (psychologist: Psychologist) => { - setOpen(true); - setSelectedPsychologist(psychologist); - setSelectedDate(null); - setSelectedTime(''); - }; + const [psychologists, setPsychologists] = useState<Psychologist[]>([]); + const [selectedPsychologist, setSelectedPsychologist] = useState<Psychologist | null>(null); + const [selectedDate, setSelectedDate] = useState<Date | null>(null); + const [selectedTime, setSelectedTime] = useState<string>(''); + const navigate = useNavigate(); + axios.interceptors.response.use( + (response) => response, + (error) => { + if (error.response && error.response.status === 401) { + + console.log('Unauthorized - Redirecting to login page'); + localStorage.removeItem('user'); + localStorage.removeItem('jwt'); + window.location.replace('/login'); + } + return Promise.reject(error); + } + ); + useEffect(() => { + const user = localStorage.getItem('user'); + + if (!user) { + navigate('/login'); + alert('Anda harus login terlebih dahulu untuk mengakses halaman ini'); + } else { + + const token = localStorage.getItem('jwt') + axios.defaults.headers.common['Authorization'] = `Bearer ${token}`; + console.log('Token:', token); + console.log('User:', user); + fetchPsiko(); + } + }, [navigate]); + + + const fetchPsiko = () => { + return axios.get('http://localhost:3000/user/consultation') + .then((response) => setPsychologists(response.data.data)); + }; + + useEffect(() => { + fetchPsiko(); + }, []); + + const handleBookClick = (psychologist: Psychologist) => { + setOpen(true); + setSelectedPsychologist(psychologist); + setSelectedDate(null); + setSelectedTime(''); + }; + const handleDateChange = (date: Date | null) => { setSelectedDate(date); diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index bd036ee6ec16b41558bd442cad9932a9e827456e..fb5d5f7f42a3cf21a9b61d50270d662568bddd5e 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -11,7 +11,7 @@ const Login = () => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [isLoading, setIsLoading] = useState(false); - + const [error, setError] = useState(''); const [showPassword, setShowPassword] = React.useState(false); const history = useNavigate(); const handleClickShowPassword = () => { @@ -27,15 +27,21 @@ const Login = () => { console.log(email, password); try { - axios.post('http://localhost:3000/psikolog/login/', { - email: email, - password: password, + const response = await axios.post('http://localhost:3000/psikolog/login/', { + psikolog_email: email, + psikolog_password: password, }); - history('/register'); - } - catch (error) { - console.log(error); + localStorage.setItem('jwt', response.data.token); + localStorage.setItem('user', response.data.user.psikolog_name); + console.log('Response:', response.data); + if (response.data !== "failed") { + history('/'); } + } catch (error) { + + setError('Email not registered or wrong password'); + console.error(error); + } }; return ( diff --git a/src/pages/Register.tsx b/src/pages/Register.tsx index c6032764b088917c71deb0cc6885dec77c302323..e983d325b6861f1b347a42d058619545b906e7fc 100644 --- a/src/pages/Register.tsx +++ b/src/pages/Register.tsx @@ -15,7 +15,7 @@ const Register = () => { const [password, setPassword] = useState(''); const [clinic, setClinic] = useState(''); const [isLoading, setIsLoading] = useState(false); - + const navigate = useNavigate(); const [error, setError] = useState(''); const [showPassword, setShowPassword] = React.useState(false); const [showConfirmPassword, setShowConfirmPassword] = React.useState(false); @@ -50,9 +50,11 @@ const Register = () => { psikolog_password: password, psikolog_klinik: clinic, }); - + navigate('/login'); + console.log('Response:', response); if (response.status === 200) { - history('/login/'); + // Registrasi berhasil, arahkan pengguna ke halaman login + navigate('/login'); } else { console.log('Registration failed:', response); } @@ -60,6 +62,7 @@ const Register = () => { catch (error) { console.log(error); } + }; return ( diff --git a/src/styles/Navbar.css b/src/styles/Navbar.css index 11182dbcda39e82000ba7fc471863818e687666c..e2234c65caec9dac21acba6836e33540b1754779 100644 --- a/src/styles/Navbar.css +++ b/src/styles/Navbar.css @@ -1,11 +1,16 @@ .navbar { background-image: linear-gradient(to bottom, #4560A6 ,#313e61); color: #fff; - padding: 10px 0; display: flex; + width: 100%; + } + .navbarContainer{ justify-content: space-between; align-items: center; width: 100%; + padding: 15px; + margin-top: 0px; + display: flex; } .logo { @@ -48,4 +53,64 @@ font-size: 16px; font-weight: bold; } - \ No newline at end of file + + .avatar{ + height: 40px; + width: 40px; + border-radius: 50%; + margin-right: 10px; + +} +.avatarButton { + background: none; + border: none; + cursor: pointer; + display: flex; + align-items: center; +} +.dropdownWrap{ + max-height: 0px; + overflow: hidden; + transition: max-height 0.2s ease-out; +} +.dropdown { + position: absolute; + right: 20px; + top: 75px; + background: #F3AA98; + color: black; + border-radius: 7px; + width: 120px; + height: 50px; + /* padding: 8px; */ + display: flex; + flex-direction: column; + z-index: 2; + font-size: 16px; + justify-content: center; + gap: 5px; + +} + +.dropdown button { + + background: #F3AA98; + border: none; + border-radius: 5px; + background: transparent; + +} +.dropdown button:hover { + /* background: whitesmoke; */ + cursor: pointer; + transition: 0.3s; + color: whitesmoke; + +} +.dropdown { + display: flex; +} + +.dropdownVisible .dropdown { + display: flex; +} \ No newline at end of file