"use client"; import { useState, useEffect, useRef } from "react"; import { useRouter, usePathname } from "next/navigation"; import { MessageSquare, PlusCircle, Trash2, ServerIcon, Settings, Loader2, Sparkles, ChevronsUpDown, UserIcon, Copy } from "lucide-react"; import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuBadge, useSidebar } from "@/components/ui/sidebar"; import { Separator } from "@/components/ui/separator"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { toast } from "sonner"; import Image from "next/image"; import { MCPServerManager, type MCPServer } from "./mcp-server-manager"; import { ThemeToggle } from "./theme-toggle"; import { getUserId } from "@/lib/user-id"; import { useLocalStorage } from "@/lib/hooks/use-local-storage"; import { STORAGE_KEYS } from "@/lib/constants"; import { useChats } from "@/lib/hooks/use-chats"; import { cn } from "@/lib/utils"; import Link from "next/link"; import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; export function ChatSidebar() { const router = useRouter(); const pathname = usePathname(); const [userId, setUserId] = useState(''); const [mcpServers, setMcpServers] = useLocalStorage(STORAGE_KEYS.MCP_SERVERS, []); const [selectedMcpServers, setSelectedMcpServers] = useLocalStorage(STORAGE_KEYS.SELECTED_MCP_SERVERS, []); const [mcpSettingsOpen, setMcpSettingsOpen] = useState(false); const { state } = useSidebar(); const isCollapsed = state === "collapsed"; // Initialize userId useEffect(() => { setUserId(getUserId()); }, []); // Use TanStack Query to fetch chats const { chats, isLoading, deleteChat, refreshChats } = useChats(userId); // Start a new chat const handleNewChat = () => { router.push('/'); }; // Delete a chat const handleDeleteChat = async (chatId: string, e: React.MouseEvent) => { e.stopPropagation(); e.preventDefault(); deleteChat(chatId); // If we're currently on the deleted chat's page, navigate to home if (pathname === `/chat/${chatId}`) { router.push('/'); } }; // Get active MCP servers status const activeServersCount = selectedMcpServers.length; // Show loading state if user ID is not yet initialized if (!userId) { return null; // Or a loading spinner } return (
Scira Logo
{!isCollapsed && (
MCP
)}
Chats {isLoading ? (
{!isCollapsed && ( Loading... )}
) : chats.length === 0 ? (
{isCollapsed ? (
) : (
No conversations yet
)}
) : ( chats.map((chat) => (
{!isCollapsed && ( {chat.title.length > 18 ? `${chat.title.slice(0, 18)}...` : chat.title} )}
{!isCollapsed && ( )}
)) )}
MCP Servers setMcpSettingsOpen(true)} className={cn( "w-full flex items-center gap-2 transition-all", "hover:bg-secondary/50 active:bg-secondary/70" )} tooltip={isCollapsed ? "MCP Servers" : undefined} > 0 ? "text-primary" : "text-muted-foreground" )} /> {!isCollapsed && ( MCP Servers )} {activeServersCount > 0 && !isCollapsed ? ( {activeServersCount} ) : activeServersCount > 0 && isCollapsed ? ( {activeServersCount} ) : null}
{isCollapsed ? ( ) : ( )}
{userId.substring(0, 2).toUpperCase()}
User ID {userId}
{ e.preventDefault(); navigator.clipboard.writeText(userId); toast.success("User ID copied to clipboard"); }}> Copy User ID { e.preventDefault(); setMcpSettingsOpen(true); }}> MCP Settings e.preventDefault()}>
Theme
); }