mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 13:52:20 +00:00
The sweep that follows from the primitives. Nothing here is new behaviour; every change removes a second way of saying something the surface already said one way somewhere else. Headers. The two collapsible security cards stop rebuilding `SettingsCardHeader` by hand to carry a chevron — the chevron rides inside the title button, and the description moves out of the collapsed region, so the first paint is no longer a bare title. The import card shell, the export and import section headings, and the four free-standing group headers stop inventing their own type scale: a heading above a GROUP of cards is `SectionHeading` (`text-base`), a card title is `SettingsCardHeader` (`text-lg`), and the step between them is what says which is which. The targets card gets a title instead of a naked icon. Actions. Every card-level row is `SettingsCardActions`. The primary action comes out of the header's status slot in six cards (password, web push, pillar order, coach memory, and the two danger-zone triggers) and out of the middle of the card in three more; the reset that hung in the dashboard-layout header joins save as a secondary in the same row. Result and status lines move ABOVE the row — sources' cross-link, the invite form's two status lines — because nothing follows a card's actions. Revoking a share link is `variant="destructive"` rather than an `outline` hand-tinted red in two different ways. The import row had four variants for four buttons; it has two. Export downloads are the card's primary, not an outline link. Integrations. One description sentence with the setup-guide link inline: the second paragraph was byte-identical across six of eight cards, which is the tell that it said nothing about the provider it sat under. The `<hr>` under the header — which existed only in this folder — is gone. So is the hint that pointed at a guide 40 px above it, and the second format for "not configured". Connect is one button everywhere: primary, `sm`, in the action row, instead of primary-and-small in three cards and outline-and-large in four. Plus the standards leftovers the audit listed: two `pl-5` list gutters, one `scroll-mt-20` anchor, a purple header icon, `text-[10px]` badges, four hand-rolled callout shells that `SettingsInfoTile` already paints, and the two inline buttons that never had the mobile tap floor at all.
96 lines
3.9 KiB
TypeScript
96 lines
3.9 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { Bell } from "lucide-react";
|
|
|
|
import { useAuth } from "@/hooks/use-auth";
|
|
import { useTranslations } from "@/lib/i18n/context";
|
|
import { LowStockCard } from "@/components/settings/low-stock-card";
|
|
import { SectionHeading } from "@/components/ui/section-heading";
|
|
import { MoodReminderCard } from "@/components/settings/mood-reminder-card";
|
|
import { Button } from "@/components/ui/button";
|
|
|
|
/**
|
|
* `<NotificationsSection>` — Settings → Notifications ("Benachrichtigungen").
|
|
*
|
|
* v1.18.0 (S4) — the single module-gated home for reminder TYPES. Earlier the
|
|
* settings carried two near-identical entries: this Notifications screen and a
|
|
* separate "Erinnerungen" hub that only deep-linked into the canonical editors
|
|
* ("doppelt gemoppelt"). The hub is gone (its route 301-redirects here); the
|
|
* reminder TYPES now live centrally on this one screen.
|
|
*
|
|
* Each reminder-type card is shown ONLY when its module is enabled, read from
|
|
* the resolved `useAuth().user.modules` map (the same `/auth/me` map nav and
|
|
* Insights pills gate off). Mood → `mood`, low-stock runway → `medications`
|
|
* (a toggleable fail-open module since D3, so a missing key reads as enabled
|
|
* and a stale `/me` payload never blanks a card).
|
|
*
|
|
* v1.25.7 — delivery channels move to Settings → Integrationen (channels are
|
|
* delivery providers, the same family as the connected services). This screen
|
|
* keeps ONLY the reminder-TYPE content; `/settings/channels` 301-redirects to
|
|
* `/settings/integrations#channels`.
|
|
*
|
|
* v1.18.6 (W9) — the page heading + subtitle come from the shared
|
|
* `<SettingsSectionFrame>`. The proactive-Coach nudge card lives under
|
|
* Settings → Coach (it is a Coach setting, not a generic notification).
|
|
*/
|
|
export function NotificationsSection() {
|
|
const { isAuthenticated, user } = useAuth();
|
|
const { t } = useTranslations();
|
|
|
|
// v1.18.0 (S4) — module-gated per-type visibility. Fail OPEN (`!== false`)
|
|
// so a stale `/me` payload without the module map keeps every card visible.
|
|
const moodEnabled = user?.modules?.mood !== false;
|
|
const medsEnabled = user?.modules?.medications !== false;
|
|
const anyReminder = moodEnabled || medsEnabled;
|
|
|
|
return (
|
|
<div className="space-y-10">
|
|
{/* Group 1 — Reminders ("what you receive"). Rendered only when at
|
|
least one reminder-type card is visible, so a fully-disabled
|
|
account never shows an empty heading. */}
|
|
{anyReminder ? (
|
|
<section className="space-y-4">
|
|
<SectionHeading
|
|
icon={Bell}
|
|
title={t("settings.sections.notifications.remindersHeading")}
|
|
/>
|
|
|
|
{/* Mood check-in reminder — only when the mood module is enabled. */}
|
|
{moodEnabled ? (
|
|
<div id="mood-reminder" className="scroll-mt-28">
|
|
<MoodReminderCard isAuthenticated={isAuthenticated} />
|
|
</div>
|
|
) : null}
|
|
|
|
{/* Medication low-stock runway — only when the medications module
|
|
is enabled (toggleable, fail-open, since D3). */}
|
|
{medsEnabled ? (
|
|
<div id="low-stock" className="scroll-mt-28">
|
|
<LowStockCard isAuthenticated={isAuthenticated} />
|
|
</div>
|
|
) : null}
|
|
</section>
|
|
) : null}
|
|
{/* Cross-links to the other two notification surfaces. At the END of
|
|
the page: a screen that opens with two ways off it never says what
|
|
it is for. */}
|
|
<div
|
|
className="flex flex-wrap gap-2"
|
|
data-slot="notifications-crosslinks"
|
|
>
|
|
<Button asChild variant="outline" size="sm">
|
|
<Link href="/notifications">
|
|
{t("settings.sections.notifications.matrixLink")}
|
|
</Link>
|
|
</Button>
|
|
<Button asChild variant="outline" size="sm">
|
|
<Link href="/settings/integrations#channels">
|
|
{t("settings.sections.notifications.channelsLink")}
|
|
</Link>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|