// web/src/components/sidebar/SavedChatSection.tsx import React, { useEffect, useState } from "react"; import { Card } from "../ui/card"; import { Button } from "../ui/button"; import { Separator } from "../ui/separator"; import { Bookmark, Trash2, Pencil } from "lucide-react"; import type { SavedChat } from "../../App"; export function SavedChatSection({ isLoggedIn, savedChats, onLoadChat, onDeleteSavedChat, onRenameSavedChat, }: { isLoggedIn: boolean; savedChats: SavedChat[]; onLoadChat: (chat: SavedChat) => void; onDeleteSavedChat: (id: string) => void; onRenameSavedChat?: (id: string, newTitle: string) => void; }) { const [editingId, setEditingId] = useState(null); const [draftTitle, setDraftTitle] = useState(""); // Keep draft in sync if list changes while editing (e.g., load, delete) useEffect(() => { if (!editingId) return; const current = savedChats.find((c) => c.id === editingId); if (!current) { setEditingId(null); setDraftTitle(""); return; } // Only update draft if it was empty (avoid overwriting user's typing) if (!draftTitle) setDraftTitle(current.title || ""); // eslint-disable-next-line react-hooks/exhaustive-deps }, [savedChats, editingId]); if (!isLoggedIn) return null; const beginRename = (chat: SavedChat) => { if (!onRenameSavedChat) return; setEditingId(chat.id); setDraftTitle(chat.title || ""); }; const cancelRename = () => { setEditingId(null); setDraftTitle(""); }; const saveRename = () => { if (!editingId || !onRenameSavedChat) return; const next = draftTitle.trim(); const current = savedChats.find((c) => c.id === editingId); const fallback = current?.title || ""; // If user clears the title, revert to previous (keeps it clean) const finalTitle = next || fallback; if (finalTitle && finalTitle !== current?.title) { onRenameSavedChat(editingId, finalTitle); } setEditingId(null); setDraftTitle(""); }; return ( // โœ… NO scrolling here. Scrolling is owned by LeftSidebar's scroll container.
{/* header */}
Saved Chat
{/* content (normal flow; NO overflow-y-auto) */}
{savedChats.length === 0 ? (
No saved chats yet
Save conversations to view them here
) : (
{savedChats.map((chat) => { const isEditing = editingId === chat.id; const renameEnabled = !!onRenameSavedChat; return (
{/* Left: title + timestamp (click loads, but disabled while editing) */}
{!isEditing ? ( ) : (
setDraftTitle(e.target.value)} onBlur={saveRename} onKeyDown={(e) => { if (e.key === "Enter") saveRename(); if (e.key === "Escape") cancelRename(); }} className="w-full h-8 px-2 rounded-md border bg-background text-sm outline-none focus:ring-2 focus:ring-ring" />
Enter to save ยท Esc to cancel
)}
{/* Right: actions (hover show) */}
{/* โœ๏ธ Rename */} {renameEnabled && !isEditing && ( )} {/* ๐Ÿ—‘ Delete */}
); })}
)}
); }