mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
The admin page was a single 2,702-line client component with nineteen inline functions covering everything from system status to feedback inbox. The status-card grid foundation in #133 already moved the at-a-glance dashboard out; this commit moves the inner panels. Split into one file per logical section in src/components/admin/: _shared.tsx 276 LOC shared types, hooks, primitives (PasswordInput, StatusItem, SettingsToggle, useAdminSettings, useUpdateSettings, useSystemStatus, getApiErrorMessage) system-status-section.tsx 155 general-settings-section.tsx 54 services-section.tsx 68 umami-section.tsx 173 glitchtip-section.tsx 172 web-push-vapid-section.tsx 148 bug-report-section.tsx 109 reminders-section.tsx 318 user-management-section.tsx 341 api-token-overview-section.tsx 144 login-overview-section.tsx 181 danger-zone-section.tsx 118 feedback-inbox-section.tsx 511 (inbox + category badge + detail dialog) src/app/admin/page.tsx is now a 77-line shell that imports the 14 sections and the existing status-card-grid.tsx. No behavior change — every section keeps the same DOM, the same query keys, the same i18n keys, the same id="…" anchors so deep-links from the sidebar still scroll into place. UserManagementSection no longer takes a queryClient prop; it grabs its own via useQueryClient() like every other section does.
69 lines
2.2 KiB
TypeScript
69 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({ id }: { id: string }) {
|
|
const { t } = useTranslations();
|
|
const { data: settings } = useAdminSettings();
|
|
const updateSettings = useUpdateSettings();
|
|
|
|
return (
|
|
<div
|
|
id={id}
|
|
className="bg-card border-border scroll-mt-28 rounded-xl border p-6"
|
|
>
|
|
<div className="flex items-center gap-2">
|
|
<Globe className="text-primary h-5 w-5" />
|
|
<h2 className="text-lg font-semibold">{t("admin.servicesGlobal")}</h2>
|
|
</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>
|
|
);
|
|
}
|