mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 22:02:16 +00:00
feat(modules): unify Vorsorge, Illness and Labs with the medication pattern
- add a wrench beside each module's add button linking to the module's own settings page; rename every add button to a plain "hinzufügen" - give each module a settings page: view (cards/list) + manual reorder; Labs also gets a sort-order choice (by last reading) and biomarker CRUD/reorder - collapse the Illness "abgeschlossen" list by default - rebuild the Vorsorge card on the medication card's building blocks: a green "Jetzt messen" action, the interval as a chip beside the name, and an in-interval progress signal; drop the kebab "anpassen" and stray actions - persist per-module view/order/sort client-side; add reverse-coverage-clean strings across all six locales
This commit is contained in:
1 parent
ae3091df9e
commit
267dcad13d
22 files changed
+1834
-273
No files matched your search
@@ -0,0 +1,69 @@
|
||||
"use client";
|
||||
|
||||
import { LayoutGrid, List as ListIcon } from "lucide-react";
|
||||
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { ModuleListView } from "@/lib/module-list-prefs";
|
||||
|
||||
/**
|
||||
* v1.18.6 (W8 / MOD-03) — icon-only card/list view toggle shared by the
|
||||
* Vorsorge / Illness / Labs settings pages. Mirrors the medication module's
|
||||
* `MedicationViewToggle` grammar (two ghost segments, the active one filled,
|
||||
* `aria-pressed` per segment) but switches between a card grid and a compact
|
||||
* list rather than cards-vs-table, so the label set is `moduleList.view*`.
|
||||
*/
|
||||
interface ModuleViewToggleProps {
|
||||
view: ModuleListView;
|
||||
onChange: (view: ModuleListView) => void;
|
||||
}
|
||||
|
||||
export function ModuleViewToggle({ view, onChange }: ModuleViewToggleProps) {
|
||||
const { t } = useTranslations();
|
||||
|
||||
const segments = [
|
||||
{
|
||||
value: "cards" as const,
|
||||
label: t("moduleList.viewCards"),
|
||||
icon: LayoutGrid,
|
||||
},
|
||||
{
|
||||
value: "list" as const,
|
||||
label: t("moduleList.viewList"),
|
||||
icon: ListIcon,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div
|
||||
role="group"
|
||||
aria-label={t("moduleList.viewToggleLabel")}
|
||||
className="border-border bg-background/30 inline-flex shrink-0 items-center rounded-md border p-0.5"
|
||||
>
|
||||
{segments.map(({ value, label, icon: Icon }) => {
|
||||
const active = view === value;
|
||||
return (
|
||||
<button
|
||||
key={value}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (!active) onChange(value);
|
||||
}}
|
||||
aria-pressed={active}
|
||||
aria-label={label}
|
||||
title={label}
|
||||
data-slot={`module-view-${value}`}
|
||||
className={cn(
|
||||
"focus-visible:ring-ring inline-flex size-10 items-center justify-center rounded-[5px] transition-colors focus-visible:ring-2 focus-visible:outline-none motion-reduce:transition-none sm:size-8",
|
||||
active
|
||||
? "bg-secondary text-secondary-foreground shadow-sm"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
>
|
||||
<Icon className="size-4" aria-hidden="true" />
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user