Added Private route and global store
This commit is contained in:
@@ -10,25 +10,27 @@ import Bookmark from "./pages/Bookmark";
|
||||
import VotingPage from "./pages/VotingPage";
|
||||
import CreatePollForm from "./pages/CreatePollForm";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
import PrivateRoute from "./components/PrivateRoute/PrivateRoute";
|
||||
|
||||
function App() {
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<BrowserRouter>
|
||||
<Header />
|
||||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route path="dashboard" element={<Dashboard />} />
|
||||
<Route path="bookmark" element={<Bookmark />} />
|
||||
<Route path="/voting/:pollId" element={<VotingPage />} />
|
||||
<Route path="/create" element={<CreatePollForm />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
<BrowserRouter>
|
||||
<Header />
|
||||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route path="/register" element={<Register />} />
|
||||
<Route element={<PrivateRoute />}>
|
||||
<Route path="dashboard" element={<Dashboard />} />
|
||||
<Route path="bookmark" element={<Bookmark />} />
|
||||
<Route path="/voting/:pollId" element={<VotingPage />} />
|
||||
<Route path="/create" element={<CreatePollForm />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import useUserStore from '../../store/useStore'
|
||||
import ProfileImage from './ProfileImage';
|
||||
|
||||
function Header() {
|
||||
|
||||
const {user} = useUserStore();
|
||||
|
||||
return (
|
||||
<div className="navbar bg-base-100">
|
||||
<div className="flex-1">
|
||||
@@ -10,32 +14,11 @@ function Header() {
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<ul className="menu menu-horizontal px-1">
|
||||
<li><Link to={"/login"}>Login</Link></li>
|
||||
{user.username ? <li><Link to={"/dashboard"}>Dashboard</Link></li> : <li><Link to={"/login"}>Login</Link></li>}
|
||||
<li><Link to={'/bookmark'}>Bookmarks</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<div className="dropdown dropdown-end">
|
||||
<div tabIndex={0} role="button" className="btn btn-ghost btn-circle avatar">
|
||||
<div className="w-10 rounded-full">
|
||||
<img
|
||||
alt="Tailwind CSS Navbar component"
|
||||
src="https://img.daisyui.com/images/stock/photo-1534528741775-53994a69daeb.webp" />
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
tabIndex={0}
|
||||
className="menu menu-sm dropdown-content bg-base-100 rounded-box z-[1] mt-3 w-52 p-2 shadow">
|
||||
<li>
|
||||
<Link to={'/dashboard'} className="justify-between" >
|
||||
Profile
|
||||
<span className="badge">New</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li><a>Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{user.username && <ProfileImage userData={user}/>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
41
frontend/src/components/Header/ProfileImage.jsx
Normal file
41
frontend/src/components/Header/ProfileImage.jsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import useUserStore from '../../store/useStore';
|
||||
|
||||
function ProfileImage({userData}) {
|
||||
|
||||
const {setUser} = useUserStore();
|
||||
|
||||
const handleLogout = () => {
|
||||
setUser({});
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className="flex-none">
|
||||
<div className="dropdown dropdown-end">
|
||||
<div tabIndex={0} role="button" className="btn btn-ghost btn-circle avatar">
|
||||
<div className="w-10 rounded-full">
|
||||
<img
|
||||
alt="Tailwind CSS Navbar component"
|
||||
src="https://img.daisyui.com/images/stock/photo-1534528741775-53994a69daeb.webp" />
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
tabIndex={0}
|
||||
className="menu menu-sm dropdown-content bg-base-100 rounded-box z-[1] mt-3 w-52 p-2 shadow">
|
||||
<li className='font-bold'><a >{userData?.username || "User"}</a></li>
|
||||
<li>
|
||||
<Link to={'/dashboard'} className="justify-between" >
|
||||
Profile
|
||||
<span className="badge">New</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li><a onClick={handleLogout}>Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProfileImage
|
||||
16
frontend/src/components/PrivateRoute/PrivateRoute.jsx
Normal file
16
frontend/src/components/PrivateRoute/PrivateRoute.jsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import React from 'react'
|
||||
import useUserStore from '../../store/useStore';
|
||||
import { Navigate, Outlet } from 'react-router-dom';
|
||||
|
||||
function PrivateRoute() {
|
||||
|
||||
const {user} = useUserStore();
|
||||
|
||||
return (
|
||||
<div>
|
||||
{user.username ? <Outlet/> : <Navigate to={'/login'}/>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PrivateRoute
|
||||
@@ -1,10 +1,12 @@
|
||||
import React from 'react'
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import useStore from '../store/useStore';
|
||||
|
||||
function Home() {
|
||||
|
||||
const navigator = useNavigate();
|
||||
|
||||
|
||||
return (
|
||||
<div className="flex bg-base-200 min-h-screen flex-col items-center text-white p-8">
|
||||
<h1 className="text-4xl mt-2 md:text-5xl font-bold mb-6 text-center flex flex-col gap-2 md:block">Welcome to <span className='bg-slate-800 px-4 rounded-md relative'>LivePoll</span></h1>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Link, useNavigate } from 'react-router-dom';
|
||||
import { loginService } from '../services/loginService';
|
||||
import SpinnerLoader from '../components/Loaders/SpinnerLoader';
|
||||
import InlineTextError from '../components/Errors/InlineTextError';
|
||||
import useUserStore from '../store/useStore';
|
||||
|
||||
const LoginPage = () => {
|
||||
|
||||
@@ -12,8 +13,11 @@ const LoginPage = () => {
|
||||
const [password, setPassword] = useState('');
|
||||
const navigator = useNavigate();
|
||||
|
||||
let {setUser} = useUserStore()
|
||||
|
||||
const mutation = useMutation(loginService, {
|
||||
onSuccess: (data) => {
|
||||
setUser(data?.user);
|
||||
setEmail('');
|
||||
setPassword('');
|
||||
navigator('/');
|
||||
|
||||
18
frontend/src/store/useStore.js
Normal file
18
frontend/src/store/useStore.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import {create} from "zustand"
|
||||
import {createJSONStorage, persist} from "zustand/middleware"
|
||||
|
||||
const useUserStore = create(persist((set) => {
|
||||
return {
|
||||
user : {},
|
||||
setUser : (user) => set(() => {
|
||||
return {
|
||||
user : user
|
||||
}
|
||||
}),
|
||||
}
|
||||
}, {
|
||||
name: "livepoll",
|
||||
storage: createJSONStorage(() => localStorage),
|
||||
}));
|
||||
|
||||
export default useUserStore;
|
||||
Reference in New Issue
Block a user