Files
AgentHub/client/src/pages/SettingsHub.tsx
T
nntrivi2001 bcfeeb5140 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.
2026-08-26 09:17:17 +07:00

74 lines
2.5 KiB
TypeScript

/**
* @file SettingsHub.tsx
* @description Tabbed shell for /settings that hosts the dashboard's own settings plus per-AI-tool configuration panels (Claude Code today, Codex/Cursor reserved), with the active tab kept in the `?tool=` query param.
* @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 { Boxes, Settings as SettingsIcon, SquareTerminal, MousePointerClick } from "lucide-react";
import { PageTabs } from "../components/PageTabs";
import { Settings } from "./Settings";
import { CcConfig } from "./CcConfig";
interface ToolTab {
id: string;
labelKey: string;
Icon: ComponentType<{ className?: string }>;
/** Omit for tools that are not integrated yet - the tab renders a placeholder. */
Panel?: ComponentType;
}
const DASHBOARD_TAB: ToolTab = {
id: "dashboard",
labelKey: "tools.dashboard",
Icon: SettingsIcon,
Panel: Settings,
};
/** Add a tool here to give it a tab; that is the whole extension point. */
const TOOL_TABS: ToolTab[] = [
DASHBOARD_TAB,
{ id: "claude-code", labelKey: "tools.claudeCode", Icon: Boxes, Panel: CcConfig },
{ id: "codex", labelKey: "tools.codex", Icon: SquareTerminal },
{ id: "cursor", labelKey: "tools.cursor", Icon: MousePointerClick },
];
/**
* Settings page shell with one tab per configuration surface.
* @returns The tab bar plus the active tab's panel.
*/
export function SettingsHub() {
const { t } = useTranslation("settings");
const [params, setParams] = useSearchParams();
const requested = params.get("tool");
const active = TOOL_TABS.find((tab) => tab.id === requested) ?? DASHBOARD_TAB;
return (
<div className="space-y-6">
<PageTabs
ariaLabel={t("tools.label", "Tools")}
activeId={active.id}
onSelect={(id) => setParams(id === DASHBOARD_TAB.id ? {} : { tool: id }, { replace: true })}
tabs={TOOL_TABS.map(({ id, labelKey, Icon, Panel }) => ({
id,
Icon,
label: t(labelKey),
...(Panel ? {} : { badge: t("tools.soonBadge", "soon") }),
}))}
/>
{active.Panel ? (
<active.Panel />
) : (
<div className="card p-8 text-center space-y-1">
<p className="text-sm font-medium text-fg-primary">
{t("tools.comingSoon", { tool: t(active.labelKey) })}
</p>
<p className="text-xs text-fg-muted">{t("tools.comingSoonDesc")}</p>
</div>
)}
</div>
);
}