diff --git a/messages/de.json b/messages/de.json index ad6935b2c..6140e8ca9 100644 --- a/messages/de.json +++ b/messages/de.json @@ -1259,6 +1259,8 @@ "activeTokens": "Aktive API-Tokens", "activeSessions": "Aktive Sessions", "loadingStatus": "Lade Status...", + "systemStatusLoadError": "System-Status konnte nicht geladen werden. Bitte die Seite neu laden.", + "adminSettingsLoadError": "Admin-Einstellungen konnten nicht geladen werden. Schalter unten zeigen evtl. nicht den Live-Zustand — Seite neu laden.", "workerStatus": "Job-Worker", "workerRunning": "Aktiv", "workerStopped": "Gestoppt", diff --git a/messages/en.json b/messages/en.json index 64a015e51..12be0dc7d 100644 --- a/messages/en.json +++ b/messages/en.json @@ -1259,6 +1259,8 @@ "activeTokens": "Active API Tokens", "activeSessions": "Active Sessions", "loadingStatus": "Loading status...", + "systemStatusLoadError": "Failed to load system status. Try refreshing the page.", + "adminSettingsLoadError": "Failed to load admin settings. Toggles below may not reflect the live state — refresh the page.", "workerStatus": "Job Worker", "workerRunning": "Running", "workerStopped": "Stopped", diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index 688dcf152..8bb13132c 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -16,10 +16,16 @@ import { SystemStatusSection } from "@/components/admin/system-status-section"; import { UmamiSection } from "@/components/admin/umami-section"; import { UserManagementSection } from "@/components/admin/user-management-section"; import { WebPushVapidSection } from "@/components/admin/web-push-vapid-section"; +import { useAdminSettings } from "@/components/admin/_shared"; export default function AdminPage() { const { user } = useAuth(); const { t } = useTranslations(); + // P19: surface admin-settings fetch failures once at the top of the + // page. Many child sections share `useAdminSettings()` and render + // defaults silently on error — the banner makes the failure visible + // so the admin knows the toggles below aren't reflecting real state. + const { isError: settingsError } = useAdminSettings(); if (!user || user.role !== "ADMIN") return null; @@ -32,6 +38,15 @@ export default function AdminPage() {

{t("admin.subtitle")}

+ {settingsError && ( +
+ {t("admin.adminSettingsLoadError")} +
+ )} +
diff --git a/src/components/admin/system-status-section.tsx b/src/components/admin/system-status-section.tsx index 607b7ed3a..527edc1be 100644 --- a/src/components/admin/system-status-section.tsx +++ b/src/components/admin/system-status-section.tsx @@ -22,7 +22,7 @@ import { StatusItem, useSystemStatus } from "./_shared"; export function SystemStatusSection({ id }: { id: string }) { const { t } = useTranslations(); const fmt = useFormatters(); - const { data: status } = useSystemStatus(); + const { data: status, isError } = useSystemStatus(); return (
)}
+ ) : isError ? ( + // P19: surface load failures inline instead of leaving the + // section spinning forever. The hook throws on non-OK + // responses, so isError is true on 500s, network errors, etc. +
+ {t("admin.systemStatusLoadError")} +
) : (