diff options
| author | schererleander <leander@schererleander.de> | 2025-12-26 16:07:58 +0100 |
|---|---|---|
| committer | schererleander <leander@schererleander.de> | 2025-12-26 16:07:58 +0100 |
| commit | ba8c98a8dccb8b561747168b90ae769a105d37cf (patch) | |
| tree | f67f1b23510d27a16c6ac0bfc449a6aece6c81a2 /src/components/UserNav.tsx | |
| parent | 4b564ae2ef6d47e548ff3f1c6513605b8f2509ed (diff) | |
refactor: implement server-side rendering for auth-dependent pages
Diffstat (limited to 'src/components/UserNav.tsx')
| -rw-r--r-- | src/components/UserNav.tsx | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/components/UserNav.tsx b/src/components/UserNav.tsx new file mode 100644 index 0000000..e11cad7 --- /dev/null +++ b/src/components/UserNav.tsx @@ -0,0 +1,82 @@ +"use client" + +import Link from "next/link" +import { signOut } from "next-auth/react" +import { LogOut, Settings } from "lucide-react" + +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Button } from "@/components/ui/button" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" + +interface UserNavProps { + user: { + name?: string | null + email?: string | null + image?: string | null + } +} + +export function UserNav({ user }: UserNavProps) { + const getInitials = (name: string) => { + return name + .split(' ') + .map(word => word[0]) + .join('') + .toUpperCase() + .slice(0, 2) + } + + return ( + <DropdownMenu> + <DropdownMenuTrigger asChild> + <Button variant="ghost" className="relative h-10 w-auto px-2 rounded-full"> + <div className="flex items-center space-x-2"> + <span className="text-sm font-medium hidden sm:block"> + {user.name} + </span> + <Avatar className="h-8 w-8"> + <AvatarImage src={user.image || ""} alt={user.name || ""} /> + <AvatarFallback className="text-xs"> + {user.name ? getInitials(user.name) : "U"} + </AvatarFallback> + </Avatar> + </div> + </Button> + </DropdownMenuTrigger> + <DropdownMenuContent className="w-56" align="end" forceMount> + <DropdownMenuLabel className="font-normal"> + <div className="flex flex-col space-y-1"> + <p className="text-sm font-medium leading-none"> + {user.name} + </p> + <p className="text-xs leading-none text-muted-foreground"> + {user.email} + </p> + </div> + </DropdownMenuLabel> + <DropdownMenuSeparator /> + <DropdownMenuItem asChild> + <Link href="/settings" className="w-full cursor-pointer"> + <Settings className="mr-2 h-4 w-4" /> + Settings + </Link> + </DropdownMenuItem> + <DropdownMenuSeparator /> + <DropdownMenuItem + className="cursor-pointer text-destructive hover:text-destructive focus:text-destructive" + onClick={() => signOut()} + > + <LogOut className="mr-2 h-4 w-4 text-destructive" /> + Log out + </DropdownMenuItem> + </DropdownMenuContent> + </DropdownMenu> + ) +} |
