/** * @file SettingsHub.tsx * @description Tabbed shell for /settings that hosts the dashboard's own settings plus one configuration panel per AI tool (Claude Code and Codex) plus the AI Router profiles they can be pointed at, 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, Router, Settings as SettingsIcon, SquareTerminal } from "lucide-react"; import { PageTabs } from "../components/PageTabs"; import { Settings } from "./Settings"; import { CcConfig } from "./CcConfig"; import { CodexConfig } from "./CodexConfig"; import { AiRouterConfig } from "./AiRouterConfig"; interface ToolTab { id: string; labelKey: string; Icon: ComponentType<{ className?: string }>; 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, Panel: CodexConfig }, { id: "ai-router", labelKey: "tools.aiRouter", Icon: Router, Panel: AiRouterConfig }, ]; /** * 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 }) => ({ id, Icon, label: t(labelKey), }))} />
); }