From 2cb149f3c2c89f32cd958094c4c36b32023226fc Mon Sep 17 00:00:00 2001 From: calisio Date: Wed, 23 Oct 2024 11:29:24 -0500 Subject: [PATCH] feat: add facility context switch and ui --- backend/src/handlers/auth.go | 6 +- frontend/src/Components/Navbar.tsx | 210 ++++++++++++------- frontend/src/Components/PageNav.tsx | 91 ++++---- frontend/src/Layouts/AuthenticatedLayout.tsx | 2 +- frontend/src/Pages/AdminDashboard.tsx | 12 +- frontend/src/Pages/StudentManagement.tsx | 11 +- frontend/src/app.tsx | 7 +- frontend/src/routeLoaders.ts | 16 +- 8 files changed, 209 insertions(+), 146 deletions(-) diff --git a/backend/src/handlers/auth.go b/backend/src/handlers/auth.go index c1e6a1ab..003c3ff6 100644 --- a/backend/src/handlers/auth.go +++ b/backend/src/handlers/auth.go @@ -213,11 +213,15 @@ func (srv *Server) validateOrySession(r *http.Request) (*Claims, bool, error) { if !ok { passReset = true } + var facilityName string + if err := srv.Db.Model(&models.Facility{}).Select("name").Where("id = ?", facilityId).Find(&facilityName).Error; err != nil { + return nil, hasCookie, err + } claims := &Claims{ Username: user.Username, UserID: user.ID, FacilityID: uint(facilityId), - FacilityName: user.Facility.Name, + FacilityName: facilityName, PasswordReset: passReset, KratosID: kratosID, Role: user.Role, diff --git a/frontend/src/Components/Navbar.tsx b/frontend/src/Components/Navbar.tsx index 1e95578b..acef6e82 100644 --- a/frontend/src/Components/Navbar.tsx +++ b/frontend/src/Components/Navbar.tsx @@ -10,11 +10,16 @@ import { HomeIcon, RectangleStackIcon, TrophyIcon, - UsersIcon + UsersIcon, + ArrowRightEndOnRectangleIcon, + SunIcon, + MoonIcon, + UserCircleIcon } from '@heroicons/react/24/solid'; -import { useAuth } from '@/useAuth'; +import { useAuth, handleLogout } from '@/useAuth'; import ULIComponent from './ULIComponent'; import { Link } from 'react-router-dom'; +import ThemeToggle from './ThemeToggle'; export default function Navbar({ isPinned, @@ -23,9 +28,10 @@ export default function Navbar({ isPinned: boolean; onTogglePin: () => void; }) { - const user = useAuth(); + const { user } = useAuth(); + return ( -
+
{isPinned ? (
-
    - {user.user?.role == UserRole.Admin ? ( - <> - {/* admin view */} -
  • - - Dashboard - -
  • -
  • - - - Students - -
  • -
  • - - - Admins - -
  • -
  • - - - Open Content - -
  • -
  • - - - Resources - -
  • -
  • - - - Platforms - -
  • - - ) : ( - <> - {/* student view */} -
  • - - Dashboard - -
  • -
  • - - My Courses - -
  • -
  • - - My Progress - -
  • -
  • - - - Open Content - -
  • -
  • - - - Course Catalog - -
  • - - )} -
+
+
    +
    + {user?.role == UserRole.Admin ? ( + <> + {/* admin view */} +
  • + + + Dashboard + +
  • +
  • + + + Students + +
  • +
  • + + + Admins + +
  • +
  • + + + Open Content + +
  • +
  • + + + Resources + +
  • +
  • + + + Platforms + +
  • + + ) : ( + <> + {/* student view */} +
  • + + + Dashboard + +
  • +
  • + + My + Courses + +
  • +
  • + + My + Progress + +
  • +
  • + + + Open Content + +
  • +
  • + + + Course Catalog + +
  • + + )} +
    +
  • +
    + + {user?.name_first} {user?.name_last} +
    +
      +
    • + +
    • +
      +
    • + +
    • +
    +
  • +
+
); } diff --git a/frontend/src/Components/PageNav.tsx b/frontend/src/Components/PageNav.tsx index d855c51e..db610609 100644 --- a/frontend/src/Components/PageNav.tsx +++ b/frontend/src/Components/PageNav.tsx @@ -1,16 +1,15 @@ import { useEffect, useRef, useState } from 'react'; -import { handleLogout, useAuth } from '@/useAuth'; +import { useAuth } from '@/useAuth'; import { - ArrowRightEndOnRectangleIcon, Bars3Icon, + BuildingOffice2Icon, HomeIcon } from '@heroicons/react/24/solid'; - -import { SunIcon, MoonIcon } from '@heroicons/react/24/outline'; - -import ThemeToggle from './ThemeToggle'; import ULIComponent from '@/Components/ULIComponent.tsx'; import { usePathValue } from '@/PathValueCtx'; +import { Facility, UserRole } from '@/common'; +import { useLoaderData } from 'react-router-dom'; +import API from '@/api/api'; export default function PageNav({ path, @@ -25,6 +24,7 @@ export default function PageNav({ const detailsRef = useRef(null); const { pathVal } = usePathValue(); const [customPath, setCustomPath] = useState(path ?? []); + const facilityNames = useLoaderData() as Facility[] | null; useEffect(() => { const handlePathChange = () => { @@ -60,6 +60,13 @@ export default function PageNav({ }; }, []); + const handleSwitchFacility = async (facility: Facility) => { + const resp = await API.put(`admin/facility-context/${facility.id}`, {}); + if (resp.success) { + window.location.reload(); + } + }; + return (
@@ -97,46 +104,42 @@ export default function PageNav({ ))}
-
    -
  • -
    - - {user && ( + {user?.role == UserRole.Admin ? ( +
      +
    • +
      + + - {user.name_first} {user.name_last} + {user.facility_name} - )} - -
        -
      • - -
      • -
        - -
      • - -
      • -
      -
      -
    • -
    +
    +
      + {facilityNames?.map((facility: Facility) => ( +
    • { + void handleSwitchFacility(facility); + }} + > + +
    • + ))} +
    +
    +
  • +
+ ) : ( +
+ + +
+ )}
); } diff --git a/frontend/src/Layouts/AuthenticatedLayout.tsx b/frontend/src/Layouts/AuthenticatedLayout.tsx index 6bbb41ec..cd1dfd77 100644 --- a/frontend/src/Layouts/AuthenticatedLayout.tsx +++ b/frontend/src/Layouts/AuthenticatedLayout.tsx @@ -62,7 +62,7 @@ export default function AuthenticatedLayout() { checked={isNavOpen && !isNavPinned} onChange={() => setIsNavOpen(!isNavOpen)} /> -
+