From d817cb48964fa6024968d248760292c697ed58a5 Mon Sep 17 00:00:00 2001 From: Vinay Anand Lodhi Date: Wed, 23 Oct 2024 15:31:33 +0530 Subject: [PATCH] private routes and hospital page added --- client/src/components/Navbar.jsx | 269 +++++++++++------------ client/src/privateroute/privateroute.jsx | 25 +-- client/src/store/userContext.jsx | 8 +- 3 files changed, 147 insertions(+), 155 deletions(-) diff --git a/client/src/components/Navbar.jsx b/client/src/components/Navbar.jsx index 9791d49..258115f 100644 --- a/client/src/components/Navbar.jsx +++ b/client/src/components/Navbar.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback } from 'react'; +import React, { useState, useEffect, useCallback, useContext } from 'react'; import { NavLink } from 'react-router-dom'; import { IoMenu, IoClose } from 'react-icons/io5'; import { @@ -7,20 +7,25 @@ import { FaHospital, FaUserPlus, FaHospitalAlt, -} from 'react-icons/fa'; // Import FaHospitalAlt +} from 'react-icons/fa'; import { AiOutlineInfoCircle } from 'react-icons/ai'; import { MdOutlineLocalHospital, MdLogin, MdDarkMode } from 'react-icons/md'; import { WiDaySunny } from 'react-icons/wi'; import { useRecoilState } from 'recoil'; import { mode } from '../store/atom'; +import { UserContext } from '../store/userContext'; import PropTypes from 'prop-types'; +import { FiUser } from 'react-icons/fi'; // New icon for user placeholder -const Navbar = ({ isAuthenticated, user, handleLogout }) => { +const Navbar = () => { const [isMobileMenuOpen, setMobileMenuOpen] = useState(false); const [dark, setDark] = useRecoilState(mode); const [isNavbarVisible, setNavbarVisible] = useState(true); const [lastScrollY, setLastScrollY] = useState(0); + // Access isAuthenticated, user, and handleLogout from UserContext + const { isAuthenticated, user, handleLogout } = useContext(UserContext); + const toggleMobileMenu = () => setMobileMenuOpen(!isMobileMenuOpen); const handleToggleMode = () => { @@ -98,6 +103,7 @@ const Navbar = ({ isAuthenticated, user, handleLogout }) => { {dark === 'light' ? : } + {/* Navbar Links */} `${isActive ? 'border-b border-white ' : ''} flex gap-2 items-baseline` @@ -119,106 +125,94 @@ const Navbar = ({ isAuthenticated, user, handleLogout }) => {

About

- - `${isActive ? 'border-b border-white ' : ''} flex gap-2 items-baseline` - } - to="/labtest" - onClick={() => setMobileMenuOpen(false)} - > - {' '} -

Lab Tests

-
- - `${isActive ? 'border-b border-white ' : ''} flex gap-2 items-baseline` - } - to="/blog" - onClick={() => setMobileMenuOpen(false)} - > - {' '} -

Blogs

-
- - - `${isActive ? 'border-b border-white ' : ''} flex gap-2 items-baseline` - } - to="/hospitals-around" - onClick={() => setMobileMenuOpen(false)} - > - -

- Hospitals Around -

