import { CloudSyncOutlined, DeleteOutlined, EditOutlined, FolderOpenOutlined, MenuFoldOutlined, MenuUnfoldOutlined, ReloadOutlined, } from "@ant-design/icons"; import { useCallback, useMemo, useState } from "react"; import type { WebProjectSummary } from "../../types"; interface ProjectSidebarProps { projects: WebProjectSummary[]; activeId: string | null; collapsed: boolean; filterMode?: "chat" | "image" | "video"; loading?: boolean; error?: string | null; onToggle: () => void; onSelect: (id: string) => void; onRefresh: () => void; onRename: (id: string, title: string) => void; onDelete: (id: string) => void; } function formatRelativeTime(dateStr: string): string { const then = new Date(dateStr).getTime(); if (!Number.isFinite(then)) return ""; const diff = Date.now() - then; if (diff < 60_000) return "just now"; if (diff < 3_600_000) return `${Math.floor(diff / 60_000)} min ago`; if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)} h ago`; if (diff < 604_800_000) return `${Math.floor(diff / 86_400_000)} d ago`; return new Date(dateStr).toLocaleDateString("zh-CN"); } export default function ProjectSidebar({ projects, activeId, collapsed, filterMode, loading, error, onToggle, onSelect, onRefresh, onRename, onDelete, }: ProjectSidebarProps) { const [editingId, setEditingId] = useState(null); const [editValue, setEditValue] = useState(""); const filteredProjects = useMemo( () => filterMode ? projects.filter((p) => p.mode === filterMode) : projects, [projects, filterMode], ); const startRename = useCallback((project: WebProjectSummary) => { setEditingId(project.id); setEditValue(project.name); }, []); const commitRename = useCallback(() => { if (editingId && editValue.trim()) { onRename(editingId, editValue.trim()); } setEditingId(null); }, [editValue, editingId, onRename]); return ( ); }