Files
tgex-frontend/components/nav-user.tsx
2026-01-21 22:43:54 +03:00

175 lines
6.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { Building2, Check, LogOut, Plus, Sparkles } from "lucide-react";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
useSidebar,
} from "@/components/ui/sidebar";
import { useAuth } from "@/components/auth/auth-provider";
import type { Workspace } from "@/lib/types/api";
import { DEMO_WORKSPACE_ID } from "@/lib/demo";
export function NavUser({
user,
workspaceSwitcher,
}: {
user: {
name: string;
email: string;
avatar: string;
};
workspaceSwitcher?: {
workspaces: Workspace[];
currentWorkspaceId?: string;
onSelect: (workspace: Workspace) => void;
onCreate?: () => void;
};
}) {
const { isMobile } = useSidebar();
const { logout } = useAuth();
const handleLogout = () => {
logout();
};
const getInitials = (name: string) => {
return name
.split(" ")
.map((n) => n[0])
.join("")
.toUpperCase()
.slice(0, 2);
};
return (
<SidebarMenu>
<SidebarMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<SidebarMenuButton
size="lg"
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback className="rounded-lg">
{getInitials(user.name)}
</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">{user.name}</span>
<span className="text-muted-foreground truncate text-xs">
{user.email}
</span>
</div>
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
className="w-56 rounded-lg"
side={isMobile ? "bottom" : "right"}
align="end"
sideOffset={4}
>
<DropdownMenuLabel className="p-0 font-normal">
<div className="flex items-center gap-2 px-2 py-1.5 text-left text-sm">
<Avatar className="h-8 w-8 rounded-lg">
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback className="rounded-lg">
{getInitials(user.name)}
</AvatarFallback>
</Avatar>
<div className="grid flex-1 text-left text-sm leading-tight">
<span className="truncate font-medium">{user.name}</span>
<span className="text-muted-foreground truncate text-xs">
{user.email}
</span>
</div>
</div>
</DropdownMenuLabel>
{workspaceSwitcher && (
<>
<DropdownMenuSeparator />
<DropdownMenuLabel className="text-xs text-muted-foreground">
Воркспейсы
</DropdownMenuLabel>
{workspaceSwitcher.workspaces.length > 0 ? (
workspaceSwitcher.workspaces.map((workspace) => {
const isDemo = workspace.id === DEMO_WORKSPACE_ID;
const isSelected = workspaceSwitcher.currentWorkspaceId === workspace.id;
return (
<DropdownMenuItem
key={workspace.id}
onClick={() => workspaceSwitcher.onSelect(workspace)}
className="gap-2 p-2 text-sm"
>
<Avatar className="h-6 w-6 rounded-sm">
<AvatarImage src={workspace.avatar_url || undefined} alt={workspace.name} />
<AvatarFallback className="rounded-sm text-xs">
{isDemo ? (
<Sparkles className="h-3 w-3 text-purple-500" />
) : (
workspace.name.charAt(0).toUpperCase()
)}
</AvatarFallback>
</Avatar>
<span className="flex-1 truncate">
{workspace.name}
{isDemo && (
<span className="ml-2 text-xs text-muted-foreground">
(Демо)
</span>
)}
</span>
{isSelected && (
<Check className="size-4 ml-auto" />
)}
</DropdownMenuItem>
);
})
) : (
<div className="px-2 py-1.5 text-sm text-muted-foreground">
Нет доступных воркспейсов
</div>
)}
{workspaceSwitcher.onCreate && (
<>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={workspaceSwitcher.onCreate}
className="gap-2 p-2"
>
<div className="flex size-6 items-center justify-center rounded-md border bg-background">
<Plus className="size-4" />
</div>
<span className="text-muted-foreground">
Создать воркспейс
</span>
</DropdownMenuItem>
</>
)}
</>
)}
<DropdownMenuSeparator />
<DropdownMenuItem onClick={handleLogout}>
<LogOut className="mr-2 h-4 w-4" />
Выйти
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
</SidebarMenu>
);
}