-
+ {/* Conditional Links */} + {!isAuthenticated && ( + + `${isActive ? 'border-b border-white ' : ''} flex gap-2 items-baseline` + } + to="/hospitals" + onClick={() => setMobileMenuOpen(false)} + > + +

Hospitals

+
+ )} - {isAuthenticated ? ( + {/* Show Lab Tests and Hospitals Around for regular user */} + {isAuthenticated && user?.role === 'user' && ( <> `${isActive ? 'border-b border-white ' : ''} flex gap-2 items-baseline` } - to="/profile" + to="/labtest" + onClick={() => setMobileMenuOpen(false)} + > + +

Lab Tests

+
+ + + `${isActive ? 'border-b border-white ' : ''} flex gap-2 items-baseline` + } + to="/hospitals-around" onClick={() => setMobileMenuOpen(false)} > - +

- Profile + Hospitals Around

- {user && user?.role === 'user' && ( - - `${isActive ? 'border-b border-white ' : ''} flex gap-2 items-baseline` - } - to="/hospitals" - onClick={() => setMobileMenuOpen(false)} - > - -

- Hospitals -

-
- )} - {user && user?.role === 'hospital' && ( - - `${isActive ? 'border-b border-white ' : ''} flex gap-2 items-baseline` - } - to="/panel" - onClick={() => setMobileMenuOpen(false)} - > - -

- OPD Panel -

-
- )} - ) : ( + )} + + {/* Show only Hospitals Around for hospital */} + {isAuthenticated && user?.role === 'hospital' && ( - `${isActive ? 'border-b border-white ' : ''} flex items-center gap-2` + `${isActive ? 'border-b border-white ' : ''} flex gap-2 items-baseline` } - to="/registerOPD" + to="/hospitals-around" onClick={() => setMobileMenuOpen(false)} > - +

- Instant OPD + Hospitals Around

)} {isAuthenticated ? ( - + <> + {/* Profile Avatar with Name */} +
+ {/* Check if the user has an avatar, else use a placeholder */} + {user?.avatar ? ( + User Avatar + ) : ( +
+ +
+ )} + + {user?.name || user?.hospitalName} + +
+ + + ) : (
{

Home

+ {

About

- - {' '} -

Blog

-
- - {' '} -

Lab Test

-
- - {/* Add the new Hospitals Around Link for Desktop */} - - -

- Hospitals Around -

-
+ {/* Conditional Links */} + {!isAuthenticated && ( + + +

Hospitals

+
+ )} - {isAuthenticated ? ( + {/* Show Lab Tests and Hospitals Around for regular user */} + {isAuthenticated && user?.role === 'user' && ( <> - - -

Profile

+ + +

Lab Test

+
+ + + +

+ Hospitals Around +

- {user && user?.role === 'user' && ( - - -

- Hospitals -

-
- )} - {user && user?.role === 'hospital' && ( - - -

- OPD Panel -

-
- )} - ) : ( - - + )} + + {/* Show only Hospitals Around for hospital */} + {isAuthenticated && user?.role === 'hospital' && ( + +

- Instant OPD + Hospitals Around

)} -
-
- {localStorage?.getItem('token') ? ( - + {isAuthenticated ? ( + <> + {/* Profile Avatar with Name */} +
+ {/* Check if the user has an avatar, else use a placeholder */} + {user?.avatar ? ( + User Avatar + ) : ( +
+ +
+ )} + + {user?.name || user?.hospitalName} + +
+ + + ) : (
{ }; Navbar.propTypes = { - isAuthenticated: PropTypes.bool, user: PropTypes.object, - handleLogout: PropTypes.func, }; export default Navbar; diff --git a/client/src/privateroute/privateroute.jsx b/client/src/privateroute/privateroute.jsx index 97e0f27..8bb0a72 100644 --- a/client/src/privateroute/privateroute.jsx +++ b/client/src/privateroute/privateroute.jsx @@ -1,21 +1,16 @@ -import { useState, useEffect } from 'react'; -import { Outlet } from 'react-router-dom'; +import { useContext } from 'react'; +import { Outlet, Navigate } from 'react-router-dom'; import Spinner from './spinner'; +import { UserContext } from '../store/userContext'; // Import the UserContext export default function PrivateRoute() { - const [ok, setOk] = useState(false); - useEffect(() => { - const AuthCheck = async () => { - const user = localStorage.getItem('userid'); + const { isAuthenticated, loading } = useContext(UserContext); // Get auth and loading state from context - if (user) { - setOk(true); - } else { - setOk(false); - } - }; - AuthCheck(); - }, []); + // While checking authentication (loading), show Spinner + if (loading) { + return ; + } - return ok ? : ; + // If authenticated, show the protected route, otherwise redirect to login + return isAuthenticated ? : ; } diff --git a/client/src/store/userContext.jsx b/client/src/store/userContext.jsx index 05fbc6d..991885b 100644 --- a/client/src/store/userContext.jsx +++ b/client/src/store/userContext.jsx @@ -10,6 +10,7 @@ export const UserContext = createContext(); export const UserProvider = ({ children }) => { const [isAuthenticated, setAuth] = useState(false); const [user, setUser] = useState(null); + const [loading, setLoading] = useState(true); // Add loading state const location = useLocation(); // Get location const fetchProfile = async () => { @@ -20,6 +21,7 @@ export const UserProvider = ({ children }) => { // If no token, consider the user as not authenticated setAuth(false); setUser(null); + setLoading(false); // Stop loading when no token is found return; } @@ -51,6 +53,7 @@ export const UserProvider = ({ children }) => { setAuth(false); setUser(null); } + setLoading(false); // Stop loading once profile fetch is complete }; useEffect(() => { @@ -67,14 +70,13 @@ export const UserProvider = ({ children }) => { return ( - {console.log(isAuthenticated)} {children} ); }; -UserProvider.prototype = { +UserProvider.propTypes = { children: PropTypes.node, };