gitdataai/src/components/layout/sidebar-user.tsx
ZhenYi 7620f2f281 feat(command): use real API data for navigation, fix notification button
CommandPalette: replace workspaceProjects with getCurrentUserProjects
(no workspace dependency so it works outside WorkspaceProvider).
Repos fetched per-project to preserve correct /repository/ns/repo
routes. Keyboard shortcut correctly matches Ctrl+Alt+F / Cmd+Ctrl+F.

sidebar-user: fix notification button layout — bell icon and label
now on the same row instead of separate stacked elements.
2026-04-25 09:53:12 +08:00

102 lines
4.6 KiB
TypeScript

import {Avatar, AvatarFallback, AvatarImage} from '@/components/ui/avatar';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import {useUser} from '@/contexts';
import {cn} from '@/lib/utils';
import {UserPlus, Bell} from 'lucide-react';
import {useNavigate} from 'react-router-dom';
import {NotificationDrawer} from '@/components/notify/NotificationDrawer';
const btnClass = 'flex w-full h-9 justify-start items-center rounded-md font-medium hover:bg-muted cursor-pointer bg-transparent border-0 text-left text-sm';
export function SidebarUser({collapsed}: { collapsed: boolean }) {
const {user, logout} = useUser();
const navigate = useNavigate();
return (
<div className="w-full mb-2">
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')}
onClick={() => navigate('/invitations')}>
<span className="flex h-6 items-center shrink-0 w-6">
<UserPlus className="h-4 w-4"/>
</span>
{!collapsed && <span className="text-sm leading-none">Invitations</span>}
</button>
{!collapsed ? (
<button type="button" className={cn(btnClass, 'px-2')}
onClick={() => navigate('/notify')}>
<span className="flex h-6 items-center shrink-0 w-6">
<Bell className="h-4 w-4"/>
</span>
<span className="text-sm leading-none">Notify</span>
</button>
) : (
<div className="flex justify-center">
<NotificationDrawer />
</div>
)}
{user && (
<DropdownMenu>
<DropdownMenuTrigger
render={
<button
type="button"
className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')}
/>
}
>
<span
className={cn('flex h-6 items-center shrink-0', collapsed ? 'w-6 justify-center' : 'w-6')}>
<Avatar className="h-6 w-6">
<AvatarImage src={user.avatar_url || ''}/>
<AvatarFallback>
{user.username?.charAt(0).toUpperCase()}
</AvatarFallback>
</Avatar>
</span>
{!collapsed && <span className="text-sm leading-none">{user.username}</span>}
</DropdownMenuTrigger>
<DropdownMenuContent side="right" align="start">
{!collapsed && (
<DropdownMenuGroup>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem onClick={() => navigate(`/user/${user.username}`)}>
Profile
</DropdownMenuItem>
<DropdownMenuItem onClick={() => navigate('/settings')}>
Settings
</DropdownMenuItem>
<DropdownMenuSeparator/>
<DropdownMenuItem className="text-red-600 focus:text-red-600" onClick={() => logout()}>
Log out
</DropdownMenuItem>
</DropdownMenuGroup>
)}
{collapsed && (
<>
<DropdownMenuItem onClick={() => {
navigate(`/user/${user.username}`);
}}/>
<DropdownMenuItem onClick={() => {
navigate('/settings');
}}/>
<DropdownMenuSeparator/>
<DropdownMenuItem className="text-red-600 focus:text-red-600" onClick={() => logout()}/>
</>
)}
</DropdownMenuContent>
</DropdownMenu>
)}
</div>
);
}