/** * @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ĩ */ 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 (
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 ? ( ) : (

{t("tools.comingSoon", { tool: t(active.labelKey) })}

{t("tools.comingSoonDesc")}

)}
); }