Template
108 lines
3.1 KiB
TypeScript
108 lines
3.1 KiB
TypeScript
'use client';
|
|
|
|
import { RiAddLine, RiMoreLine, RiDeleteBinLine } from '@remixicon/react';
|
|
import {
|
|
Sidebar,
|
|
SidebarContent,
|
|
SidebarHeader,
|
|
SidebarGroup,
|
|
SidebarGroupContent,
|
|
SidebarGroupLabel,
|
|
SidebarMenu,
|
|
SidebarMenuItem,
|
|
SidebarMenuButton,
|
|
SidebarMenuAction,
|
|
useSidebar,
|
|
} from '@/components/ui/sidebar';
|
|
import {
|
|
DropdownMenu,
|
|
DropdownMenuContent,
|
|
DropdownMenuItem,
|
|
DropdownMenuTrigger,
|
|
} from '@/components/ui/dropdown-menu';
|
|
import { Button } from '@/components/ui/button';
|
|
import { ChatSearch } from './ChatSearch';
|
|
import type { StoredChat } from '@/services/indexed-db/chat-store';
|
|
|
|
export type Chat = StoredChat;
|
|
|
|
interface ChatSidebarProps {
|
|
chats: Chat[];
|
|
activeChatId: string | null;
|
|
onSelectChat: (chatId: string) => void;
|
|
onNewChat: () => void;
|
|
onDeleteChat: (chatId: string) => void;
|
|
}
|
|
|
|
export function ChatSidebar({
|
|
chats,
|
|
activeChatId,
|
|
onSelectChat,
|
|
onNewChat,
|
|
onDeleteChat,
|
|
}: ChatSidebarProps) {
|
|
const { setOpenMobile } = useSidebar();
|
|
|
|
const selectChat = (chatId: string) => {
|
|
onSelectChat(chatId);
|
|
setOpenMobile(false);
|
|
};
|
|
|
|
return (
|
|
<Sidebar>
|
|
<SidebarHeader>
|
|
<div className="flex h-7 items-center justify-between gap-2 pl-2">
|
|
<span className="text-xl font-semibold tracking-tight">ChatGPT</span>
|
|
<ChatSearch chats={chats} activeChatId={activeChatId} onSelectChat={selectChat} />
|
|
</div>
|
|
<Button
|
|
onClick={() => {
|
|
onNewChat();
|
|
setOpenMobile(false);
|
|
}}
|
|
variant="outline"
|
|
className="mt-2 w-full justify-start gap-2"
|
|
>
|
|
<RiAddLine className="size-4" />
|
|
New Chat
|
|
</Button>
|
|
</SidebarHeader>
|
|
<SidebarContent>
|
|
<SidebarGroup>
|
|
<SidebarGroupLabel>Recent Chats</SidebarGroupLabel>
|
|
<SidebarGroupContent>
|
|
<SidebarMenu>
|
|
{chats.map((chat) => (
|
|
<SidebarMenuItem key={chat.id}>
|
|
<SidebarMenuButton
|
|
isActive={chat.id === activeChatId}
|
|
onClick={() => selectChat(chat.id)}
|
|
tooltip={chat.title}
|
|
>
|
|
<span>{chat.title}</span>
|
|
</SidebarMenuButton>
|
|
<DropdownMenu>
|
|
<DropdownMenuTrigger asChild>
|
|
<SidebarMenuAction showOnHover aria-label={`Options for ${chat.title}`}>
|
|
<RiMoreLine className="size-4" />
|
|
</SidebarMenuAction>
|
|
</DropdownMenuTrigger>
|
|
<DropdownMenuContent side="right" align="start">
|
|
<DropdownMenuItem
|
|
onClick={() => onDeleteChat(chat.id)}
|
|
>
|
|
<RiDeleteBinLine className="size-4" />
|
|
Delete
|
|
</DropdownMenuItem>
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
</SidebarMenuItem>
|
|
))}
|
|
</SidebarMenu>
|
|
</SidebarGroupContent>
|
|
</SidebarGroup>
|
|
</SidebarContent>
|
|
</Sidebar>
|
|
);
|
|
}
|