175 lines
8.7 KiB
TypeScript
175 lines
8.7 KiB
TypeScript
import {useTheme} from '@/contexts/theme-context';
|
|
import {tryUseWorkspace} from '@/contexts/workspace-context';
|
|
import {cn} from '@/lib/utils';
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuGroup,
|
|
DropdownMenuItem,
|
|
DropdownMenuLabel,
|
|
DropdownMenuSeparator,
|
|
DropdownMenuTrigger,
|
|
} from '@/components/ui/dropdown-menu';
|
|
import {BookOpen, Box, ChevronDown, Compass, Home, LayoutGrid, Monitor, Moon, Plus, Sun, Users} from 'lucide-react';
|
|
import {useNavigate} from 'react-router-dom';
|
|
import {Avatar, AvatarFallback, AvatarImage} from '@/components/ui/avatar';
|
|
|
|
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 SidebarSystem({collapsed}: {collapsed: boolean}) {
|
|
const {theme, setTheme} = useTheme();
|
|
const navigate = useNavigate();
|
|
const workspaceCtx = tryUseWorkspace();
|
|
const workspaces = workspaceCtx?.workspaces;
|
|
const currentWorkspace = workspaceCtx?.currentWorkspace;
|
|
|
|
return (
|
|
<div className="w-full">
|
|
{/* Workspace switcher — only shown when inside WorkspaceProvider */}
|
|
{workspaceCtx && (
|
|
<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')}>
|
|
{currentWorkspace ? (
|
|
<Avatar className="h-4 w-4">
|
|
<AvatarImage src={currentWorkspace.avatar_url || ''}/>
|
|
<AvatarFallback className="text-[8px]">
|
|
{currentWorkspace.name.charAt(0).toUpperCase()}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
) : (
|
|
<LayoutGrid className="h-4 w-4"/>
|
|
)}
|
|
</span>
|
|
{!collapsed && (
|
|
<span className="flex-1 truncate text-sm leading-none">
|
|
{currentWorkspace?.name || 'Workspaces'}
|
|
</span>
|
|
)}
|
|
{!collapsed && <ChevronDown className="h-3 w-3 ml-auto shrink-0"/>}
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent side="right" align="start" className="w-56">
|
|
<DropdownMenuGroup>
|
|
<DropdownMenuLabel>Workspaces</DropdownMenuLabel>
|
|
{workspaces?.workspaces.map((ws) => (
|
|
<DropdownMenuItem
|
|
key={ws.id}
|
|
onClick={() => navigate(`/w/${ws.slug}`)}
|
|
className="gap-2"
|
|
>
|
|
<Avatar className="h-5 w-5">
|
|
<AvatarImage src={ws.avatar_url || ''}/>
|
|
<AvatarFallback className="text-[9px]">
|
|
{ws.name.charAt(0).toUpperCase()}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
<span className="flex-1 truncate">{ws.name}</span>
|
|
<span className="text-xs text-muted-foreground">@{ws.slug}</span>
|
|
</DropdownMenuItem>
|
|
))}
|
|
<DropdownMenuSeparator/>
|
|
<DropdownMenuItem onClick={() => navigate('/w/me')} className="gap-2">
|
|
<Users className="h-4 w-4"/>
|
|
<span>All Workspaces</span>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem onClick={() => navigate('/init/workspace')} className="gap-2">
|
|
<Plus className="h-4 w-4"/>
|
|
<span>Create Workspace</span>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuGroup>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
)}
|
|
|
|
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')} onClick={() => navigate('/')}>
|
|
<span className={cn('flex h-6 items-center shrink-0', collapsed ? 'w-6 justify-center' : 'w-6')}>
|
|
<Home className="h-4 w-4"/>
|
|
</span>
|
|
{!collapsed && <span className="text-sm leading-none">Home</span>}
|
|
</button>
|
|
|
|
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')} onClick={() => navigate('/explore')}>
|
|
<span className={cn('flex h-6 items-center shrink-0', collapsed ? 'w-6 justify-center' : 'w-6')}>
|
|
<Compass className="h-4 w-4" />
|
|
</span>
|
|
{!collapsed && <span className="text-sm leading-none">Explore</span>}
|
|
</button>
|
|
|
|
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')} onClick={() => navigate('/market')}>
|
|
<span className={cn('flex h-6 items-center shrink-0', collapsed ? 'w-6 justify-center' : 'w-6')}>
|
|
<Box className="h-4 w-4" />
|
|
</span>
|
|
{!collapsed && <span className="text-sm leading-none">Marketplace</span>}
|
|
</button>
|
|
|
|
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')} onClick={() => window.open('/docs', '_blank')}>
|
|
<span className={cn('flex h-6 items-center shrink-0', collapsed ? 'w-6 justify-center' : 'w-6')}>
|
|
<BookOpen className="h-4 w-4" />
|
|
</span>
|
|
{!collapsed && <span className="text-sm leading-none">Docs</span>}
|
|
</button>
|
|
|
|
<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')}>
|
|
{theme === 'dark' ? (
|
|
<Moon className="h-4 w-4" />
|
|
) : theme === 'light' ? (
|
|
<Sun className="h-4 w-4" />
|
|
) : (
|
|
<Monitor className="h-4 w-4" />
|
|
)}
|
|
</span>
|
|
{!collapsed && <span className="text-sm leading-none">Theme</span>}
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent side="right" align="start">
|
|
{!collapsed && (
|
|
<DropdownMenuGroup>
|
|
<DropdownMenuLabel>Theme Settings</DropdownMenuLabel>
|
|
<DropdownMenuItem onClick={() => setTheme('light')}>
|
|
<Sun className="mr-2 h-4 w-4" />
|
|
<span>Light</span>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem onClick={() => setTheme('dark')}>
|
|
<Moon className="mr-2 h-4 w-4" />
|
|
<span>Dark</span>
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem onClick={() => setTheme('system')}>
|
|
<Monitor className="mr-2 h-4 w-4" />
|
|
<span>System</span>
|
|
</DropdownMenuItem>
|
|
</DropdownMenuGroup>
|
|
)}
|
|
{collapsed && (
|
|
<>
|
|
<DropdownMenuItem onClick={() => setTheme('light')}>
|
|
<Sun className="mr-2 h-4 w-4" />
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem onClick={() => setTheme('dark')}>
|
|
<Moon className="mr-2 h-4 w-4" />
|
|
</DropdownMenuItem>
|
|
<DropdownMenuItem onClick={() => setTheme('system')}>
|
|
<Monitor className="mr-2 h-4 w-4" />
|
|
</DropdownMenuItem>
|
|
</>
|
|
)}
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</div>
|
|
);
|
|
}
|