feat(sessions): merge the activity feed into a tab on /sessions
Sessions and Activity Feed are two views of the same event pipeline, so they now share one page: /sessions renders a tab bar (Sessions | Activity Feed) with the active view in the ?view= query param, and /activity redirects to /sessions?view=events. The sidebar entry is dropped. The tab bar itself moves out of SettingsHub into components/PageTabs so both hubs share it, and DocumentTitle loses the two branches for paths that now only redirect.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file History.tsx
|
||||
* @description Tabbed shell for /sessions that hosts the two views over the same
|
||||
* event pipeline: the per-session list and the raw activity feed. The active tab
|
||||
* lives in the `?view=` query param, so `/activity` can redirect into it.
|
||||
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
||||
*/
|
||||
import type { ComponentType } from "react";
|
||||
import { useSearchParams } from "react-router-dom";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Activity, FolderOpen } from "lucide-react";
|
||||
import { PageTabs } from "../components/PageTabs";
|
||||
import { Sessions } from "./Sessions";
|
||||
import { ActivityFeed } from "./ActivityFeed";
|
||||
|
||||
interface HistoryView {
|
||||
id: string;
|
||||
label: string;
|
||||
Icon: ComponentType<{ className?: string }>;
|
||||
Panel: ComponentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sessions page shell: grouped sessions and the raw event stream 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 },
|
||||
];
|
||||
const defaultView = views[0]!;
|
||||
const active = views.find((v) => v.id === params.get("view")) ?? defaultView;
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<PageTabs
|
||||
ariaLabel={t("sessions")}
|
||||
activeId={active.id}
|
||||
onSelect={(id) => setParams(id === defaultView.id ? {} : { view: id }, { replace: true })}
|
||||
tabs={views.map(({ id, label, Icon }) => ({ id, label, Icon }))}
|
||||
/>
|
||||
<active.Panel />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user