'use client'; import { KeyboardShortcutHint } from "@/app/components/keyboardShortcutHint"; import { useToast } from "@/components/hooks/use-toast"; import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"; import { ResizablePanel } from "@/components/ui/resizable"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Separator } from "@/components/ui/separator"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { deleteChat, updateChatName } from "@/features/chat/actions"; import { useDomain } from "@/hooks/useDomain"; import { cn, isServiceError } from "@/lib/utils"; import { CirclePlusIcon, EllipsisIcon, PencilIcon, TrashIcon } from "lucide-react"; import { useRouter } from "next/navigation"; import { useCallback, useRef, useState } from "react"; import { useHotkeys } from "react-hotkeys-hook"; import { GoSidebarCollapse as ExpandIcon, } from "react-icons/go"; import { ImperativePanelHandle } from "react-resizable-panels"; import { useChatId } from "../useChatId"; import { RenameChatDialog } from "./renameChatDialog"; import { DeleteChatDialog } from "./deleteChatDialog"; import Link from "next/link"; interface ChatSidePanelProps { order: number; chatHistory: { id: string; name: string | null; createdAt: Date; }[]; isAuthenticated: boolean; isCollapsedInitially: boolean; } export const ChatSidePanel = ({ order, chatHistory, isAuthenticated, isCollapsedInitially, }: ChatSidePanelProps) => { const domain = useDomain(); const [isCollapsed, setIsCollapsed] = useState(isCollapsedInitially); const sidePanelRef = useRef(null); const router = useRouter(); const { toast } = useToast(); const chatId = useChatId(); const [isRenameDialogOpen, setIsRenameDialogOpen] = useState(false); const [chatIdToRename, setChatIdToRename] = useState(null); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const [chatIdToDelete, setChatIdToDelete] = useState(null); useHotkeys("mod+b", () => { if (isCollapsed) { sidePanelRef.current?.expand(); } else { sidePanelRef.current?.collapse(); } }, { enableOnFormTags: true, enableOnContentEditable: true, description: "Toggle side panel", }); const onRenameChat = useCallback(async (name: string, chatId: string) => { if (!chatId) { return; } const response = await updateChatName({ chatId, name: name, }, domain); if (isServiceError(response)) { toast({ description: `❌ Failed to rename chat. Reason: ${response.message}` }); } else { toast({ description: `✅ Chat renamed successfully` }); router.refresh(); } }, [router, toast, domain]); const onDeleteChat = useCallback(async (chatIdToDelete: string) => { if (!chatIdToDelete) { return; } const response = await deleteChat({ chatId: chatIdToDelete }, domain); if (isServiceError(response)) { toast({ description: `❌ Failed to delete chat. Reason: ${response.message}` }); } else { toast({ description: `✅ Chat deleted successfully` }); // If we just deleted the current chat, navigate to new chat if (chatIdToDelete === chatId) { router.push(`/${domain}/chat`); } router.refresh(); } }, [chatId, router, toast, domain]); return ( <> setIsCollapsed(true)} onExpand={() => setIsCollapsed(false)} >

Recent Chats

{!isAuthenticated ? (

Sign in to access your chat history.

) : chatHistory.length === 0 ? (

Recent chats will appear here.

) : chatHistory.map((chat) => (
{ router.push(`/${domain}/chat/${chat.id}`); }} > {chat.name ?? 'Untitled chat'} { e.stopPropagation(); setChatIdToRename(chat.id); setIsRenameDialogOpen(true); }} > Rename { e.stopPropagation(); setChatIdToDelete(chat.id); setIsDeleteDialogOpen(true); }} > Delete
))}
{isCollapsed && (
Open side panel
)} { if (chatIdToRename) { onRenameChat(name, chatIdToRename); } }} currentName={chatHistory?.find((chat) => chat.id === chatIdToRename)?.name ?? ""} /> { if (chatIdToDelete) { onDeleteChat(chatIdToDelete); } }} /> ) }