mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
Phase 4b's `<SectionFrame>` already paints the canonical h1 + subtitle for each `/admin/<slug>` route, but every section card kept its v1.4 in-card h2 with the same (or near-same) text. The result was the section title announcing twice — once as h1, then immediately again as h2 — both visually redundant and a screen-reader landmark anti-pattern. Demoting the in-card label to a `<div>` preserves the visual look (same Tailwind classes) while removing the duplicate heading. The four sub-cards inside `IntegrationsGroupSection` (umami, glitchtip, web-push, bug-report) keep their h2 because they live under the "Integrations" h1 and genuinely deserve a heading level — that is the non-duplicating case. Closes H1 from .planning/phase-6-design-findings.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
66 lines
2.2 KiB
TypeScript
66 lines
2.2 KiB
TypeScript
"use client";
|
|
|
|
import { Bell, Globe, Key, MessageCircle } from "lucide-react";
|
|
import { useTranslations } from "@/lib/i18n/context";
|
|
import { SettingsToggle, useAdminSettings, useUpdateSettings } from "./_shared";
|
|
|
|
export function ServicesSection() {
|
|
const { t } = useTranslations();
|
|
const { data: settings } = useAdminSettings();
|
|
const updateSettings = useUpdateSettings();
|
|
|
|
return (
|
|
<div className="bg-card border-border rounded-xl border p-6">
|
|
<div className="flex items-center gap-2">
|
|
<Globe className="text-primary h-5 w-5" />
|
|
<div className="text-lg font-semibold">{t("admin.servicesGlobal")}</div>
|
|
</div>
|
|
<p className="text-muted-foreground mt-1 text-xs">
|
|
{t("admin.servicesGlobalDescription")}
|
|
</p>
|
|
<div className="mt-4 space-y-3">
|
|
<SettingsToggle
|
|
label="Telegram"
|
|
description={t("admin.telegramGlobal")}
|
|
icon={MessageCircle}
|
|
checked={settings?.telegramGlobal ?? true}
|
|
onCheckedChange={(checked) =>
|
|
updateSettings.mutate({ telegramGlobal: checked })
|
|
}
|
|
disabled={updateSettings.isPending}
|
|
/>
|
|
<SettingsToggle
|
|
label="ntfy"
|
|
description={t("admin.ntfyGlobal")}
|
|
icon={Bell}
|
|
checked={settings?.ntfyGlobal ?? true}
|
|
onCheckedChange={(checked) =>
|
|
updateSettings.mutate({ ntfyGlobal: checked })
|
|
}
|
|
disabled={updateSettings.isPending}
|
|
/>
|
|
<SettingsToggle
|
|
label={t("admin.integrationWebPush")}
|
|
description={t("admin.webPushGlobal")}
|
|
icon={Globe}
|
|
checked={settings?.webPushGlobal ?? true}
|
|
onCheckedChange={(checked) =>
|
|
updateSettings.mutate({ webPushGlobal: checked })
|
|
}
|
|
disabled={updateSettings.isPending}
|
|
/>
|
|
<SettingsToggle
|
|
label="API"
|
|
description={t("admin.apiGlobal")}
|
|
icon={Key}
|
|
checked={settings?.apiGlobal ?? true}
|
|
onCheckedChange={(checked) =>
|
|
updateSettings.mutate({ apiGlobal: checked })
|
|
}
|
|
disabled={updateSettings.isPending}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|