Files
neo-blog/web/src/components/layout/nav/avatar-with-dropdown-menu.tsx
Snowykami 349cf5a5b7
All checks were successful
Push to Helm Chart Repository / build (push) Successful in 13s
refactor: restructure authentication components and routes
- Removed the old reset password form component and replaced it with a new implementation.
- Updated routing paths for login, registration, and reset password to be under a common auth path.
- Added new login and registration pages with corresponding forms.
- Introduced a common auth header component for consistent branding across auth pages.
- Implemented a current logged-in user display component.
- Enhanced the register form to include email verification and captcha.
- Updated translations for new and modified components.
- Refactored the navigation bar to include user avatar dropdown and improved menu structure.
2025-09-23 02:21:03 +08:00

76 lines
2.5 KiB
TypeScript

"use client"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { userLogout } from "@/api/user";
import Link from "next/link";
import { toast } from "sonner";
import { useToLogin } from "@/hooks/use-route";
import { CircleUser } from "lucide-react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { getGravatarFromUser } from "@/utils/common/gravatar";
import { formatDisplayName, getFallbackAvatarFromUsername } from "@/utils/common/username";
import { useAuth } from "@/contexts/auth-context";
export function AvatarWithDropdownMenu() {
const { user } = useAuth();
const toLogin = useToLogin();
const handleLogout = () => {
userLogout().then(() => {
toast.success("Logged out successfully");
window.location.reload();
})
}
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button className="rounded-full overflow-hidden">
{user ? <Avatar className="h-8 w-8 rounded-full">
<AvatarImage src={getGravatarFromUser({ user })} alt={user.username} />
<AvatarFallback className="rounded-full">{getFallbackAvatarFromUsername(user.nickname || user.username)}</AvatarFallback>
</Avatar> : <CircleUser className="h-8 w-8" />}
</button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-auto" align="start">
{user && <DropdownMenuLabel>
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">{formatDisplayName(user)}</span>
<span className="text-muted-foreground truncate text-xs">
{user.email}
</span>
</div>
</div>
</DropdownMenuLabel>}
{user &&
<>
<DropdownMenuGroup>
<DropdownMenuItem asChild>
<Link href={`/u/${user?.username}`}>Profile</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/console">Console</Link>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
</>
}
<DropdownMenuItem onClick={user ? handleLogout : toLogin}>
{user ? "Logout" : "Login"}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}