mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +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
@@ -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