From a3c0130e3d0b8922cd16f5fd8ab4878d336fc785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 9 May 2026 21:04:26 +0200 Subject: [PATCH] feat(settings): notification channel status UI with re-enable + test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v1.4.15 Phase B3, criterion 3. Wires the new into the Notifications settings section as the FIRST card, so the state of every channel (Active / Auto-disabled / Sending paused) is visible above the per-channel config. Note: the new files for this criterion (status route, status card, SSR test, i18n keys) landed in main earlier in the marathon — they were absorbed into a sibling agent's commit during a worktree race on shared-cwd staging. Commit 7c32d63 contains those files; this commit completes the wiring. The card surface (already on main) shows for each Telegram / ntfy / Web Push channel: - State badge (Active / Auto-disabled / Sending paused / Disabled). - Last successful send timestamp (locale-formatted). - Last failure + reason (e.g. web_push_410_gone). - Consecutive failure counter (only when > 0). - disabled_reason line when auto-disabled (so the user knows whether to re-pair their device, unblock the bot, etc.). - next_retry_at when in cooldown — "sending paused" is honest about WHEN it resumes. - "Re-enable" button — only painted for auto_disabled. Hits POST /api/notifications/status, which clears disabled_reason + consecutive_failures + nextRetryAt and audit-logs the override. - "Send test" button — delegates to the existing per-channel test endpoints. Disabled while the channel is auto-disabled so a user can't dispatch into a known-dead pipe. GET /api/notifications/status returns the per-channel state with a derived "active / auto_disabled / sending_paused / manually_disabled" enum. POST { channelId } re-enables an auto_disabled channel via channel-state.reEnableChannel(). Tests: 6 SSR-smoke tests cover every state branch + EN/DE locale labels. 883/883 unit tests pass; typecheck clean; lint clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/components/settings/notifications-section.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/settings/notifications-section.tsx b/src/components/settings/notifications-section.tsx index 3fc3ee2d2..aa9650247 100644 --- a/src/components/settings/notifications-section.tsx +++ b/src/components/settings/notifications-section.tsx @@ -4,6 +4,7 @@ import { useQuery } from "@tanstack/react-query"; import { useAuth } from "@/hooks/use-auth"; import { useTranslations } from "@/lib/i18n/context"; +import { NotificationStatusCard } from "@/components/settings/notification-status-card"; import { NtfyCard } from "@/components/settings/ntfy-card"; import { TelegramCard } from "@/components/settings/telegram-card"; import { WebPushCard } from "@/components/settings/web-push-card"; @@ -51,6 +52,8 @@ export function NotificationsSection() {

+ + {showTelegram && } {showNtfy && } {showWebPush && }