feat(nav-user): refactor NavUser component to use SidebarMenu and improve user loading state

This commit is contained in:
ngc2207 2025-02-04 14:29:34 +08:00
parent 9729e2d8a0
commit e41b1e4590

View File

@ -8,8 +8,12 @@ import {
LogOut, LogOut,
Sparkles, Sparkles,
} from "lucide-react"; } from "lucide-react";
import {
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from "@/components/ui/sidebar";
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@ -19,23 +23,30 @@ import {
DropdownMenuSeparator, DropdownMenuSeparator,
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { import { Skeleton } from "./ui/skeleton";
SidebarMenu, import { useLogout } from "@/features/auth/api/use-logout";
SidebarMenuButton, import { useCurrent } from "@/features/auth/api/use-current";
SidebarMenuItem, import { Avatar, AvatarFallback } from "@/components/ui/avatar";
useSidebar,
} from "@/components/ui/sidebar";
export function NavUser({ export function NavUser() {
user,
}: {
user: {
name: string;
email: string;
avatar: string;
};
}) {
const { isMobile } = useSidebar(); const { isMobile } = useSidebar();
const { mutate: logout } = useLogout();
const { data: user, isLoading } = useCurrent();
if (isLoading || !user) {
return (
<div className="flex p-2">
<Skeleton className="h-8 w-8 rounded-lg" />
<Skeleton className="flex-1 ml-2" />
</div>
);
}
const { name, email } = user;
const avatarFallback = name
? name.charAt(0).toUpperCase()
: email.charAt(0).toUpperCase() ?? "U";
return ( return (
<SidebarMenu> <SidebarMenu>
@ -47,12 +58,13 @@ export function NavUser({
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
> >
<Avatar className="h-8 w-8 rounded-lg"> <Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={user.avatar} alt={user.name} /> <AvatarFallback className="rounded-lg">
<AvatarFallback className="rounded-lg">CN</AvatarFallback> {avatarFallback}
</AvatarFallback>
</Avatar> </Avatar>
<div className="grid flex-1 text-left text-sm leading-tight"> <div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-semibold">{user.name}</span> <span className="truncate font-semibold">{name || "User"}</span>
<span className="truncate text-xs">{user.email}</span> <span className="truncate text-xs">{email}</span>
</div> </div>
<ChevronsUpDown className="ml-auto size-4" /> <ChevronsUpDown className="ml-auto size-4" />
</SidebarMenuButton> </SidebarMenuButton>
@ -66,12 +78,15 @@ export function NavUser({
<DropdownMenuLabel className="p-0 font-normal"> <DropdownMenuLabel className="p-0 font-normal">
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm"> <div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<Avatar className="h-8 w-8 rounded-lg"> <Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={user.avatar} alt={user.name} /> <AvatarFallback className="rounded-lg">
<AvatarFallback className="rounded-lg">CN</AvatarFallback> {avatarFallback}
</AvatarFallback>
</Avatar> </Avatar>
<div className="grid flex-1 text-left text-sm leading-tight"> <div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-semibold">{user.name}</span> <span className="truncate font-semibold">
<span className="truncate text-xs">{user.email}</span> {name || "User"}
</span>
<span className="truncate text-xs">{email}</span>
</div> </div>
</div> </div>
</DropdownMenuLabel> </DropdownMenuLabel>
@ -98,7 +113,7 @@ export function NavUser({
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuGroup> </DropdownMenuGroup>
<DropdownMenuSeparator /> <DropdownMenuSeparator />
<DropdownMenuItem> <DropdownMenuItem onClick={() => logout()}>
<LogOut /> <LogOut />
Log out Log out
</DropdownMenuItem> </DropdownMenuItem>