mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 06:06:10 +00:00
Add an `<AppSettingsProvider>` that fetches `bugReportEnabled` once via `/api/bugreport/status` and exposes it through `useAppSettings()`. The sidebar consumes the flag and conditionally renders the Bug Report entry — both in the collapsed icon mode and the expanded label mode. The bottom-nav and topbar do not surface bugreport today, so no changes were needed there. The provider mounts inside `Providers` (above the toaster), so any future flag-gated UI can reuse the same hook without re-fetching the status payload. Defaults to `true` while the query is loading or the user is unauthenticated so the entry doesn't flicker out under the cursor on slow connections. Tests: SSR-render `<SidebarNav>` with both flag states and assert the `/bugreport` href appears / disappears accordingly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
84 lines
2.9 KiB
TypeScript
84 lines
2.9 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* Client-side feature-flag context — exposes admin-managed app settings to
|
|
* layout components so nav surfaces can hide entries when the admin flips a
|
|
* toggle.
|
|
*
|
|
* Today this only carries the `bugReportEnabled` flag (the "Bug Report"
|
|
* sidebar entry, the bottom-nav, the topbar dropdown, and the user-facing
|
|
* "Report bug" buttons inside `<ErrorDetails>` all gate on it). Add new
|
|
* flags here when more admin-managed feature toggles need to reach the
|
|
* client.
|
|
*
|
|
* Source: `GET /api/bugreport/status` already returns `{ enabled }` for any
|
|
* authenticated user. We piggy-back on that endpoint instead of standing up
|
|
* a parallel `/api/app-settings` route — the data is identical and the
|
|
* caching / rate-limit story is already solved upstream.
|
|
*
|
|
* Defaults to "all flags ON" so unauthenticated layouts (login, register)
|
|
* and the brief window before the query resolves don't flicker the entry
|
|
* out from underneath the user. The admin's "off" state only takes effect
|
|
* once the data has actually arrived.
|
|
*/
|
|
|
|
import { createContext, useContext, type ReactNode } from "react";
|
|
import { useQuery } from "@tanstack/react-query";
|
|
import { useAuth } from "@/hooks/use-auth";
|
|
import { queryKeys } from "@/lib/query-keys";
|
|
|
|
export interface AppSettings {
|
|
/** Whether the admin has enabled in-app bug-report / feedback submission. */
|
|
bugReportEnabled: boolean;
|
|
}
|
|
|
|
const DEFAULT_SETTINGS: AppSettings = {
|
|
bugReportEnabled: true,
|
|
};
|
|
|
|
const AppSettingsContext = createContext<AppSettings>(DEFAULT_SETTINGS);
|
|
|
|
export function useAppSettings(): AppSettings {
|
|
return useContext(AppSettingsContext);
|
|
}
|
|
|
|
interface BugReportStatusPayload {
|
|
configured: boolean;
|
|
enabled: boolean;
|
|
isAdmin: boolean;
|
|
}
|
|
|
|
/**
|
|
* Fetches `bugReportEnabled` once per session and exposes it via context. The
|
|
* provider lives inside `Providers` so anything beneath the React tree —
|
|
* including the global nav surfaces — can observe the flag without
|
|
* each component re-fetching the same status payload.
|
|
*/
|
|
export function AppSettingsProvider({ children }: { children: ReactNode }) {
|
|
const { isAuthenticated } = useAuth();
|
|
const { data } = useQuery({
|
|
queryKey: queryKeys.bugreportStatus(),
|
|
enabled: isAuthenticated,
|
|
queryFn: async () => {
|
|
const res = await fetch("/api/bugreport/status");
|
|
if (!res.ok) throw new Error("Failed to load bug-report status");
|
|
const json = (await res.json()) as { data: BugReportStatusPayload };
|
|
return json.data;
|
|
},
|
|
staleTime: 5 * 60 * 1000,
|
|
});
|
|
|
|
// Default to ON when the query is still loading, has errored, or the user
|
|
// is unauthenticated — the nav must not flicker the entry out under the
|
|
// user's cursor on a slow network.
|
|
const settings: AppSettings = {
|
|
bugReportEnabled: data?.enabled ?? true,
|
|
};
|
|
|
|
return (
|
|
<AppSettingsContext.Provider value={settings}>
|
|
{children}
|
|
</AppSettingsContext.Provider>
|
|
);
|
|
}
|