All checks were successful
PR Check — Frontend / frontend (pull_request) Successful in 1m56s
Self-review of PR #470: the System card of the Settings home lists the page's sections as chips, still with the version history before the logs. The chips now follow the page (version, update, logs, history), and a test renders the page and compares its section headings with the card, so the two cannot drift apart again. SECTIONS is exported for that test, as DocsContent exports its own. The /settings/systems row of docs/architecture.md names both unreleased headings and the card. Resolves #372 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
107 lines
3.5 KiB
TypeScript
107 lines
3.5 KiB
TypeScript
import { useTranslation } from "react-i18next";
|
|
import { Link } from "react-router-dom";
|
|
import { Users, Database, Cpu, ChevronRight } from "lucide-react";
|
|
import { PageHelp } from "../../components/shared/PageHelp";
|
|
|
|
interface SectionCard {
|
|
to: string;
|
|
titleKey: string;
|
|
descriptionKey: string;
|
|
Icon: React.ComponentType<{ size?: number }>;
|
|
itemKeys: string[];
|
|
}
|
|
|
|
/** The three cards of the hub; each lists its page's sections, in the page's order. */
|
|
export const SECTIONS: SectionCard[] = [
|
|
{
|
|
to: "/settings/users",
|
|
titleKey: "settings.users.title",
|
|
descriptionKey: "settings.users.description",
|
|
Icon: Users,
|
|
itemKeys: [
|
|
"settings.users.sections.accounts",
|
|
"settings.users.sections.licenses",
|
|
"settings.users.sections.userGuide",
|
|
],
|
|
},
|
|
{
|
|
to: "/settings/data",
|
|
titleKey: "settings.data.title",
|
|
descriptionKey: "settings.data.description",
|
|
Icon: Database,
|
|
itemKeys: [
|
|
"settings.data.sections.categories",
|
|
"settings.data.sections.backup",
|
|
"settings.data.sections.priceFetch",
|
|
],
|
|
},
|
|
{
|
|
to: "/settings/systems",
|
|
titleKey: "settings.systems.title",
|
|
descriptionKey: "settings.systems.description",
|
|
Icon: Cpu,
|
|
itemKeys: [
|
|
"settings.systems.sections.version",
|
|
"settings.systems.sections.update",
|
|
"settings.systems.sections.logs",
|
|
"settings.systems.sections.changelog",
|
|
],
|
|
},
|
|
];
|
|
|
|
export default function SettingsHomePage() {
|
|
const { t } = useTranslation();
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="relative flex items-center gap-3">
|
|
<h1 className="text-2xl font-bold">{t("settings.title")}</h1>
|
|
<PageHelp helpKey="settings" />
|
|
</div>
|
|
|
|
<p className="text-sm text-[var(--muted-foreground)]">
|
|
{t("settings.home.intro")}
|
|
</p>
|
|
|
|
<div className="space-y-4">
|
|
{SECTIONS.map(({ to, titleKey, descriptionKey, Icon, itemKeys }) => (
|
|
<Link
|
|
key={to}
|
|
to={to}
|
|
className="block bg-[var(--card)] border border-[var(--border)] rounded-xl p-6 hover:border-[var(--primary)] transition-colors group"
|
|
>
|
|
<div className="flex items-center justify-between gap-4">
|
|
<div className="flex items-start gap-4 flex-1">
|
|
<div className="w-12 h-12 rounded-xl bg-[var(--primary)]/10 flex items-center justify-center text-[var(--primary)] shrink-0">
|
|
<Icon size={22} />
|
|
</div>
|
|
<div className="flex-1 space-y-2">
|
|
<div>
|
|
<h2 className="text-lg font-semibold">{t(titleKey)}</h2>
|
|
<p className="text-sm text-[var(--muted-foreground)]">
|
|
{t(descriptionKey)}
|
|
</p>
|
|
</div>
|
|
<ul className="flex flex-wrap gap-2 text-xs text-[var(--muted-foreground)]">
|
|
{itemKeys.map((key) => (
|
|
<li
|
|
key={key}
|
|
className="px-2 py-0.5 rounded-full bg-[var(--background)] border border-[var(--border)]"
|
|
>
|
|
{t(key)}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<ChevronRight
|
|
size={18}
|
|
className="text-[var(--muted-foreground)] group-hover:text-[var(--primary)] transition-colors shrink-0"
|
|
/>
|
|
</div>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|