From 700b0136fc774f75347c2d500348741dab6ca68d Mon Sep 17 00:00:00 2001 From: Manik Maity Date: Fri, 8 Nov 2024 18:53:34 +0530 Subject: [PATCH] Added Private route and global store --- frontend/package-lock.json | 38 +++++++++++++++-- frontend/package.json | 3 +- frontend/src/App.jsx | 28 +++++++------ frontend/src/components/Header/Header.jsx | 29 +++---------- .../src/components/Header/ProfileImage.jsx | 41 +++++++++++++++++++ .../components/PrivateRoute/PrivateRoute.jsx | 16 ++++++++ frontend/src/pages/Home.jsx | 2 + frontend/src/pages/LoginPage.jsx | 4 ++ frontend/src/store/useStore.js | 18 ++++++++ 9 files changed, 138 insertions(+), 41 deletions(-) create mode 100644 frontend/src/components/Header/ProfileImage.jsx create mode 100644 frontend/src/components/PrivateRoute/PrivateRoute.jsx create mode 100644 frontend/src/store/useStore.js diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5430781..6b814ae 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -15,7 +15,8 @@ "react-dom": "^18.3.1", "react-icons": "^5.3.0", "react-query": "^3.39.3", - "react-router-dom": "^6.27.0" + "react-router-dom": "^6.27.0", + "zustand": "^5.0.1" }, "devDependencies": { "@eslint/js": "^9.13.0", @@ -1399,14 +1400,14 @@ "version": "15.7.13", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.12", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -2081,7 +2082,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/culori": { @@ -5955,6 +5956,35 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.1.tgz", + "integrity": "sha512-pRET7Lao2z+n5R/HduXMio35TncTlSW68WsYBq2Lg1ASspsNGjpwLAsij3RpouyV6+kHMwwwzP0bZPD70/Jx/w==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } } } } diff --git a/frontend/package.json b/frontend/package.json index 047adf3..1ed2b0c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,7 +17,8 @@ "react-dom": "^18.3.1", "react-icons": "^5.3.0", "react-query": "^3.39.3", - "react-router-dom": "^6.27.0" + "react-router-dom": "^6.27.0", + "zustand": "^5.0.1" }, "devDependencies": { "@eslint/js": "^9.13.0", diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 8f3d095..8283dc3 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -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 ( - -
- - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - + +
+ + } /> + } /> + } /> + }> + } /> + } /> + } /> + } /> + + + ); } diff --git a/frontend/src/components/Header/Header.jsx b/frontend/src/components/Header/Header.jsx index 978250d..f6f03a7 100644 --- a/frontend/src/components/Header/Header.jsx +++ b/frontend/src/components/Header/Header.jsx @@ -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 (
@@ -10,32 +14,11 @@ function Header() {
    -
  • Login
  • + {user.username ?
  • Dashboard
  • :
  • Login
  • }
  • Bookmarks
-
-
-
-
- Tailwind CSS Navbar component -
-
-
    -
  • - - Profile - New - -
  • -
  • Logout
  • -
-
-
+ {user.username && }
) } diff --git a/frontend/src/components/Header/ProfileImage.jsx b/frontend/src/components/Header/ProfileImage.jsx new file mode 100644 index 0000000..19f355e --- /dev/null +++ b/frontend/src/components/Header/ProfileImage.jsx @@ -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 ( +
+
+
+
+ Tailwind CSS Navbar component +
+
+ +
+
+ ) +} + +export default ProfileImage diff --git a/frontend/src/components/PrivateRoute/PrivateRoute.jsx b/frontend/src/components/PrivateRoute/PrivateRoute.jsx new file mode 100644 index 0000000..b6000e6 --- /dev/null +++ b/frontend/src/components/PrivateRoute/PrivateRoute.jsx @@ -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 ( +
+ {user.username ? : } +
+ ) +} + +export default PrivateRoute diff --git a/frontend/src/pages/Home.jsx b/frontend/src/pages/Home.jsx index d6f1aed..35fbbd9 100644 --- a/frontend/src/pages/Home.jsx +++ b/frontend/src/pages/Home.jsx @@ -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 (

Welcome to LivePoll

diff --git a/frontend/src/pages/LoginPage.jsx b/frontend/src/pages/LoginPage.jsx index 4fa7276..feafa1c 100644 --- a/frontend/src/pages/LoginPage.jsx +++ b/frontend/src/pages/LoginPage.jsx @@ -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('/'); diff --git a/frontend/src/store/useStore.js b/frontend/src/store/useStore.js new file mode 100644 index 0000000..45c3d02 --- /dev/null +++ b/frontend/src/store/useStore.js @@ -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; \ No newline at end of file