From 5b10ccde55f9baf656847b9c040d8aa35aa9e2e4 Mon Sep 17 00:00:00 2001 From: razzanYoni <13521087@mahasiswa.itb.ac.id> Date: Fri, 17 Nov 2023 02:59:27 +0700 Subject: [PATCH] feat : add context --- src/TonalityApp.tsx | 10 +++++- src/components/sidebar.tsx | 62 +++++++++++++++++++++-------------- src/context/AuthProvider.tsx | 40 ++++++++++++++++++++++ src/routes/ProtectedRoute.tsx | 9 +++-- src/routes/RenderRoutes.tsx | 27 ++++++++++----- 5 files changed, 111 insertions(+), 37 deletions(-) create mode 100644 src/context/AuthProvider.tsx diff --git a/src/TonalityApp.tsx b/src/TonalityApp.tsx index 7051a29..7a6f9b8 100644 --- a/src/TonalityApp.tsx +++ b/src/TonalityApp.tsx @@ -2,12 +2,20 @@ import './App.css' import React from 'react' import { RenderRoutes } from "@/routes/RenderRoutes.tsx"; import {routes} from "@/routes/routes.ts"; +import AuthProvider from "@/context/AuthProvider.tsx"; + +export const AuthContext = React.createContext(null) + +export const useAuth = () => React.useContext(AuthContext) export const Routes = RenderRoutes(routes) const TonalityApp = () => { + return ( - <Routes isAuthorized={true}/> + <AuthProvider> + <Routes/> + </AuthProvider> ) } export default TonalityApp diff --git a/src/components/sidebar.tsx b/src/components/sidebar.tsx index 4fd0b00..8bf509c 100644 --- a/src/components/sidebar.tsx +++ b/src/components/sidebar.tsx @@ -1,36 +1,48 @@ import logo from '../assets/images/logo.svg'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faPlayCircle, faUser, } from '@fortawesome/free-solid-svg-icons'; -import { useNavigate } from 'react-router-dom'; +import {NavLink} from "react-router-dom"; +// import {useAuth} from "@/TonalityApp.tsx"; +// import {NavLink, useNavigate} from 'react-router-dom'; // import profile from '../assets/images/user.png'; const Sidebar = () => { - const navigate = useNavigate(); - - const toPremAlbum = () => { - navigate('/album'); - } + // TODO : Add logout functionality + // const { token, onLogout } = useAuth(); return ( - <div className="sidebar text-white w-200 flex fixed flex-col items-center top-0 left-0 h-full border-r border-opacity-10 border-gray-300 pr-6"> - <div className="sidebar-header flex items-center"> - <img src={logo} alt="Tonality Logo" className="logo" /> - <h2 className='title font-bold text-4xl'>Tonality</h2> - </div> - <div className="menu h-screen"> - <ul className='text-left'> - <li className="mb-2 hover:bg-gray-700 p-2 rounded cursor-pointer flex items-center" onClick={toPremAlbum}> - <FontAwesomeIcon icon={faPlayCircle} className="mr-2" /> Premium Albums - </li> - <li className="mb-2 hover:bg-gray-700 p-2 rounded cursor-pointer flex items-center"> - <FontAwesomeIcon icon={faUser} className="mr-2" /> Subscription - </li> - </ul> - </div> - <div className="user-profile flex mb-10 items-center text-left justify-items-left hover:bg-gray-700 p-2 rounded cursor-pointer"> - <FontAwesomeIcon icon={faUser} className="mr-2" /> Username - </div> - </div> + <nav> + <div className="sidebar text-white w-200 flex fixed flex-col items-center top-0 left-0 h-full border-r border-opacity-10 border-gray-300 pr-6"> + <div className="sidebar-header flex items-center"> + <img src={logo} alt="Tonality Logo" className="logo" /> + <h2 className='title font-bold text-4xl'>Tonality</h2> + </div> + <div className="menu h-screen"> + <nav> + <ul className='text-left'> + <NavLink to="/album" className="mb-2 hover:bg-gray-700 p-2 rounded cursor-pointer flex items-center"> + <FontAwesomeIcon icon={faPlayCircle} className="mr-2" /> Premium Albums + </NavLink> + <NavLink to="/subscription" className="mb-2 hover:bg-gray-700 p-2 rounded cursor-pointer flex items-center"> + <FontAwesomeIcon icon={faUser} className="mr-2" /> Subscription + </NavLink> + </ul> + </nav> + </div> + <div className="user-profile flex mb-5 items-center text-left justify-items-left "> + <FontAwesomeIcon icon={faUser} className="mr-2" /> Username + </div> + { + // TODO : Add logout functionality + // token && + // <button className="btn btn-primary mb-10 text-red-600 font-bold hover:bg-gray-700 p-2 rounded cursor-pointer" onClick={onLogout}> + <button className="btn btn-primary mb-10 text-red-600 font-bold hover:bg-gray-700 p-2 rounded cursor-pointer"> + Logout + </button> + } + </div> + </nav> + ); }; diff --git a/src/context/AuthProvider.tsx b/src/context/AuthProvider.tsx new file mode 100644 index 0000000..131886d --- /dev/null +++ b/src/context/AuthProvider.tsx @@ -0,0 +1,40 @@ +import React from 'react'; +import {AuthContext} from "@/TonalityApp.tsx"; +import {useNavigate} from "react-router-dom"; + +const AuthProvider = ({ children }) => { + const navigate = useNavigate(); + + const [accessToken, setAccessToken] = React.useState(null); + + if (window.localStorage.getItem('accessToken')) { + setAccessToken(window.localStorage.getItem('accessToken')); + navigate('/album') + } + + const handleLogin = (accessToken) => { + window.localStorage.setItem('accessToken', accessToken); + setAccessToken(accessToken); + navigate('/album') + }; + + const handleLogout = () => { + window.localStorage.removeItem('accessToken'); + setAccessToken(null); + navigate('/login') + } + + const value = { + token: accessToken, + onLogin: handleLogin, + onLogout: handleLogout, + } + + return ( + <AuthContext.Provider value={value}> + {children} + </AuthContext.Provider> + ); +}; + +export default AuthProvider; \ No newline at end of file diff --git a/src/routes/ProtectedRoute.tsx b/src/routes/ProtectedRoute.tsx index fb1da95..c1e81a4 100644 --- a/src/routes/ProtectedRoute.tsx +++ b/src/routes/ProtectedRoute.tsx @@ -1,6 +1,9 @@ -import { Navigate, Outlet } from 'react-router-dom'; -const ProtectedRoute = ({ isPublic, isAuthorized}) => { - return (isPublic || isAuthorized) ? <Outlet/> : <Navigate to="/login" /> +import {Navigate, Outlet,} from 'react-router-dom'; +import {useAuth} from "@/TonalityApp.tsx"; + +const ProtectedRoute = ({isPublic}) => { + const isValidUser : boolean = useAuth().token === null; + return (isValidUser || isPublic) ? <Outlet/> : <Navigate to='/login'/> } export default ProtectedRoute; \ No newline at end of file diff --git a/src/routes/RenderRoutes.tsx b/src/routes/RenderRoutes.tsx index e10430a..5e4cf51 100644 --- a/src/routes/RenderRoutes.tsx +++ b/src/routes/RenderRoutes.tsx @@ -7,24 +7,35 @@ export const RenderRoutes : React.FC = (mainRoutes) => { const layouts = mainRoutes.map(({layout: Layout, routes}, index) => { const subRoutes = generateFlattenRoutes(routes); + subRoutes.map(({component: Component, path, name}) => { + console.log('component', Component) + console.log('path', path) + console.log('name', name) + }) + return ( <Route key={index} element={<Layout/>}> - <Route element={<ProtectedRoute isAuthorized={isAuthorized}/>}> - {subRoutes.map(({component: Component, path, name}) => { - return ( - Component + {subRoutes.map(({component: Component, path, name, isPublic}, index) => { + const isPublics : boolean = typeof isPublic === 'boolean' ? isPublic : false; + const componentFound = Component !== undefined; + if (!componentFound) return null; + + return ( + (<Route key={index} element={<ProtectedRoute isPublic={isPublics} isAuthorized={isAuthorized}/>}>) + && Component && path && (<Route key={name} element={<Component/>} path={path}/>) - ) - })} - </Route> + && (</Route>) + ) + })} </Route> ) }); + console.log('layouts', layouts) return ( <Routes> <> - {layouts} + {layouts} </> </Routes> ); -- GitLab