mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
fix(insights): take weight and BMI bands from the record on screen
Inside a shared or managed record the weight page shaded the band for the viewer's own height, and the record's own target never arrived because `/api/user/thresholds` refuses under a switch: a parent saw their own healthy range behind a child's weights. The BMI page decided from the viewer's height whether there was anything to show, and the target gear opened an editor that could neither load nor save there. The weight page now reads the record's target and height from `/api/insights/targets`, the payload the reference panel under the chart already uses, and paints the same wings as before. The BMI page reads the record's height there inside somebody else's record. The gear stays hidden in another person's record, as the BMI chart already draws nothing there rather than a wrong figure.
This commit is contained in:
1 parent
2c7a0dc3c2
commit
4fa5e6381e
10 files changed
+350
-43
No files matched your search
@@ -10,6 +10,12 @@ vi.mock("next/navigation", () => ({
|
||||
usePathname: () => "/insights/weight",
|
||||
}));
|
||||
|
||||
// The target gear asks whether this is somebody else's record; the shell
|
||||
// renders here without the session it would read that from.
|
||||
vi.mock("@/hooks/use-record-capabilities", () => ({
|
||||
useRecordCapabilities: () => ({ inSharedRecord: false }),
|
||||
}));
|
||||
|
||||
/**
|
||||
* v1.4.25 — `<SubPageShell>` unit tests.
|
||||
*
|
||||
|
||||
@@ -28,6 +28,11 @@ vi.mock("@/lib/insights/target-adjust-context", () => ({
|
||||
useTargetAdjust: () => useTargetAdjustMock(),
|
||||
}));
|
||||
|
||||
const capabilities = { inSharedRecord: false };
|
||||
vi.mock("@/hooks/use-record-capabilities", () => ({
|
||||
useRecordCapabilities: () => capabilities,
|
||||
}));
|
||||
|
||||
const { TargetAdjustButton } = await import("../target-adjust-button");
|
||||
|
||||
function render(node: React.ReactNode, locale: "en" | "de" = "en") {
|
||||
@@ -53,6 +58,22 @@ describe("<TargetAdjustButton>", () => {
|
||||
expect(html).toBe("");
|
||||
});
|
||||
|
||||
it("renders nothing inside somebody else's record", () => {
|
||||
// The editor reads and writes the signed-in account's own targets, which
|
||||
// the server refuses under a switch: the gear would open a dead sheet.
|
||||
useTargetAdjustMock.mockReturnValue({
|
||||
canAdjust: true,
|
||||
requestAdjust: vi.fn(),
|
||||
register: vi.fn(),
|
||||
});
|
||||
capabilities.inSharedRecord = true;
|
||||
try {
|
||||
expect(render(<TargetAdjustButton />)).toBe("");
|
||||
} finally {
|
||||
capabilities.inSharedRecord = false;
|
||||
}
|
||||
});
|
||||
|
||||
it("renders the gear once an editable target is registered", () => {
|
||||
useTargetAdjustMock.mockReturnValue({
|
||||
canAdjust: true,
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useTranslations } from "@/lib/i18n/context";
|
||||
import { useTargetAdjust } from "@/lib/insights/target-adjust-context";
|
||||
import { useRecordCapabilities } from "@/hooks/use-record-capabilities";
|
||||
|
||||
/**
|
||||
* Header gear that opens the per-metric target editor.
|
||||
@@ -20,6 +21,10 @@ import { useTargetAdjust } from "@/lib/insights/target-adjust-context";
|
||||
* has registered for the page (e.g. a metric without a numeric
|
||||
* target band, where the card paints nothing), so the header never
|
||||
* shows a dead control;
|
||||
* - renders nothing inside somebody else's record: the editor loads and
|
||||
* saves the signed-in account's own targets (`/api/user/thresholds`),
|
||||
* which refuses under a switch, so the gear would open a sheet that
|
||||
* can do neither;
|
||||
* - opens the primary registered target's `<TargetEditSheet>` on click.
|
||||
*
|
||||
* Sized to match `<CoachLaunchButton variant="icon">` so the gear + the
|
||||
@@ -29,9 +34,11 @@ import { useTargetAdjust } from "@/lib/insights/target-adjust-context";
|
||||
export function TargetAdjustButton({ className }: { className?: string }) {
|
||||
const { t } = useTranslations();
|
||||
const adjust = useTargetAdjust();
|
||||
const { inSharedRecord } = useRecordCapabilities();
|
||||
|
||||
// No provider, or no editable target registered for this page.
|
||||
if (!adjust || !adjust.canAdjust) return null;
|
||||
// No provider, no editable target registered for this page, or a record
|
||||
// whose targets this editor cannot reach.
|
||||
if (!adjust || !adjust.canAdjust || inSharedRecord) return null;
|
||||
|
||||
// Reuse the action's existing copy ("Adjust target range" /
|
||||
// "Zielbereich anpassen") — the gear performs exactly what the old
|
||||
|
||||
Reference in new issue
Block a user