mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
fix(settings): align the Vorsorge settings card with the shared pattern
Adopt the standard SettingsCard + SettingsCardHeader contract for the three Vorsorge settings groups (view, order, manage): bordered card surface, neutral muted section icon, text-lg title, and a short muted description, replacing the bare sections with text-sm headings so the surface reads like every other Settings section. Add a reorder description string across all locales.
This commit is contained in:
1 parent
aae65b8bb1
commit
ed99d207e4
7 files changed
+90
-73
No files matched your search
@@ -6472,6 +6472,7 @@
|
||||
"viewDescription": "Lege fest, ob die Einträge als Karten oder als kompakte Liste angezeigt werden.",
|
||||
"reorder": {
|
||||
"heading": "Reihenfolge",
|
||||
"description": "Ziehe die Einträge, um ihre Reihenfolge festzulegen.",
|
||||
"empty": "Noch keine Einträge zum Sortieren."
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6472,6 +6472,7 @@
|
||||
"viewDescription": "Choose whether entries show as cards or as a compact list.",
|
||||
"reorder": {
|
||||
"heading": "Order",
|
||||
"description": "Drag the entries to set the order they appear in.",
|
||||
"empty": "No entries to reorder yet."
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6472,6 +6472,7 @@
|
||||
"viewDescription": "Elige si las entradas se muestran como tarjetas o como lista compacta.",
|
||||
"reorder": {
|
||||
"heading": "Orden",
|
||||
"description": "Arrastra las entradas para definir el orden en que aparecen.",
|
||||
"empty": "Aún no hay entradas para ordenar."
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6472,6 +6472,7 @@
|
||||
"viewDescription": "Choisissez si les entrées s'affichent en cartes ou en liste compacte.",
|
||||
"reorder": {
|
||||
"heading": "Ordre",
|
||||
"description": "Faites glisser les entrées pour définir leur ordre d'affichage.",
|
||||
"empty": "Aucune entrée à réordonner pour l'instant."
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6472,6 +6472,7 @@
|
||||
"viewDescription": "Scegli se le voci appaiono come schede o come elenco compatto.",
|
||||
"reorder": {
|
||||
"heading": "Ordine",
|
||||
"description": "Trascina le voci per definire l'ordine in cui appaiono.",
|
||||
"empty": "Nessuna voce da riordinare."
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6472,6 +6472,7 @@
|
||||
"viewDescription": "Wybierz, czy pozycje mają być pokazywane jako karty czy jako zwarta lista.",
|
||||
"reorder": {
|
||||
"heading": "Kolejność",
|
||||
"description": "Przeciągnij pozycje, aby ustawić kolejność ich wyświetlania.",
|
||||
"empty": "Brak pozycji do uporządkowania."
|
||||
}
|
||||
},
|
||||
|
||||
@@ -10,10 +10,14 @@
|
||||
* `useModuleListPrefs("vorsorge")`; the toggles persist through the existing
|
||||
* reminder PATCH route.
|
||||
*/
|
||||
import { ArrowUpDown, LayoutGrid, ListChecks } from "lucide-react";
|
||||
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
import { SettingsCard } from "@/components/settings/settings-card";
|
||||
import { SettingsCardHeader } from "@/components/settings/_card-header";
|
||||
import { ModuleViewToggle } from "@/components/module-list/module-view-toggle";
|
||||
import {
|
||||
ModuleOrderEditor,
|
||||
@@ -52,82 +56,89 @@ export function VorsorgeSettings() {
|
||||
: t("measurementReminders.selfPlanned"),
|
||||
}));
|
||||
|
||||
// v1.18.10 (W7) — the three Vorsorge settings groups adopt the shared
|
||||
// `SettingsCard` + `SettingsCardHeader` contract (rounded-xl bordered
|
||||
// surface, neutral muted icon, `text-lg` title, short muted description)
|
||||
// so this surface reads like every other Settings section instead of bare
|
||||
// `<section>` blocks with `text-sm` headings.
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<section className="space-y-3">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<h2 className="text-sm font-semibold">
|
||||
{t("moduleList.viewHeading")}
|
||||
</h2>
|
||||
<ModuleViewToggle view={prefs.view} onChange={setView} />
|
||||
</div>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t("moduleList.viewDescription")}
|
||||
</p>
|
||||
</section>
|
||||
<div className="space-y-6">
|
||||
<SettingsCard>
|
||||
<SettingsCardHeader
|
||||
icon={LayoutGrid}
|
||||
title={t("moduleList.viewHeading")}
|
||||
description={t("moduleList.viewDescription")}
|
||||
status={<ModuleViewToggle view={prefs.view} onChange={setView} />}
|
||||
/>
|
||||
</SettingsCard>
|
||||
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-sm font-semibold">
|
||||
{t("moduleList.reorder.heading")}
|
||||
</h2>
|
||||
{isLoading ? (
|
||||
<div className="space-y-2">
|
||||
{Array.from({ length: 3 }, (_, i) => (
|
||||
<Skeleton key={i} className="h-12 w-full" />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<ModuleOrderEditor items={reorderItems} onChange={setOrder} />
|
||||
)}
|
||||
</section>
|
||||
|
||||
<section className="space-y-3">
|
||||
<h2 className="text-sm font-semibold">
|
||||
{t("measurementReminders.manage.title")}
|
||||
</h2>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t("measurementReminders.manage.description")}
|
||||
</p>
|
||||
{isLoading ? (
|
||||
<Skeleton className="h-24 w-full" />
|
||||
) : (reminders?.length ?? 0) === 0 ? (
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t("measurementReminders.manage.empty")}
|
||||
</p>
|
||||
) : (
|
||||
<Card>
|
||||
<CardContent className="divide-border divide-y p-0">
|
||||
{ordered.map((reminder) => (
|
||||
<div
|
||||
key={reminder.id}
|
||||
className="flex items-center justify-between gap-3 px-4 py-3"
|
||||
>
|
||||
<span
|
||||
id={`vorsorge-reminder-label-${reminder.id}`}
|
||||
className="min-w-0 truncate text-sm"
|
||||
>
|
||||
{resolveLabel(reminder, t)}
|
||||
</span>
|
||||
<Switch
|
||||
checked={reminder.enabled}
|
||||
onCheckedChange={(next) =>
|
||||
update.mutate({
|
||||
id: reminder.id,
|
||||
body: { enabled: next },
|
||||
})
|
||||
}
|
||||
disabled={update.isPending}
|
||||
// L3 — label each row's Switch by its own name span so SR
|
||||
// users hear the reminder name (plus the switch role's
|
||||
// on/off state) instead of N identical generic labels.
|
||||
aria-labelledby={`vorsorge-reminder-label-${reminder.id}`}
|
||||
/>
|
||||
</div>
|
||||
<SettingsCard>
|
||||
<SettingsCardHeader
|
||||
icon={ArrowUpDown}
|
||||
title={t("moduleList.reorder.heading")}
|
||||
description={t("moduleList.reorder.description")}
|
||||
/>
|
||||
<div className="mt-4 pl-7">
|
||||
{isLoading ? (
|
||||
<div className="space-y-2">
|
||||
{Array.from({ length: 3 }, (_, i) => (
|
||||
<Skeleton key={i} className="h-12 w-full" />
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
) : (
|
||||
<ModuleOrderEditor items={reorderItems} onChange={setOrder} />
|
||||
)}
|
||||
</div>
|
||||
</SettingsCard>
|
||||
|
||||
<SettingsCard>
|
||||
<SettingsCardHeader
|
||||
icon={ListChecks}
|
||||
title={t("measurementReminders.manage.title")}
|
||||
description={t("measurementReminders.manage.description")}
|
||||
/>
|
||||
<div className="mt-4 pl-7">
|
||||
{isLoading ? (
|
||||
<Skeleton className="h-24 w-full" />
|
||||
) : (reminders?.length ?? 0) === 0 ? (
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t("measurementReminders.manage.empty")}
|
||||
</p>
|
||||
) : (
|
||||
<Card>
|
||||
<CardContent className="divide-border divide-y p-0">
|
||||
{ordered.map((reminder) => (
|
||||
<div
|
||||
key={reminder.id}
|
||||
className="flex items-center justify-between gap-3 px-4 py-3"
|
||||
>
|
||||
<span
|
||||
id={`vorsorge-reminder-label-${reminder.id}`}
|
||||
className="min-w-0 truncate text-sm"
|
||||
>
|
||||
{resolveLabel(reminder, t)}
|
||||
</span>
|
||||
<Switch
|
||||
checked={reminder.enabled}
|
||||
onCheckedChange={(next) =>
|
||||
update.mutate({
|
||||
id: reminder.id,
|
||||
body: { enabled: next },
|
||||
})
|
||||
}
|
||||
disabled={update.isPending}
|
||||
// L3 — label each row's Switch by its own name span so SR
|
||||
// users hear the reminder name (plus the switch role's
|
||||
// on/off state) instead of N identical generic labels.
|
||||
aria-labelledby={`vorsorge-reminder-label-${reminder.id}`}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</SettingsCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user