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