refactor(labs): align Labs settings with the standard Settings pattern

Restructure the Labs settings sub-page to the canonical Settings dialect:
each block is a SettingsCard with a SettingsCardHeader (neutral icon, title,
short description), matching the AI / notifications / mood sections instead of
bare sections with text-sm headings. Surface the new alphabetical sort options
in the sort select.
This commit is contained in:
Marc-André Bombeck committed 2026-06-20 11:59:27 +02:00
1 parent 8ae498ffb2
commit b60b2c2bbf
7 files changed
+58 -26

No files matched your search

+2
View File
@@ -6492,6 +6492,8 @@
"label": "Reihenfolge der Werte",
"recentDesc": "Neueste Messung zuerst",
"recentAsc": "Älteste Messung zuerst",
"alphaAsc": "Name (A–Z)",
"alphaDesc": "Name (Z–A)",
"manual": "Manuell sortieren",
"hint": "Bei manueller Sortierung kannst du die Biomarker unten in deine eigene Reihenfolge bringen."
},
+2
View File
@@ -6492,6 +6492,8 @@
"label": "Order of values",
"recentDesc": "Most recent reading first",
"recentAsc": "Oldest reading first",
"alphaAsc": "Name (A–Z)",
"alphaDesc": "Name (Z–A)",
"manual": "Sort manually",
"hint": "With manual sorting you can drag the biomarkers below into your own order."
},
+2
View File
@@ -6492,6 +6492,8 @@
"label": "Orden de los valores",
"recentDesc": "Medición más reciente primero",
"recentAsc": "Medición más antigua primero",
"alphaAsc": "Nombre (A–Z)",
"alphaDesc": "Nombre (Z–A)",
"manual": "Ordenar manualmente",
"hint": "Con el orden manual puedes arrastrar los biomarcadores de abajo en tu propio orden."
},
+2
View File
@@ -6492,6 +6492,8 @@
"label": "Ordre des valeurs",
"recentDesc": "Mesure la plus récente d'abord",
"recentAsc": "Mesure la plus ancienne d'abord",
"alphaAsc": "Nom (A–Z)",
"alphaDesc": "Nom (Z–A)",
"manual": "Trier manuellement",
"hint": "En tri manuel, vous pouvez glisser les biomarqueurs ci-dessous dans votre propre ordre."
},
+2
View File
@@ -6492,6 +6492,8 @@
"label": "Ordine dei valori",
"recentDesc": "Misurazione più recente prima",
"recentAsc": "Misurazione più vecchia prima",
"alphaAsc": "Nome (A–Z)",
"alphaDesc": "Nome (Z–A)",
"manual": "Ordina manualmente",
"hint": "Con l'ordinamento manuale puoi trascinare i biomarcatori qui sotto nel tuo ordine."
},
+2
View File
@@ -6492,6 +6492,8 @@
"label": "Kolejność wartości",
"recentDesc": "Najnowszy pomiar najpierw",
"recentAsc": "Najstarszy pomiar najpierw",
"alphaAsc": "Nazwa (A–Z)",
"alphaDesc": "Nazwa (Z–A)",
"manual": "Sortuj ręcznie",
"hint": "Przy sortowaniu ręcznym możesz przeciągnąć biomarkery poniżej we własnej kolejności."
},
+46 -26
View File
@@ -14,7 +14,15 @@
* View / sort / order persist client-side via `useModuleListPrefs("labs")`.
*/
import { useQuery } from "@tanstack/react-query";
import {
ArrowDownUp,
FlaskConical,
LayoutGrid,
ListOrdered,
} from "lucide-react";
import { SettingsCard } from "@/components/settings/settings-card";
import { SettingsCardHeader } from "@/components/settings/_card-header";
import { NativeSelect } from "@/components/ui/native-select";
import { Label } from "@/components/ui/label";
import { Skeleton } from "@/components/ui/skeleton";
@@ -54,22 +62,30 @@ export function LabsSettings() {
const manual = prefs.sortDir === "manual";
// v1.18.9 (#44) — the Labs settings sub-page now follows the canonical
// Settings dialect: every block is a `<SettingsCard>` with a
// `<SettingsCardHeader>` (neutral icon + title + short description), the
// same shape as Stimmung / AI / Mitteilungen, instead of bare `<section>` +
// `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">
{/* View — card vs compact list. */}
<SettingsCard id="labs-view" className="scroll-mt-28 space-y-4">
<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("labs.sort.heading")}</h2>
{/* Sort order — recency, alphabetical, or manual. */}
<SettingsCard id="labs-sort-card" className="scroll-mt-28 space-y-4">
<SettingsCardHeader
icon={ArrowDownUp}
title={t("labs.sort.heading")}
description={t("labs.sort.hint")}
/>
<div className="space-y-2">
<Label htmlFor="labs-sort">{t("labs.sort.label")}</Label>
<NativeSelect
@@ -79,17 +95,19 @@ export function LabsSettings() {
>
<option value="recentDesc">{t("labs.sort.recentDesc")}</option>
<option value="recentAsc">{t("labs.sort.recentAsc")}</option>
<option value="alphaAsc">{t("labs.sort.alphaAsc")}</option>
<option value="alphaDesc">{t("labs.sort.alphaDesc")}</option>
<option value="manual">{t("labs.sort.manual")}</option>
</NativeSelect>
<p className="text-muted-foreground text-xs">{t("labs.sort.hint")}</p>
</div>
</section>
</SettingsCard>
{manual ? (
<section className="space-y-3">
<h2 className="text-sm font-semibold">
{t("moduleList.reorder.heading")}
</h2>
<SettingsCard id="labs-order" className="scroll-mt-28 space-y-4">
<SettingsCardHeader
icon={ListOrdered}
title={t("moduleList.reorder.heading")}
/>
{isLoading ? (
<div className="space-y-2">
{Array.from({ length: 3 }, (_, i) => (
@@ -99,15 +117,17 @@ export function LabsSettings() {
) : (
<ModuleOrderEditor items={reorderItems} onChange={setOrder} />
)}
</section>
</SettingsCard>
) : null}
<section className="space-y-3">
<h2 className="text-sm font-semibold">
{t("labs.biomarker.manageTitle")}
</h2>
{/* Biomarker catalog — define / edit / delete. */}
<SettingsCard id="labs-biomarkers" className="scroll-mt-28 space-y-4">
<SettingsCardHeader
icon={FlaskConical}
title={t("labs.biomarker.manageTitle")}
/>
<BiomarkerManager />
</section>
</SettingsCard>
</div>
);
}