Files
HealthLog/src/components/settings/layout-module-gate.tsx
T
Marc-André Bombeck 9f98636a43 fix(settings): read section and overview-block owners from the surface map
Settings sections and Layout groups no longer declare their own module
keys; they ask the surface map. The Insights overview arrange list marks
the breathing, labs changes and cycle blocks unavailable when their
modules are off, as the overview itself would not show them. The rows
stay in the list so a save keeps each block's place.
2026-09-24 09:51:55 +02:00

53 lines
1.6 KiB
TypeScript

"use client";
import * as React from "react";
import { useRouter } from "next/navigation";
import { useAuth } from "@/hooks/use-auth";
import { useMounted } from "@/hooks/use-mounted";
import type { ModuleKey } from "@/lib/modules/registry";
/**
* v1.25.11 (#148) — client gate for an Appearance subpage
* (`/settings/layout/<module>`).
*
* A module's subpage may be reached by direct URL even when the user has the
* module turned off. This wrapper fails OPEN: it renders the section unless the
* resolved `useAuth().user.modules` map has the gate key explicitly `false`,
* in which case it bounces back to the hub (`/settings/layout`).
*
* The gate is hydration-stable: `useMounted()` returns `false` during SSR AND
* the first client paint, so the first render ALWAYS shows the section
* (matching the server HTML); the real check applies once, after hydration, as
* an ordinary client update. The redirect is a client-only effect, so it never
* diverges the initial render and cannot trigger a React #418 mismatch.
*
* Groups the surface map gives no owner (dashboard / insights / vorsorge)
* pass `moduleGate={undefined}` and always render.
*/
export function LayoutModuleGate({
moduleGate,
children,
}: {
moduleGate?: ModuleKey;
children: React.ReactNode;
}) {
const hydrated = useMounted();
const { user } = useAuth();
const router = useRouter();
const disabled =
hydrated &&
moduleGate !== undefined &&
user?.modules?.[moduleGate] === false;
React.useEffect(() => {
if (disabled) {
router.replace("/settings/layout");
}
}, [disabled, router]);
if (disabled) return null;
return <>{children}</>;
}