mirror of
https://gitlab.massbug.com/massbug/judge4c.git
synced 2025-07-04 15:41:17 +00:00
feat(nav-user): refactor NavUser component to use SidebarMenu and improve user loading state
This commit is contained in:
parent
9729e2d8a0
commit
e41b1e4590
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user