import { MoreHorizontal, Trash2 } from "lucide-react";
import { useTranslation } from "react-i18next";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { ScrollArea } from "@/components/ui/scroll-area";
import { cn } from "@/lib/utils";
import type { ChatSummary } from "@/lib/types";
interface ChatListProps {
sessions: ChatSummary[];
activeKey: string | null;
onSelect: (key: string) => void;
onRequestDelete: (key: string, label: string) => void;
loading?: boolean;
emptyLabel?: string;
}
function titleFor(s: ChatSummary, fallbackTitle: string): string {
const p = (s.title || s.preview)?.trim();
if (p) return p.length > 48 ? `${p.slice(0, 45)}…` : p;
return fallbackTitle;
}
export function ChatList({
sessions,
activeKey,
onSelect,
onRequestDelete,
loading,
emptyLabel,
}: ChatListProps) {
const { t } = useTranslation();
if (loading && sessions.length === 0) {
return (
{t("chat.loading")}
);
}
if (sessions.length === 0) {
return (
{emptyLabel ?? t("chat.noSessions")}
);
}
const groups = groupSessions(sessions, {
today: t("chat.groups.today"),
yesterday: t("chat.groups.yesterday"),
earlier: t("chat.groups.earlier"),
});
return (
{groups.map((group) => (
{group.label}
{group.sessions.map((s) => {
const active = s.key === activeKey;
const title = titleFor(
s,
t("chat.fallbackTitle", { id: s.chatId.slice(0, 6) }),
);
return (
-
event.preventDefault()}
>
{
window.setTimeout(() => onRequestDelete(s.key, title), 0);
}}
className="text-destructive focus:text-destructive"
>
{t("chat.delete")}
);
})}
))}
);
}
function groupSessions(
sessions: ChatSummary[],
labels: { today: string; yesterday: string; earlier: string },
): Array<{ label: string; sessions: ChatSummary[] }> {
const now = new Date();
const startOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate()).getTime();
const startOfYesterday = startOfToday - 24 * 60 * 60 * 1000;
const buckets = new Map();
for (const session of sessions) {
const timestamp = Date.parse(session.updatedAt ?? session.createdAt ?? "");
const label = Number.isFinite(timestamp) && timestamp >= startOfToday
? labels.today
: Number.isFinite(timestamp) && timestamp >= startOfYesterday
? labels.yesterday
: labels.earlier;
const bucket = buckets.get(label) ?? [];
bucket.push(session);
buckets.set(label, bucket);
}
return [labels.today, labels.yesterday, labels.earlier]
.map((label) => ({ label, sessions: buckets.get(label) ?? [] }))
.filter((group) => group.sessions.length > 0);
}