mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
SURFACE_MODULE names each surface a toggleable module owns (nav entries, Insights pages, overview blocks, trend slots, add-menu entries, dashboard widgets and summaries, derived scores, Settings sections, correlation channels) as <kind>:<id>. isSurfaceVisible answers from it on the server and in the browser, useSurfaceVisible reads it against the account. The insights key owns no surface: it means AI analysis, and the Insights area is data.
35 lines
1.3 KiB
TypeScript
35 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import { useAuth } from "@/hooks/use-auth";
|
|
import { useQueryClientMounted } from "@/hooks/_internal/use-query-client-safe";
|
|
import { isSurfaceVisible, type StaticSurfaceId } from "@/lib/modules/surface";
|
|
|
|
/**
|
|
* Whether a surface shows for the record this session is on, read through the
|
|
* one surface map (`src/lib/modules/surface.ts`) against the resolved
|
|
* `modules` of `GET /api/auth/me`.
|
|
*
|
|
* SSR-safe the way `useModuleEnabled` is: a presentational component rendered
|
|
* without a `QueryClientProvider` gets the default-on answer instead of a
|
|
* crash. The branch is stable for a component's lifetime, so the conditional
|
|
* hook call is safe.
|
|
*
|
|
* Default-on: before the account resolves, and for every surface no module
|
|
* owns, the answer is `true`. A caller whose first paint must match the server
|
|
* render (nav lists, anything behind a hydration gate) keeps its own mounted
|
|
* check on top.
|
|
*/
|
|
export function useSurfaceVisible(
|
|
surfaceId: StaticSurfaceId | (string & {}),
|
|
): boolean {
|
|
const hasClient = useQueryClientMounted();
|
|
if (!hasClient) return true;
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
return useSurfaceVisibleInner(surfaceId);
|
|
}
|
|
|
|
function useSurfaceVisibleInner(surfaceId: string): boolean {
|
|
const { user } = useAuth();
|
|
return isSurfaceVisible(surfaceId, user?.modules);
|
|
}
|