-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
Showing
42 changed files
with
197 additions
and
51 deletions.
There are no files selected for viewing
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
20 changes: 20 additions & 0 deletions
20
frontend/src/app/(authenticated)/(main)/(admin)/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 ? ( | ||
<MainNavigationLayout>{children}</MainNavigationLayout> | ||
) : ( | ||
<NotFoundPage /> | ||
) | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions
9
frontend/src/app/(authenticated)/(main)/(non-admin)/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import MainNavigationLayout from "@/components/layouts/main-navigation-layout" | ||
|
||
export default function NonAdminLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode | ||
}) { | ||
return <MainNavigationLayout>{children}</MainNavigationLayout> | ||
} |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
frontend/src/components/layouts/main-navigation-layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Auth0UserProfile>() | ||
useEffect(() => { | ||
getUserProfile(getCookie("access_token") as string) | ||
.then((userProfile) => setUserProfile(userProfile)) | ||
.catch((error) => { | ||
console.log(error) | ||
}) | ||
}, []) | ||
return ( | ||
<div | ||
className="flex flex-row w-full min-h-[100vh]" | ||
suppressHydrationWarning | ||
> | ||
<Sidebar | ||
className={` ${isSidebarOpen ? "min-w-[300px] w-[300px]" : "min-w-0 w-0"} overflow-x-hidden transition-width duration-300 ease-in-out`} | ||
/> | ||
<div className="w-full"> | ||
<Navbar | ||
toggleSidebar={toggleSidebar} | ||
username={userProfile?.nickname ?? ""} | ||
/> | ||
<div className="w-full h-full max-h-[90vh] flex justify-center items-center flex-col relative"> | ||
<div className="w-5/6 h-full relative">{children}</div> | ||
</div> | ||
</div> | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<MembershipContextValue | null>(null) | ||
|
||
export function UserMembershipsProvider({ | ||
children, | ||
}: { | ||
children: React.ReactNode | ||
}) { | ||
const [userMemberships, setUserMemberships] = useState<UserMemberships>() | ||
|
||
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 ( | ||
<MembershipContext.Provider | ||
value={{ | ||
isAdmin: isAdminOfCurrentOrg, | ||
}} | ||
> | ||
{children} | ||
</MembershipContext.Provider> | ||
) | ||
} | ||
|
||
export function useUserMemberships() { | ||
const context = useContext(MembershipContext) | ||
if (!context) { | ||
throw new Error( | ||
"useUserMemberships must be used within a UserMembershipsProvider" | ||
) | ||
} | ||
|
||
return context | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 } |