Files
wr.do/components/layout/user-account-nav.tsx
2024-07-26 22:08:57 +08:00

188 lines
6.2 KiB
TypeScript

"use client";
import { useState } from "react";
import Link from "next/link";
import { LayoutDashboard, Lock, LogOut, Settings } from "lucide-react";
import { signOut, useSession } from "next-auth/react";
import { Drawer } from "vaul";
import { useMediaQuery } from "@/hooks/use-media-query";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { UserAvatar } from "@/components/shared/user-avatar";
export function UserAccountNav() {
const { data: session } = useSession();
const user = session?.user;
const [open, setOpen] = useState(false);
const closeDrawer = () => {
setOpen(false);
};
const { isMobile } = useMediaQuery();
if (!user)
return (
<div className="size-8 animate-pulse rounded-full border bg-muted" />
);
if (isMobile) {
return (
<Drawer.Root open={open} onClose={closeDrawer}>
<Drawer.Trigger onClick={() => setOpen(true)}>
<UserAvatar
user={{ name: user.name || null, image: user.image || null }}
className="size-9 border"
/>
</Drawer.Trigger>
<Drawer.Portal>
<Drawer.Overlay
className="fixed inset-0 z-40 h-full bg-background/80 backdrop-blur-sm"
onClick={closeDrawer}
/>
<Drawer.Content className="fixed inset-x-0 bottom-0 z-50 mt-24 overflow-hidden rounded-t-[10px] border bg-background px-3 text-sm">
<div className="sticky top-0 z-20 flex w-full items-center justify-center bg-inherit">
<div className="my-3 h-1.5 w-16 rounded-full bg-muted-foreground/20" />
</div>
<div className="flex items-center justify-start gap-2 p-2">
<div className="flex flex-col">
{user.name && <p className="font-medium">{user.name}</p>}
{user.email && (
<p className="w-[200px] truncate text-muted-foreground">
{user?.email}
</p>
)}
</div>
</div>
<ul role="list" className="mb-14 mt-1 w-full text-muted-foreground">
{user.role === "ADMIN" ? (
<li className="rounded-lg text-foreground hover:bg-muted">
<Link
href="/admin"
onClick={closeDrawer}
className="flex w-full items-center gap-3 px-2.5 py-2"
>
<Lock className="size-4" />
<p className="text-sm">Admin</p>
</Link>
</li>
) : null}
<li className="rounded-lg text-foreground hover:bg-muted">
<Link
href="/dashboard"
onClick={closeDrawer}
className="flex w-full items-center gap-3 px-2.5 py-2"
>
<LayoutDashboard className="size-4" />
<p className="text-sm">Dashboard</p>
</Link>
</li>
<li className="rounded-lg text-foreground hover:bg-muted">
<Link
href="/dashboard/settings"
onClick={closeDrawer}
className="flex w-full items-center gap-3 px-2.5 py-2"
>
<Settings className="size-4" />
<p className="text-sm">Settings</p>
</Link>
</li>
<li
className="rounded-lg text-foreground hover:bg-muted"
onClick={(event) => {
event.preventDefault();
signOut({
callbackUrl: `${window.location.origin}/`,
});
}}
>
<div className="flex w-full items-center gap-3 px-2.5 py-2">
<LogOut className="size-4" />
<p className="text-sm">Log out </p>
</div>
</li>
</ul>
</Drawer.Content>
<Drawer.Overlay />
</Drawer.Portal>
</Drawer.Root>
);
}
return (
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger>
<UserAvatar
user={{ name: user.name || null, image: user.image || null }}
className="size-8 border"
/>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<div className="flex items-center justify-start gap-2 p-2">
<div className="flex flex-col space-y-1 leading-none">
{user.name && <p className="font-medium">{user.name}</p>}
{user.email && (
<p className="w-[200px] truncate text-sm text-muted-foreground">
{user?.email}
</p>
)}
</div>
</div>
<DropdownMenuSeparator />
{user.role === "ADMIN" ? (
<DropdownMenuItem asChild>
<Link href="/admin" className="flex items-center space-x-2.5">
<Lock className="size-4" />
<p className="text-sm">Admin</p>
</Link>
</DropdownMenuItem>
) : null}
<DropdownMenuItem asChild>
<Link href="/dashboard" className="flex items-center space-x-2.5">
<LayoutDashboard className="size-4" />
<p className="text-sm">Dashboard</p>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
href="/dashboard/settings"
className="flex items-center space-x-2.5"
>
<Settings className="size-4" />
<p className="text-sm">Settings</p>
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem
className="cursor-pointer"
onSelect={(event) => {
event.preventDefault();
signOut({
callbackUrl: `${window.location.origin}/`,
});
}}
>
<div className="flex items-center space-x-2.5">
<LogOut className="size-4" />
<p className="text-sm">Log out </p>
</div>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}