mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 06:52:04 +00:00
feat(documents): choose how the vault is laid out, and confirm every delete
The wrench beside Upload opens Settings, Appearance, Documents, the way the illness journal offers its display options: preview cards or a compact list, and months stacked as blocks or flowing across the full width with the month name inline above the document that opens it. The choice is stored per account in `users.documents_layout_json` behind GET/PUT /api/documents/inbound/layout (preserve-when-absent, module gated, the read delegable like the rest of the vault), carried in the account-settings backup and cleared by the data wipe. Deleting from the vault now always asks first. The bulk bar's Delete and a focused card's Delete key both go through one confirmation on the page, and the detail sheet's Delete opens its own; before, all three deleted on the spot with only an undo toast behind them. The selection bar is two tight lines: the count with an X at its right edge, then one action row with Delete alone at the right in the destructive style. Below 1024 px the verbs are icon-only at the 44 px tap floor, so the row stays one line at 360 px. The bar carries the selection-bar slot the Coach launcher already steps aside for.
This commit is contained in:
1 parent
ce6d2fe72a
commit
4273af231e
39 files changed
+1661
-209
No files matched your search
@@ -29,7 +29,7 @@ import {
|
||||
} from "../layout-groups";
|
||||
|
||||
describe("layout-groups registry", () => {
|
||||
it("exposes the seven Appearance modules as statically-generated subpage params", () => {
|
||||
it("exposes the eight Appearance modules as statically-generated subpage params", () => {
|
||||
expect(LAYOUT_GROUP_IDS).toEqual([
|
||||
"dashboard",
|
||||
"insights",
|
||||
@@ -37,6 +37,7 @@ describe("layout-groups registry", () => {
|
||||
"mood",
|
||||
"labs",
|
||||
"illness",
|
||||
"documents",
|
||||
"vorsorge",
|
||||
]);
|
||||
// generateStaticParams() shape.
|
||||
@@ -47,6 +48,7 @@ describe("layout-groups registry", () => {
|
||||
{ module: "mood" },
|
||||
{ module: "labs" },
|
||||
{ module: "illness" },
|
||||
{ module: "documents" },
|
||||
{ module: "vorsorge" },
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
"use client";
|
||||
|
||||
/**
|
||||
* Settings → Appearance → Documents.
|
||||
*
|
||||
* Reached from the wrench beside the vault's Upload button, the way the
|
||||
* illness journal's wrench reaches its own page. Two choices, each in its own
|
||||
* card with the toggle in the header's status slot (the illness page's
|
||||
* shape): the card/list view and the month arrangement. Both persist per user
|
||||
* through `/api/documents/inbound/layout`.
|
||||
*/
|
||||
import { Eye, Rows3, WrapText } from "lucide-react";
|
||||
|
||||
import { SettingsCardHeader } from "@/components/settings/_card-header";
|
||||
import { SettingsCard } from "@/components/settings/settings-card";
|
||||
import { ModuleViewToggle } from "@/components/module-list/module-view-toggle";
|
||||
import { ViewToggle } from "@/components/ui/view-toggle";
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
import { useDocumentsLayout } from "@/lib/queries/use-documents-layout";
|
||||
|
||||
export function DocumentsSection() {
|
||||
const { t } = useTranslations();
|
||||
const { layout, setView, setArrangement } = useDocumentsLayout();
|
||||
|
||||
return (
|
||||
<div className="space-y-6" data-slot="documents-layout-settings">
|
||||
<SettingsCard id="documents-view" className="scroll-mt-28">
|
||||
<SettingsCardHeader
|
||||
icon={Eye}
|
||||
title={t("moduleList.viewHeading")}
|
||||
description={t("documents.layout.viewDescription")}
|
||||
status={<ModuleViewToggle view={layout.view} onChange={setView} />}
|
||||
/>
|
||||
</SettingsCard>
|
||||
|
||||
<SettingsCard id="documents-arrangement" className="scroll-mt-28">
|
||||
<SettingsCardHeader
|
||||
icon={Rows3}
|
||||
title={t("documents.layout.arrangementHeading")}
|
||||
description={t("documents.layout.arrangementDescription")}
|
||||
status={
|
||||
<ViewToggle
|
||||
view={layout.arrangement}
|
||||
onChange={setArrangement}
|
||||
groupLabel={t("documents.layout.arrangementHeading")}
|
||||
dataSlotPrefix="documents-arrangement"
|
||||
segments={[
|
||||
{
|
||||
value: "stacked",
|
||||
label: t("documents.layout.stacked"),
|
||||
icon: Rows3,
|
||||
},
|
||||
{
|
||||
value: "flow",
|
||||
label: t("documents.layout.flow"),
|
||||
icon: WrapText,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</SettingsCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import { MedicationsSection } from "./medications-section";
|
||||
import { MoodSection } from "./mood-section";
|
||||
import { LabsSection } from "./labs-section";
|
||||
import { IllnessSection } from "./illness-section";
|
||||
import { DocumentsSection } from "./documents-section";
|
||||
import { VorsorgeSection } from "./vorsorge-section";
|
||||
|
||||
/**
|
||||
@@ -93,6 +94,12 @@ export const LAYOUT_GROUPS: ReadonlyArray<LayoutGroup> = [
|
||||
descriptionKey: "settings.sections.layout.illness.description",
|
||||
Body: IllnessSection,
|
||||
},
|
||||
{
|
||||
id: "documents",
|
||||
titleKey: "settings.sections.layout.documents.title",
|
||||
descriptionKey: "settings.sections.layout.documents.description",
|
||||
Body: DocumentsSection,
|
||||
},
|
||||
{
|
||||
id: "vorsorge",
|
||||
titleKey: "settings.sections.layout.vorsorge.title",
|
||||
|
||||
Reference in new issue
Block a user