feat: add admin navigation link for authenticated admin users
This commit is contained in:
parent
37de6787bf
commit
c162258c99
2 changed files with 34 additions and 4 deletions
|
|
@ -17,7 +17,11 @@ import {
|
||||||
import { SignedIn, SignedOut, SignInButton, UserButton } from "@clerk/react-router";
|
import { SignedIn, SignedOut, SignInButton, UserButton } from "@clerk/react-router";
|
||||||
import { MenuIcon } from "lucide-react";
|
import { MenuIcon } from "lucide-react";
|
||||||
|
|
||||||
export function Navbar() {
|
interface NavbarProps {
|
||||||
|
isAdmin: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Navbar({ isAdmin }: NavbarProps) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -41,6 +45,13 @@ export function Navbar() {
|
||||||
<Link to="/how-to-play">How To Play</Link>
|
<Link to="/how-to-play">How To Play</Link>
|
||||||
</NavigationMenuLink>
|
</NavigationMenuLink>
|
||||||
</NavigationMenuItem>
|
</NavigationMenuItem>
|
||||||
|
{isAdmin && (
|
||||||
|
<NavigationMenuItem>
|
||||||
|
<NavigationMenuLink asChild className={navigationMenuTriggerStyle()}>
|
||||||
|
<Link to="/admin">Admin</Link>
|
||||||
|
</NavigationMenuLink>
|
||||||
|
</NavigationMenuItem>
|
||||||
|
)}
|
||||||
</NavigationMenuList>
|
</NavigationMenuList>
|
||||||
</NavigationMenu>
|
</NavigationMenu>
|
||||||
|
|
||||||
|
|
@ -99,6 +110,15 @@ export function Navbar() {
|
||||||
>
|
>
|
||||||
How To Play
|
How To Play
|
||||||
</Link>
|
</Link>
|
||||||
|
{isAdmin && (
|
||||||
|
<Link
|
||||||
|
to="/admin"
|
||||||
|
className="block px-4 py-2 text-lg font-medium hover:bg-accent rounded-md transition-colors"
|
||||||
|
onClick={() => setOpen(false)}
|
||||||
|
>
|
||||||
|
Admin
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
</Sheet>
|
</Sheet>
|
||||||
|
|
|
||||||
16
app/root.tsx
16
app/root.tsx
|
|
@ -9,15 +9,25 @@ import {
|
||||||
|
|
||||||
import type { Route } from "./+types/root";
|
import type { Route } from "./+types/root";
|
||||||
import "./app.css";
|
import "./app.css";
|
||||||
import { clerkMiddleware, rootAuthLoader } from "@clerk/react-router/server";
|
import { clerkMiddleware, rootAuthLoader, getAuth } from "@clerk/react-router/server";
|
||||||
import { Navbar } from "~/components/navbar";
|
import { Navbar } from "~/components/navbar";
|
||||||
import { ClerkProvider } from "@clerk/react-router";
|
import { ClerkProvider } from "@clerk/react-router";
|
||||||
import { Toaster } from "~/components/ui/sonner";
|
import { Toaster } from "~/components/ui/sonner";
|
||||||
|
import { isUserAdminByClerkId } from "~/models/user";
|
||||||
|
|
||||||
export const middleware: Route.MiddlewareFunction[] = [clerkMiddleware()];
|
export const middleware: Route.MiddlewareFunction[] = [clerkMiddleware()];
|
||||||
|
|
||||||
export async function loader(args: Route.LoaderArgs) {
|
export async function loader(args: Route.LoaderArgs) {
|
||||||
return rootAuthLoader(args);
|
return rootAuthLoader(args, async () => {
|
||||||
|
const { userId } = await getAuth(args);
|
||||||
|
|
||||||
|
let isAdmin = false;
|
||||||
|
if (userId) {
|
||||||
|
isAdmin = await isUserAdminByClerkId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { isAdmin };
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const links: Route.LinksFunction = () => [
|
export const links: Route.LinksFunction = () => [
|
||||||
|
|
@ -54,7 +64,7 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
||||||
export default function App({ loaderData }: Route.ComponentProps) {
|
export default function App({ loaderData }: Route.ComponentProps) {
|
||||||
return (
|
return (
|
||||||
<ClerkProvider loaderData={loaderData}>
|
<ClerkProvider loaderData={loaderData}>
|
||||||
<Navbar />
|
<Navbar isAdmin={loaderData?.isAdmin ?? false} />
|
||||||
<main>
|
<main>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</main>
|
</main>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue