"use client"; import { useCallback, useEffect, useState } from "react"; import Link from "next/link"; import { useTranslation } from "react-i18next"; import { ArrowUpRight } from "lucide-react"; import { fetchAuthStatus } from "@/lib/auth"; import { serviceReadiness, useSettings, } from "@/components/settings/SettingsContext"; import { SETTINGS_CATEGORIES, type Lang, type SettingsLeaf, } from "@/lib/settings-nav"; /** * Second-level grid for a sub-hub category (Models, Chat). Lists the * category's leaves as tiles — colored icon, configured chip for model * services, and a blurb — the focused view the user reaches by clicking the * hub block. */ export default function SettingsSectionGrid({ categoryKey, }: { categoryKey: string; }) { const { i18n } = useTranslation(); const zh = i18n.language?.toLowerCase().startsWith("zh"); const tr = useCallback((l: Lang) => (zh ? l.zh : l.en), [zh]); const { catalog, catalogEditable, diagnosticsResults } = useSettings(); const category = SETTINGS_CATEGORIES.find((c) => c.key === categoryKey); const [hideAdminOnly, setHideAdminOnly] = useState(false); useEffect(() => { let cancelled = false; fetchAuthStatus().then((authStatus) => { if (cancelled || !authStatus) return; setHideAdminOnly(Boolean(authStatus.enabled) && !authStatus.is_admin); }); return () => { cancelled = true; }; }, []); const chipFor = useCallback( ( leaf: SettingsLeaf, ): { label: Lang; tone: "ok" | "bad" | "neutral"; dot: boolean } | null => { if (!leaf.service) return null; if (catalogEditable !== true) return null; const readiness = serviceReadiness( catalog, leaf.service, diagnosticsResults, ); if (readiness === "failed") { return { tone: "bad", dot: true, label: { zh: "测试失败", en: "Test failed" }, }; } if (readiness === "passed") { return { tone: "ok", dot: true, label: { zh: "测试通过", en: "Test passed" }, }; } if (readiness === "untested") { return { tone: "neutral", dot: true, label: { zh: "已配置", en: "Configured" }, }; } return { tone: "neutral", dot: false, label: { zh: "未配置", en: "Not set" }, }; }, [catalog, catalogEditable, diagnosticsResults], ); if (!category?.children) return null; const leaves = category.children.filter( (leaf) => !(leaf.adminOnly && hideAdminOnly), ); return (
{tr(category.blurb)}
{tr(leaf.blurb)}
); }