import { IconChevronRight } from "@tabler/icons-react" import { IconAtom, IconChevronsDown, IconChevronsUp, IconKey, IconListDetails, IconMessageCircle, IconSettings, IconSparkles, IconTools, } from "@tabler/icons-react" import { Link, useRouterState } from "@tanstack/react-router" import * as React from "react" import { useTranslation } from "react-i18next" import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible" import { Sidebar, SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarRail, } from "@/components/ui/sidebar" import { useSidebarChannels } from "@/hooks/use-sidebar-channels" interface NavItem { title: string url: string icon: React.ComponentType<{ className?: string }> translateTitle?: boolean } interface NavGroup { label: string defaultOpen: boolean items: NavItem[] isChannelsGroup?: boolean } const baseNavGroups: Omit[] = [ { label: "navigation.chat", defaultOpen: true, }, { label: "navigation.model_group", defaultOpen: true, }, { label: "navigation.agent_group", defaultOpen: true, }, { label: "navigation.services", defaultOpen: true, }, ] export function AppSidebar({ ...props }: React.ComponentProps) { const routerState = useRouterState() const { t } = useTranslation() const currentPath = routerState.location.pathname const { channelItems, hasMoreChannels, showAllChannels, toggleShowAllChannels, } = useSidebarChannels({ t }) const navGroups: NavGroup[] = React.useMemo(() => { return [ { ...baseNavGroups[0], items: [ { title: "navigation.chat", url: "/", icon: IconMessageCircle, translateTitle: true, }, ], }, { ...baseNavGroups[1], items: [ { title: "navigation.models", url: "/models", icon: IconAtom, translateTitle: true, }, { title: "navigation.credentials", url: "/credentials", icon: IconKey, translateTitle: true, }, ], }, { label: "navigation.channels_group", defaultOpen: true, items: channelItems.map((item) => ({ title: item.title, url: item.url, icon: item.icon, translateTitle: false, })), isChannelsGroup: true, }, { ...baseNavGroups[2], items: [ { title: "navigation.skills", url: "/agent/skills", icon: IconSparkles, translateTitle: true, }, { title: "navigation.tools", url: "/agent/tools", icon: IconTools, translateTitle: true, }, ], }, { ...baseNavGroups[3], items: [ { title: "navigation.config", url: "/config", icon: IconSettings, translateTitle: true, }, { title: "navigation.logs", url: "/logs", icon: IconListDetails, translateTitle: true, }, ], }, ] }, [channelItems]) return ( {navGroups.map((group) => ( {t(group.label)} {group.items.map((item) => { const isActive = currentPath === item.url || (item.url !== "/" && currentPath.startsWith(`${item.url}/`)) return ( {item.translateTitle === false ? item.title : t(item.title)} ) })} {group.isChannelsGroup && hasMoreChannels && ( {showAllChannels ? ( ) : ( )} {showAllChannels ? t("navigation.show_less_channels") : t("navigation.show_more_channels")} )} ))} ) }