From 3eefe96fc1879637b8a3e7315567c260902fc9f6 Mon Sep 17 00:00:00 2001 From: Lim Zi Yang Date: Thu, 30 May 2024 19:41:10 +0800 Subject: [PATCH] Conditional rendering of admin features (#156) * feat: init user memberships context * feat: add user memberships context provider to main layout * feat: add conditional rendering of create service button * feat: extract main nav layout * feat: add conditional rendering in side bar * feat: implement conditional rendering of admin pages by restructuring folders and layouts * refactor: rename context folder * refactor: remove unused code --- .../admin-service-request-actions.tsx | 0 .../approve-confirmation-dialog.tsx | 0 .../reject-confirmation-dialog.tsx | 0 .../_hooks/use-org-service-requests.ts | 0 .../_hooks/use-reject-form.tsx | 0 .../columns.tsx | 0 .../admin-service-requests-dashboard/page.tsx | 0 .../(authenticated)/(main)/(admin)/layout.tsx | 20 +++++++ .../_hooks/use-create-service.ts | 0 .../create-service/_utils/validation.ts | 0 .../service-catalog/create-service/page.tsx | 0 .../(main)/(non-admin)/layout.tsx | 9 +++ .../(main)/{ => (non-admin)}/page.tsx | 0 .../_hooks/use-service-request-form.ts | 0 .../_hooks/use-service-request.ts | 0 .../_views/service-request-skeleton-view.tsx | 0 .../_views/service-request-view.tsx | 0 .../service-catalog/[pipelineId]/page.tsx | 0 .../service-catalog/_hooks/use-pagination.ts | 0 .../service-catalog/_hooks/use-services.ts | 0 .../_views/services-skeleton-view.tsx | 0 .../service-catalog/_views/services-view.tsx | 0 .../service-catalog/page.tsx | 17 +++--- .../_hooks/use-service-request-info.tsx | 0 .../[serviceRequestId]/page.tsx | 0 .../[serviceRequestId]/page.tsx | 0 .../service-request-logs-skeleton.tsx | 0 .../_components/service-request-logs-view.tsx | 0 .../_components/step-logs.tsx | 0 .../_hooks/use-service-request-steps.tsx | 0 .../_hooks/use-step-logs.tsx | 0 .../cancel-confirmation-dialog.tsx | 0 .../_components/service-request-actions.tsx | 0 .../_hooks/use-service-requests.ts | 0 .../columns.tsx | 0 .../your-service-request-dashboard/page.tsx | 0 .../src/app/(authenticated)/(main)/layout.tsx | 34 ++--------- .../layouts/main-navigation-layout.tsx | 51 +++++++++++++++++ frontend/src/components/layouts/sidebar.tsx | 38 ++++++++----- .../src/contexts/user-memberships-context.tsx | 56 +++++++++++++++++++ frontend/src/lib/service.ts | 5 ++ frontend/src/types/membership.ts | 18 ++++++ 42 files changed, 197 insertions(+), 51 deletions(-) rename frontend/src/app/(authenticated)/(main)/{ => (admin)}/admin-service-requests-dashboard/_components/admin-service-request-actions.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (admin)}/admin-service-requests-dashboard/_components/approve-confirmation-dialog.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (admin)}/admin-service-requests-dashboard/_components/reject-confirmation-dialog.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (admin)}/admin-service-requests-dashboard/_hooks/use-org-service-requests.ts (100%) rename frontend/src/app/(authenticated)/(main)/{ => (admin)}/admin-service-requests-dashboard/_hooks/use-reject-form.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (admin)}/admin-service-requests-dashboard/columns.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (admin)}/admin-service-requests-dashboard/page.tsx (100%) create mode 100644 frontend/src/app/(authenticated)/(main)/(admin)/layout.tsx rename frontend/src/app/(authenticated)/(main)/{ => (admin)}/service-catalog/create-service/_hooks/use-create-service.ts (100%) rename frontend/src/app/(authenticated)/(main)/{ => (admin)}/service-catalog/create-service/_utils/validation.ts (100%) rename frontend/src/app/(authenticated)/(main)/{ => (admin)}/service-catalog/create-service/page.tsx (100%) create mode 100644 frontend/src/app/(authenticated)/(main)/(non-admin)/layout.tsx rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/page.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-catalog/[pipelineId]/_hooks/use-service-request-form.ts (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-catalog/[pipelineId]/_hooks/use-service-request.ts (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-catalog/[pipelineId]/_views/service-request-skeleton-view.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-catalog/[pipelineId]/_views/service-request-view.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-catalog/[pipelineId]/page.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-catalog/_hooks/use-pagination.ts (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-catalog/_hooks/use-services.ts (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-catalog/_views/services-skeleton-view.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-catalog/_views/services-view.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-catalog/page.tsx (72%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-request-info/[serviceRequestId]/_hooks/use-service-request-info.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-request-info/[serviceRequestId]/page.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-request-logs/[serviceRequestId]/page.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-request-logs/_components/service-request-logs-skeleton.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-request-logs/_components/service-request-logs-view.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-request-logs/_components/step-logs.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-request-logs/_hooks/use-service-request-steps.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/service-request-logs/_hooks/use-step-logs.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/your-service-request-dashboard/_components/cancel-confirmation-dialog.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/your-service-request-dashboard/_components/service-request-actions.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/your-service-request-dashboard/_hooks/use-service-requests.ts (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/your-service-request-dashboard/columns.tsx (100%) rename frontend/src/app/(authenticated)/(main)/{ => (non-admin)}/your-service-request-dashboard/page.tsx (100%) create mode 100644 frontend/src/components/layouts/main-navigation-layout.tsx create mode 100644 frontend/src/contexts/user-memberships-context.tsx create mode 100644 frontend/src/types/membership.ts diff --git a/frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/_components/admin-service-request-actions.tsx b/frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/_components/admin-service-request-actions.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/_components/admin-service-request-actions.tsx rename to frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/_components/admin-service-request-actions.tsx diff --git a/frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/_components/approve-confirmation-dialog.tsx b/frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/_components/approve-confirmation-dialog.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/_components/approve-confirmation-dialog.tsx rename to frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/_components/approve-confirmation-dialog.tsx diff --git a/frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/_components/reject-confirmation-dialog.tsx b/frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/_components/reject-confirmation-dialog.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/_components/reject-confirmation-dialog.tsx rename to frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/_components/reject-confirmation-dialog.tsx diff --git a/frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/_hooks/use-org-service-requests.ts b/frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/_hooks/use-org-service-requests.ts similarity index 100% rename from frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/_hooks/use-org-service-requests.ts rename to frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/_hooks/use-org-service-requests.ts diff --git a/frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/_hooks/use-reject-form.tsx b/frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/_hooks/use-reject-form.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/_hooks/use-reject-form.tsx rename to frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/_hooks/use-reject-form.tsx diff --git a/frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/columns.tsx b/frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/columns.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/columns.tsx rename to frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/columns.tsx diff --git a/frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/page.tsx b/frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/page.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/admin-service-requests-dashboard/page.tsx rename to frontend/src/app/(authenticated)/(main)/(admin)/admin-service-requests-dashboard/page.tsx diff --git a/frontend/src/app/(authenticated)/(main)/(admin)/layout.tsx b/frontend/src/app/(authenticated)/(main)/(admin)/layout.tsx new file mode 100644 index 00000000..d63d9a80 --- /dev/null +++ b/frontend/src/app/(authenticated)/(main)/(admin)/layout.tsx @@ -0,0 +1,20 @@ +"use client" + +import NotFoundPage from "@/app/not-found" +import MainNavigationLayout from "@/components/layouts/main-navigation-layout" +import { useUserMemberships } from "@/contexts/user-memberships-context" +import { ReactNode, useState } from "react" + +interface AdminLayoutProps { + children: ReactNode +} + +export default function AdminLayout({ children }: AdminLayoutProps) { + const { isAdmin } = useUserMemberships() + + return isAdmin ? ( + {children} + ) : ( + + ) +} diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/create-service/_hooks/use-create-service.ts b/frontend/src/app/(authenticated)/(main)/(admin)/service-catalog/create-service/_hooks/use-create-service.ts similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/create-service/_hooks/use-create-service.ts rename to frontend/src/app/(authenticated)/(main)/(admin)/service-catalog/create-service/_hooks/use-create-service.ts diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/create-service/_utils/validation.ts b/frontend/src/app/(authenticated)/(main)/(admin)/service-catalog/create-service/_utils/validation.ts similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/create-service/_utils/validation.ts rename to frontend/src/app/(authenticated)/(main)/(admin)/service-catalog/create-service/_utils/validation.ts diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/create-service/page.tsx b/frontend/src/app/(authenticated)/(main)/(admin)/service-catalog/create-service/page.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/create-service/page.tsx rename to frontend/src/app/(authenticated)/(main)/(admin)/service-catalog/create-service/page.tsx diff --git a/frontend/src/app/(authenticated)/(main)/(non-admin)/layout.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/layout.tsx new file mode 100644 index 00000000..24c5aa09 --- /dev/null +++ b/frontend/src/app/(authenticated)/(main)/(non-admin)/layout.tsx @@ -0,0 +1,9 @@ +import MainNavigationLayout from "@/components/layouts/main-navigation-layout" + +export default function NonAdminLayout({ + children, +}: { + children: React.ReactNode +}) { + return {children} +} diff --git a/frontend/src/app/(authenticated)/(main)/page.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/page.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/page.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/page.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/[pipelineId]/_hooks/use-service-request-form.ts b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/[pipelineId]/_hooks/use-service-request-form.ts similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/[pipelineId]/_hooks/use-service-request-form.ts rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/[pipelineId]/_hooks/use-service-request-form.ts diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/[pipelineId]/_hooks/use-service-request.ts b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/[pipelineId]/_hooks/use-service-request.ts similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/[pipelineId]/_hooks/use-service-request.ts rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/[pipelineId]/_hooks/use-service-request.ts diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/[pipelineId]/_views/service-request-skeleton-view.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/[pipelineId]/_views/service-request-skeleton-view.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/[pipelineId]/_views/service-request-skeleton-view.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/[pipelineId]/_views/service-request-skeleton-view.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/[pipelineId]/_views/service-request-view.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/[pipelineId]/_views/service-request-view.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/[pipelineId]/_views/service-request-view.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/[pipelineId]/_views/service-request-view.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/[pipelineId]/page.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/[pipelineId]/page.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/[pipelineId]/page.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/[pipelineId]/page.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/_hooks/use-pagination.ts b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/_hooks/use-pagination.ts similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/_hooks/use-pagination.ts rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/_hooks/use-pagination.ts diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/_hooks/use-services.ts b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/_hooks/use-services.ts similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/_hooks/use-services.ts rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/_hooks/use-services.ts diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/_views/services-skeleton-view.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/_views/services-skeleton-view.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/_views/services-skeleton-view.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/_views/services-skeleton-view.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/_views/services-view.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/_views/services-view.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-catalog/_views/services-view.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/_views/services-view.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-catalog/page.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/page.tsx similarity index 72% rename from frontend/src/app/(authenticated)/(main)/service-catalog/page.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/page.tsx index 49858db5..f410d549 100644 --- a/frontend/src/app/(authenticated)/(main)/service-catalog/page.tsx +++ b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-catalog/page.tsx @@ -9,23 +9,26 @@ import HeaderAccessory from "@/components/ui/header-accessory" import { useRouter } from "next/navigation" import ServicesSkeletonView from "./_views/services-skeleton-view" import ServicesView from "./_views/services-view" +import { useUserMemberships } from "@/contexts/user-memberships-context" export default function ServiceCatalogPage() { const { services, isServicesLoading } = useServices() const router = useRouter() - + const { isAdmin } = useUserMemberships() return ( <>

Service Catalog

- + {isAdmin && ( + + )}
{isServicesLoading ? ( diff --git a/frontend/src/app/(authenticated)/(main)/service-request-info/[serviceRequestId]/_hooks/use-service-request-info.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-info/[serviceRequestId]/_hooks/use-service-request-info.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-request-info/[serviceRequestId]/_hooks/use-service-request-info.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-info/[serviceRequestId]/_hooks/use-service-request-info.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-request-info/[serviceRequestId]/page.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-info/[serviceRequestId]/page.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-request-info/[serviceRequestId]/page.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-info/[serviceRequestId]/page.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-request-logs/[serviceRequestId]/page.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/[serviceRequestId]/page.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-request-logs/[serviceRequestId]/page.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/[serviceRequestId]/page.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-request-logs/_components/service-request-logs-skeleton.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/_components/service-request-logs-skeleton.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-request-logs/_components/service-request-logs-skeleton.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/_components/service-request-logs-skeleton.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-request-logs/_components/service-request-logs-view.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/_components/service-request-logs-view.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-request-logs/_components/service-request-logs-view.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/_components/service-request-logs-view.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-request-logs/_components/step-logs.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/_components/step-logs.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-request-logs/_components/step-logs.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/_components/step-logs.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-request-logs/_hooks/use-service-request-steps.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/_hooks/use-service-request-steps.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-request-logs/_hooks/use-service-request-steps.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/_hooks/use-service-request-steps.tsx diff --git a/frontend/src/app/(authenticated)/(main)/service-request-logs/_hooks/use-step-logs.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/_hooks/use-step-logs.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/service-request-logs/_hooks/use-step-logs.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/service-request-logs/_hooks/use-step-logs.tsx diff --git a/frontend/src/app/(authenticated)/(main)/your-service-request-dashboard/_components/cancel-confirmation-dialog.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/your-service-request-dashboard/_components/cancel-confirmation-dialog.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/your-service-request-dashboard/_components/cancel-confirmation-dialog.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/your-service-request-dashboard/_components/cancel-confirmation-dialog.tsx diff --git a/frontend/src/app/(authenticated)/(main)/your-service-request-dashboard/_components/service-request-actions.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/your-service-request-dashboard/_components/service-request-actions.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/your-service-request-dashboard/_components/service-request-actions.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/your-service-request-dashboard/_components/service-request-actions.tsx diff --git a/frontend/src/app/(authenticated)/(main)/your-service-request-dashboard/_hooks/use-service-requests.ts b/frontend/src/app/(authenticated)/(main)/(non-admin)/your-service-request-dashboard/_hooks/use-service-requests.ts similarity index 100% rename from frontend/src/app/(authenticated)/(main)/your-service-request-dashboard/_hooks/use-service-requests.ts rename to frontend/src/app/(authenticated)/(main)/(non-admin)/your-service-request-dashboard/_hooks/use-service-requests.ts diff --git a/frontend/src/app/(authenticated)/(main)/your-service-request-dashboard/columns.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/your-service-request-dashboard/columns.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/your-service-request-dashboard/columns.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/your-service-request-dashboard/columns.tsx diff --git a/frontend/src/app/(authenticated)/(main)/your-service-request-dashboard/page.tsx b/frontend/src/app/(authenticated)/(main)/(non-admin)/your-service-request-dashboard/page.tsx similarity index 100% rename from frontend/src/app/(authenticated)/(main)/your-service-request-dashboard/page.tsx rename to frontend/src/app/(authenticated)/(main)/(non-admin)/your-service-request-dashboard/page.tsx diff --git a/frontend/src/app/(authenticated)/(main)/layout.tsx b/frontend/src/app/(authenticated)/(main)/layout.tsx index db312144..a165826c 100644 --- a/frontend/src/app/(authenticated)/(main)/layout.tsx +++ b/frontend/src/app/(authenticated)/(main)/layout.tsx @@ -1,13 +1,9 @@ "use client" -import Navbar from "@/components/layouts/navbar" -import Sidebar from "@/components/layouts/sidebar" import { Toaster } from "@/components/ui/toaster" -import { useCurrentUserInfo } from "@/contexts/current-user-info-context" -import { getUserProfile } from "@/lib/auth0" -import { Auth0UserProfile } from "@/types/user-profile" +import { UserMembershipsProvider } from "@/contexts/user-memberships-context" import { QueryClient, QueryClientProvider } from "@tanstack/react-query" -import { getCookie, hasCookie } from "cookies-next" +import { hasCookie } from "cookies-next" import { useRouter } from "next/navigation" import { ReactNode, useEffect, useState } from "react" @@ -28,33 +24,13 @@ export default function MainLayout({ children }: MainLayoutProps) { const queryClient = new QueryClient() - const [isSidebarOpen, setIsSidebarOpen] = useState(true) - const toggleSidebar = () => { - setIsSidebarOpen((isSidebarOpen) => !isSidebarOpen) - } - const userInfo = useCurrentUserInfo() - return ( render && ( -
- -
- -
-
{children}
-
-
+ + {children} -
+
) ) diff --git a/frontend/src/components/layouts/main-navigation-layout.tsx b/frontend/src/components/layouts/main-navigation-layout.tsx new file mode 100644 index 00000000..91e83472 --- /dev/null +++ b/frontend/src/components/layouts/main-navigation-layout.tsx @@ -0,0 +1,51 @@ +"use client" + +import Navbar from "@/components/layouts/navbar" +import Sidebar from "@/components/layouts/sidebar" +import { getUserProfile } from "@/lib/auth0" +import { Auth0UserProfile } from "@/types/user-profile" +import { getCookie } from "cookies-next" +import { ReactNode, useEffect, useState } from "react" + +interface MainNavigationLayoutProps { + children: ReactNode + name?: string +} + +export default function MainNavigationLayout({ + children, + name, +}: MainNavigationLayoutProps) { + const [isSidebarOpen, setIsSidebarOpen] = useState(true) + const toggleSidebar = () => { + setIsSidebarOpen((isSidebarOpen) => !isSidebarOpen) + } + + const [userProfile, setUserProfile] = useState() + useEffect(() => { + getUserProfile(getCookie("access_token") as string) + .then((userProfile) => setUserProfile(userProfile)) + .catch((error) => { + console.log(error) + }) + }, []) + return ( +
+ +
+ +
+
{children}
+
+
+
+ ) +} diff --git a/frontend/src/components/layouts/sidebar.tsx b/frontend/src/components/layouts/sidebar.tsx index c1ca677c..b0d6ea37 100644 --- a/frontend/src/components/layouts/sidebar.tsx +++ b/frontend/src/components/layouts/sidebar.tsx @@ -3,6 +3,7 @@ import Link from "next/link" import React from "react" import { buttonVariants } from "../ui/button" import { LibraryBig, Workflow, LockKeyhole } from "lucide-react" +import { useUserMemberships } from "@/contexts/user-memberships-context" type LinkType = { title: string @@ -17,6 +18,7 @@ type LinkType = { | "secondary" | null | undefined + isAdminFeature?: boolean } const links: LinkType[] = [ @@ -37,6 +39,7 @@ const links: LinkType[] = [ icon: LockKeyhole, href: "/admin-service-requests-dashboard", variant: "ghost", + isAdminFeature: true, }, ] @@ -45,6 +48,7 @@ interface SidebarProps { } export default function Sidebar({ className }: SidebarProps) { + const { isAdmin } = useUserMemberships() return (
- {links.map((link, index) => ( - - - {link.title} - - ))} + {links.map((link, index) => + link.isAdminFeature && !isAdmin ? ( + <> + ) : ( + + + {link.title} + + ) + )} ) diff --git a/frontend/src/contexts/user-memberships-context.tsx b/frontend/src/contexts/user-memberships-context.tsx new file mode 100644 index 00000000..cb57d584 --- /dev/null +++ b/frontend/src/contexts/user-memberships-context.tsx @@ -0,0 +1,56 @@ +import useOrganizationId from "@/hooks/use-organization-id" +import { getUserMemberships } from "@/lib/service" +import { Role, UserMemberships } from "@/types/membership" +import { createContext, useContext, useEffect, useMemo, useState } from "react" + +interface MembershipContextValue { + isAdmin?: boolean +} + +const MembershipContext = createContext(null) + +export function UserMembershipsProvider({ + children, +}: { + children: React.ReactNode +}) { + const [userMemberships, setUserMemberships] = useState() + + useEffect(() => { + getUserMemberships() + .then(setUserMemberships) + .catch((err) => { + console.error(err) + }) + }, []) + const { organizationId } = useOrganizationId() + + const isAdminOfCurrentOrg = useMemo(() => { + return userMemberships?.memberships.some( + (membership) => + membership.org_id === organizationId && + (membership.role === Role.Admin || membership.role === Role.Owner) + ) + }, [userMemberships, organizationId]) + + return ( + + {children} + + ) +} + +export function useUserMemberships() { + const context = useContext(MembershipContext) + if (!context) { + throw new Error( + "useUserMemberships must be used within a UserMembershipsProvider" + ) + } + + return context +} diff --git a/frontend/src/lib/service.ts b/frontend/src/lib/service.ts index a0a3b3e1..7fc4fd25 100644 --- a/frontend/src/lib/service.ts +++ b/frontend/src/lib/service.ts @@ -6,6 +6,7 @@ import { } from "@/types/service-request" import { UserInfo } from "@/types/user-profile" import apiClient from "./apiClient" +import { UserMemberships } from "@/types/membership" /* Pipeline */ @@ -150,6 +151,10 @@ export async function getUserById(userId: string): Promise { return apiClient.get(`/user/${userId}`).then((res) => res.data) } +export async function getUserMemberships(): Promise { + return apiClient.get(`/membership`).then((res) => res.data) +} + export async function login(): Promise { return apiClient.get("login").then((res) => res.data) } diff --git a/frontend/src/types/membership.ts b/frontend/src/types/membership.ts new file mode 100644 index 00000000..3c612b9c --- /dev/null +++ b/frontend/src/types/membership.ts @@ -0,0 +1,18 @@ +enum Role { + Owner = "Owner", + Admin = "Admin", + Member = "Member", +} + +type Membership = { + org_id: number + role: Role + joined_on: string +} + +type UserMemberships = { + user_id: string + memberships: Membership[] +} +export { Role } +export type { Membership, UserMemberships }