/** * @file History.tsx * @description Tabbed shell for /sessions that hosts the three views over the * same data: the per-session list, the raw activity feed and the agents table. * The active tab lives in the `?view=` query param, so `/activity` and the old * `/query` Query Explorer can redirect into it. * @author Nguyễn Ngọc Trí Vĩ */ import type { ComponentType } from "react"; import { useSearchParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { Activity, Bot, FolderOpen } from "lucide-react"; import { PageTabs } from "../components/PageTabs"; import { Sessions } from "./Sessions"; import { ActivityFeed } from "./ActivityFeed"; import { AgentsTable } from "./AgentsTable"; interface HistoryView { id: string; label: string; Icon: ComponentType<{ className?: string }>; Panel: ComponentType<{ embedded?: boolean }>; } /** * Sessions page shell: sessions, the raw event stream and agents as sibling tabs. * @returns The tab bar plus the active view. */ export function History() { const { t } = useTranslation("nav"); const [params, setParams] = useSearchParams(); const views: HistoryView[] = [ { id: "sessions", label: t("sessions"), Icon: FolderOpen, Panel: Sessions }, { id: "events", label: t("activityFeed"), Icon: Activity, Panel: ActivityFeed }, { id: "agents", label: t("agents"), Icon: Bot, Panel: AgentsTable }, ]; const defaultView = views[0]!; const active = views.find((v) => v.id === params.get("view")) ?? defaultView; return (
setParams(id === defaultView.id ? {} : { view: id }, { replace: true })} tabs={views.map(({ id, label, Icon }) => ({ id, label, Icon }))} > {/* `embedded`: the tab bar names the view, so the panel drops its own title. */}
); }