"use client"; import { ExternalLink, Folder, type LucideIcon, MoreHorizontal, RefreshCw, Search, Share, Trash2, } from "lucide-react"; import { useRouter } from "next/navigation"; import { useCallback, useMemo, useState } from "react"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { SidebarGroup, SidebarGroupLabel, SidebarInput, SidebarMenu, SidebarMenuAction, SidebarMenuButton, SidebarMenuItem, useSidebar, } from "@/components/ui/sidebar"; // Map of icon names to their components const actionIconMap: Record = { ExternalLink, Folder, Share, Trash2, MoreHorizontal, Search, RefreshCw, }; interface ChatAction { name: string; icon: string; onClick: () => void; } interface ChatItem { name: string; url: string; icon: LucideIcon; id?: number; search_space_id?: number; actions?: ChatAction[]; } export function NavProjects({ chats }: { chats: ChatItem[] }) { const { isMobile } = useSidebar(); const router = useRouter(); const [searchQuery, setSearchQuery] = useState(""); const [isDeleting, setIsDeleting] = useState(null); const searchSpaceId = chats[0]?.search_space_id || ""; // Memoized filtered chats const filteredChats = useMemo(() => { if (!searchQuery.trim()) return chats; return chats.filter((chat) => chat.name.toLowerCase().includes(searchQuery.toLowerCase())); }, [chats, searchQuery]); // Handle chat deletion with loading state const handleDeleteChat = useCallback(async (chatId: number, deleteAction: () => void) => { setIsDeleting(chatId); try { await deleteAction(); } finally { setIsDeleting(null); } }, []); // Enhanced chat item component const ChatItemComponent = useCallback( ({ chat }: { chat: ChatItem }) => { const isDeletingChat = isDeleting === chat.id; return ( router.push(chat.url)} disabled={isDeletingChat} className={isDeletingChat ? "opacity-50" : ""} > {chat.name} {chat.actions && chat.actions.length > 0 && ( More {chat.actions.map((action, actionIndex) => { const ActionIcon = actionIconMap[action.icon] || Folder; const isDeleteAction = action.name.toLowerCase().includes("delete"); return ( { if (isDeleteAction) { handleDeleteChat(chat.id || 0, action.onClick); } else { action.onClick(); } }} disabled={isDeletingChat} className={isDeleteAction ? "text-destructive" : ""} > {isDeletingChat && isDeleteAction ? "Deleting..." : action.name} ); })} )} ); }, [isDeleting, router, isMobile, handleDeleteChat] ); // Show search input if there are chats const showSearch = chats.length > 0; return ( Recent Chats {/* Search Input */} {showSearch && (
setSearchQuery(e.target.value)} className="h-8" />
)} {/* Chat Items */} {filteredChats.length > 0 ? ( filteredChats.map((chat) => ) ) : ( /* No results state */ {searchQuery ? "No chats found" : "No recent chats"} )} {/* View All Chats */} {chats.length > 0 && ( router.push(`/dashboard/${searchSpaceId}/chats`)}> View All Chats )}
); }