Files
HealthLog/src/components/settings/layout-module-gate.tsx
T
Marc-André Bombeck a01c9d0435 feat(settings): turn Appearance into a hub of per-module subpages
Appearance ("Darstellung") stacked every module's view and ordering
settings on one long page. Split it into a hub that lists the modules as
navigable rows, each opening its own /settings/layout/<module> subpage
with a back link — the per-module settings move verbatim, no restyling.
The module routes now redirect to those subpages instead of an in-page
anchor, and the in-app cogs link straight to them.
2026-06-30 18:53:50 +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 with no `moduleGate` (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}</>;
}