chatbot-template/components/sidebar-history-item.tsx

121 lines
3.6 KiB
TypeScript
Raw Normal View History

import Link from "next/link";
import { memo } from "react";
import { useChatVisibility } from "@/hooks/use-chat-visibility";
import type { Chat } from "@/lib/db/schema";
2025-04-03 00:28:36 -07:00
import {
CheckCircleFillIcon,
GlobeIcon,
LockIcon,
MoreHorizontalIcon,
ShareIcon,
TrashIcon,
} from "./icons";
2025-04-03 00:28:36 -07:00
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuPortal,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "./ui/dropdown-menu";
2025-04-03 00:28:36 -07:00
import {
SidebarMenuAction,
SidebarMenuButton,
SidebarMenuItem,
} from "./ui/sidebar";
2025-04-03 00:28:36 -07:00
const PureChatItem = ({
chat,
isActive,
onDelete,
setOpenMobile,
}: {
chat: Chat;
isActive: boolean;
onDelete: (chatId: string) => void;
setOpenMobile: (open: boolean) => void;
}) => {
const { visibilityType, setVisibilityType } = useChatVisibility({
chatId: chat.id,
initialVisibilityType: chat.visibility,
2025-04-03 00:28:36 -07:00
});
return (
<SidebarMenuItem>
<SidebarMenuButton asChild isActive={isActive}>
<Link href={`/chat/${chat.id}`} onClick={() => setOpenMobile(false)}>
<span>{chat.title}</span>
</Link>
</SidebarMenuButton>
<DropdownMenu modal={true}>
<DropdownMenuTrigger asChild>
<SidebarMenuAction
2025-09-09 15:44:07 -04:00
className="mr-0.5 data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
2025-04-03 00:28:36 -07:00
showOnHover={!isActive}
>
<MoreHorizontalIcon />
<span className="sr-only">More</span>
</SidebarMenuAction>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" side="bottom">
2025-04-03 00:28:36 -07:00
<DropdownMenuSub>
<DropdownMenuSubTrigger className="cursor-pointer">
<ShareIcon />
<span>Share</span>
</DropdownMenuSubTrigger>
<DropdownMenuPortal>
<DropdownMenuSubContent>
<DropdownMenuItem
className="cursor-pointer flex-row justify-between"
onClick={() => {
setVisibilityType("private");
2025-04-03 00:28:36 -07:00
}}
>
2025-09-09 15:44:07 -04:00
<div className="flex flex-row items-center gap-2">
2025-04-03 00:28:36 -07:00
<LockIcon size={12} />
<span>Private</span>
</div>
{visibilityType === "private" ? (
2025-04-03 00:28:36 -07:00
<CheckCircleFillIcon />
) : null}
</DropdownMenuItem>
<DropdownMenuItem
className="cursor-pointer flex-row justify-between"
onClick={() => {
setVisibilityType("public");
2025-04-03 00:28:36 -07:00
}}
>
2025-09-09 15:44:07 -04:00
<div className="flex flex-row items-center gap-2">
2025-04-03 00:28:36 -07:00
<GlobeIcon />
<span>Public</span>
</div>
{visibilityType === "public" ? <CheckCircleFillIcon /> : null}
2025-04-03 00:28:36 -07:00
</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuPortal>
</DropdownMenuSub>
<DropdownMenuItem
className="cursor-pointer text-destructive focus:bg-destructive/15 focus:text-destructive dark:text-red-500"
onSelect={() => onDelete(chat.id)}
>
<TrashIcon />
<span>Delete</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</SidebarMenuItem>
);
};
export const ChatItem = memo(PureChatItem, (prevProps, nextProps) => {
if (prevProps.isActive !== nextProps.isActive) {
return false;
}
2025-04-03 00:28:36 -07:00
return true;
});