mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
fix(settings): collapse Notifications redundancy onto one status surface
Telegram, ntfy, and Web Push cards used to paint their own
"Configured · Disabled / Active" badge pair in the top-right
header. The `<NotificationStatusCard>` rendered above the same
cards already shows a live channel pill ("Active · 12 min ago" /
"Auto-disabled — web_push_410_gone"), so the per-card badges were
the third (sometimes fourth) surface for the same state.
Drop the dual-Badge slot from all three cards. The section header
pill is the single source of truth, the per-card surface now
reads as identity + description + form, and the in-app vocabulary
no longer mixes "Konfiguriert", "Aktiv", and "Verbunden" for the
same fact.
Copy pass:
* Settings → Notifications description: "Live-Übersicht aller
konfigurierten Kanäle." (was a 13-word sentence repeating "Kanal"
three times).
* `notificationStatus.title` renames to "Zustellstatus" /
"Delivery status" so the page header and the first card don't
both anchor on "Kanal".
* `notificationStatus.description` compresses the "Auto-disabled"
definition.
* Telegram card title drops "-Benachrichtigungen" — the section is
Notifications, so saying it again is wasted shelf space.
* `telegramDescription` shortens to "Medikamenten-Erinnerungen
per Bot." / "Medication reminders via bot."
* `moodLogDescription` drops the second "moodLog" mention.
Notification-status SSR test updated to the new copy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
af17db5dd5
commit
ff06b0ced2
6 files changed
+36
-73
No files matched your search
+6
-6
@@ -1506,7 +1506,7 @@
|
||||
},
|
||||
"notifications": {
|
||||
"title": "Benachrichtigungen",
|
||||
"description": "Zustellung pro Kanal und die Live-Übersicht der Kanalzuverlässigkeit für jeden konfigurierten Kanal."
|
||||
"description": "Live-Übersicht aller konfigurierten Kanäle."
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "Dashboard",
|
||||
@@ -1669,8 +1669,8 @@
|
||||
"singleDevice": "Einzelgerät",
|
||||
"multiDevice": "Multi-Gerät",
|
||||
"backedUp": "gesichert",
|
||||
"telegram": "Telegram-Benachrichtigungen",
|
||||
"telegramDescription": "Erhalte Erinnerungen bei vergessenen Medikamenten-Einnahmen per Telegram.",
|
||||
"telegram": "Telegram",
|
||||
"telegramDescription": "Medikamenten-Erinnerungen per Bot.",
|
||||
"telegramSaved": "Telegram-Einstellungen gespeichert",
|
||||
"botToken": "Bot-Token",
|
||||
"chatId": "Chat-ID",
|
||||
@@ -1883,7 +1883,7 @@
|
||||
"saved": "Gespeichert",
|
||||
"savingError": "Fehler beim Speichern",
|
||||
"moodLogTitle": "moodLog",
|
||||
"moodLogDescription": "Stimmungsdaten aus moodLog importieren",
|
||||
"moodLogDescription": "Stimmungseinträge übernehmen.",
|
||||
"moodLogUrl": "moodLog URL",
|
||||
"moodLogUrlPlaceholder": "https://mood.example.com",
|
||||
"moodLogApiKey": "API-Key",
|
||||
@@ -1944,8 +1944,8 @@
|
||||
}
|
||||
},
|
||||
"notificationStatus": {
|
||||
"title": "Kanalzuverlässigkeit",
|
||||
"description": "Live-Status jedes Benachrichtigungskanals — \"Automatisch deaktiviert\" bedeutet, HealthLog hat nach einem dauerhaften Fehler aufgehört, weiterzusenden.",
|
||||
"title": "Zustellstatus",
|
||||
"description": "Pro Kanal aktueller Status; \"Automatisch deaktiviert\" stoppt nach dauerhaften Fehlern.",
|
||||
"emptyDescription": "Noch keine Kanäle konfiguriert. Lege unten einen Kanal an, um die Zustellung zu überwachen.",
|
||||
"stateActive": "Aktiv",
|
||||
"stateAutoDisabled": "Automatisch deaktiviert",
|
||||
|
||||
+6
-6
@@ -1510,7 +1510,7 @@
|
||||
},
|
||||
"notifications": {
|
||||
"title": "Notifications",
|
||||
"description": "Per-channel delivery and the live reliability board for every configured channel."
|
||||
"description": "Live overview of every configured channel."
|
||||
},
|
||||
"dashboard": {
|
||||
"title": "Dashboard",
|
||||
@@ -1676,8 +1676,8 @@
|
||||
"singleDevice": "Single device",
|
||||
"multiDevice": "Multi-device",
|
||||
"backedUp": "backed up",
|
||||
"telegram": "Telegram Notifications",
|
||||
"telegramDescription": "Get reminders for missed medication intake via Telegram.",
|
||||
"telegram": "Telegram",
|
||||
"telegramDescription": "Medication reminders via bot.",
|
||||
"telegramSaved": "Telegram settings saved",
|
||||
"botToken": "Bot Token",
|
||||
"chatId": "Chat ID",
|
||||
@@ -1890,7 +1890,7 @@
|
||||
"saved": "Saved",
|
||||
"savingError": "Error saving",
|
||||
"moodLogTitle": "moodLog",
|
||||
"moodLogDescription": "Import mood data from moodLog",
|
||||
"moodLogDescription": "Import mood entries.",
|
||||
"moodLogUrl": "moodLog URL",
|
||||
"moodLogUrlPlaceholder": "https://mood.example.com",
|
||||
"moodLogApiKey": "API Key",
|
||||
@@ -1951,8 +1951,8 @@
|
||||
}
|
||||
},
|
||||
"notificationStatus": {
|
||||
"title": "Channel reliability",
|
||||
"description": "Live status of every notification channel — Auto-disabled means HealthLog stopped retrying after a permanent error.",
|
||||
"title": "Delivery status",
|
||||
"description": "Per-channel state; \"Auto-disabled\" stops retries after permanent errors.",
|
||||
"emptyDescription": "No channels configured yet. Add a channel below to start tracking its delivery health.",
|
||||
"stateActive": "Active",
|
||||
"stateAutoDisabled": "Auto-disabled",
|
||||
|
||||
@@ -66,7 +66,7 @@ describe("<NotificationStatusCard />", () => {
|
||||
it("renders empty state when no channels exist", () => {
|
||||
setChannels([]);
|
||||
const html = render(<NotificationStatusCard />);
|
||||
expect(html).toContain("Channel reliability");
|
||||
expect(html).toContain("Delivery status");
|
||||
expect(html).toContain("No channels configured yet");
|
||||
expect(html).not.toContain('data-testid="notification-status-list"');
|
||||
});
|
||||
@@ -189,7 +189,7 @@ describe("<NotificationStatusCard />", () => {
|
||||
},
|
||||
]);
|
||||
const html = render(<NotificationStatusCard />, "de");
|
||||
expect(html).toContain("Kanalzuverlässigkeit");
|
||||
expect(html).toContain("Zustellstatus");
|
||||
expect(html).toContain("Automatisch deaktiviert");
|
||||
expect(html).toContain("Wieder aktivieren");
|
||||
});
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useState } from "react";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { Bell, Loader2, Send } from "lucide-react";
|
||||
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
@@ -101,23 +100,12 @@ export function NtfyCard({ isAuthenticated }: { isAuthenticated: boolean }) {
|
||||
|
||||
return (
|
||||
<div className="bg-card border-border rounded-xl border p-6">
|
||||
<div className="flex flex-wrap items-start justify-between gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<Bell className="text-primary h-5 w-5" />
|
||||
<h2 className="text-lg font-semibold">{t("settings.ntfy")}</h2>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{settings?.serverUrl && settings?.topic && (
|
||||
<Badge className="border-dracula-green/30 bg-dracula-green/15 text-dracula-green">
|
||||
{t("settings.configured")}
|
||||
</Badge>
|
||||
)}
|
||||
{settings?.enabled && (
|
||||
<Badge variant="outline" className="text-xs">
|
||||
{t("common.enabled")}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
{/* v1.4.33 — drop the per-card status badge pair; the channel
|
||||
pill in `<NotificationStatusCard>` above already shows
|
||||
live ntfy state. See `telegram-card.tsx` for the same fix. */}
|
||||
<div className="flex items-center gap-2">
|
||||
<Bell className="text-primary h-5 w-5" />
|
||||
<h2 className="text-lg font-semibold">{t("settings.ntfy")}</h2>
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
{t("settings.ntfyDescription")}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useState } from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { Loader2, MessageCircle, Save, Send } from "lucide-react";
|
||||
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
@@ -106,28 +105,15 @@ export function TelegramCard({
|
||||
|
||||
return (
|
||||
<div className="bg-card border-border rounded-xl border p-6">
|
||||
<div className="flex flex-wrap items-start justify-between gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<MessageCircle className="text-primary h-5 w-5" />
|
||||
<h2 className="text-lg font-semibold">{t("settings.telegram")}</h2>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{/* F-16 (v1.4.19): show one unified status pill instead of
|
||||
the previous "Configured" + "Enabled" pair, which had no
|
||||
visual hierarchy and made it unclear how the two states
|
||||
differed. The new pill collapses both bits of info:
|
||||
green when active, neutral when configured-but-paused. */}
|
||||
{settings?.hasBotToken && settings?.chatId && settings?.enabled && (
|
||||
<Badge className="border-dracula-green/30 bg-dracula-green/15 text-dracula-green">
|
||||
{t("common.active")}
|
||||
</Badge>
|
||||
)}
|
||||
{settings?.hasBotToken && settings?.chatId && !settings?.enabled && (
|
||||
<Badge variant="outline" className="text-xs">
|
||||
{t("settings.configured")} · {t("common.disabled")}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
{/* v1.4.33 — drop the per-card status badge pair. The
|
||||
`<NotificationStatusCard>` above already paints the live
|
||||
channel pill for Telegram; surfacing the same fact a
|
||||
second time inside this card produced overlapping status
|
||||
surfaces (page header + card pill + dual Badge + the
|
||||
enable Switch) for one bit of state. */}
|
||||
<div className="flex items-center gap-2">
|
||||
<MessageCircle className="text-primary h-5 w-5" />
|
||||
<h2 className="text-lg font-semibold">{t("settings.telegram")}</h2>
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
{t("settings.telegramDescription")}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { BellRing, Loader2 } from "lucide-react";
|
||||
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { TestConnectionButton } from "@/components/settings/test-connection-button";
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
@@ -157,23 +156,13 @@ export function WebPushCard() {
|
||||
|
||||
return (
|
||||
<div className="bg-card border-border rounded-xl border p-6">
|
||||
<div className="flex flex-wrap items-start justify-between gap-2">
|
||||
<div className="flex items-center gap-2">
|
||||
<BellRing className="text-primary h-5 w-5" />
|
||||
<h2 className="text-lg font-semibold">{t("settings.webPush")}</h2>
|
||||
</div>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
{!loading && isSubscribed && (
|
||||
<Badge className="border-dracula-green/30 bg-dracula-green/15 text-dracula-green">
|
||||
{t("settings.configured")}
|
||||
</Badge>
|
||||
)}
|
||||
{!loading && isSubscribed && (
|
||||
<Badge variant="outline" className="text-xs">
|
||||
{t("settings.webPushActive")}
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
{/* v1.4.33 — drop the per-card status badge pair; the channel
|
||||
pill in `<NotificationStatusCard>` above already shows
|
||||
live Web Push state. See `telegram-card.tsx` for the same
|
||||
fix. */}
|
||||
<div className="flex items-center gap-2">
|
||||
<BellRing className="text-primary h-5 w-5" />
|
||||
<h2 className="text-lg font-semibold">{t("settings.webPush")}</h2>
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
{t("settings.webPushDescription")}
|
||||
|
||||
Reference in new issue
Block a user