mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 05:42:19 +00:00
feat(topics): add the Topics preview area, its navigation entry and its switch
/topics shows a tile per topic the record holds data for, and names the empty topics and the module-hidden ones once each. /topics/<topic> shows the topic today, its signals side by side over 7, 30, 90 days or a year against their usual range, how they move together, their trends, its blocks, the single-metric pages behind it and what it is missing. Every topic links into the metric pages, which stay as they are, and each page ends on a neutral note that this is a preview. Settings > System > Preview features is listed again and switches the area on for the person reading. While it is on, the sidebar carries a Topics entry with a Beta badge directly below Insights and the phone's More sheet leads with a Topics tile; the bottom bar does not change. The pages leave for Insights when the switch is off. The charts load through the shared chart runtime. The sidebar rows move into their own module and the More sheet tile into its own component, so neither shell file grows; the lab trend wording is shared between the marker page and the metabolism topic. Copy in all nine locales.
This commit is contained in:
1 parent
cc04e0944d
commit
c68e833dcc
64 files changed
+4319
-219
No files matched your search
@@ -12,6 +12,7 @@ function index(over: Partial<PaletteIndexInput> = {}) {
|
||||
t,
|
||||
modules: {},
|
||||
navModules: {},
|
||||
previews: null,
|
||||
inSharedRecord: false,
|
||||
sections: null,
|
||||
isAdmin: false,
|
||||
@@ -27,6 +28,16 @@ function index(over: Partial<PaletteIndexInput> = {}) {
|
||||
|
||||
const ids = (entries: ReturnType<typeof index>) => entries.map((e) => e.id);
|
||||
|
||||
describe("buildPaletteIndex — previews", () => {
|
||||
it("offers the Topics page only while the person switched the preview on", () => {
|
||||
expect(ids(index())).not.toContain("nav:/topics");
|
||||
expect(ids(index({ previews: { topics: false } }))).not.toContain(
|
||||
"nav:/topics",
|
||||
);
|
||||
expect(ids(index({ previews: { topics: true } }))).toContain("nav:/topics");
|
||||
});
|
||||
});
|
||||
|
||||
describe("buildPaletteIndex — modules", () => {
|
||||
it("a switched-off module takes its page, its Insights page and its cards along", () => {
|
||||
const off = { mood: false, timeline: false, environment: false };
|
||||
|
||||
@@ -18,6 +18,7 @@ import { SETTINGS_SECTIONS } from "@/components/settings/settings-shell";
|
||||
import { SUB_PAGE_SLUGS } from "@/lib/insights/sub-page-metric";
|
||||
import { MODULE_REGISTRY, type ModuleKey } from "@/lib/modules/registry";
|
||||
import { isSurfaceVisible, type SurfaceModuleMap } from "@/lib/modules/surface";
|
||||
import type { PreviewFeatures } from "@/lib/settings/preview-features";
|
||||
import type { ShareDomain } from "@/lib/sharing/scope";
|
||||
|
||||
import {
|
||||
@@ -74,6 +75,8 @@ export interface PaletteIndexInput {
|
||||
modules: SurfaceModuleMap | undefined;
|
||||
/** The same map with `coach` following the AI capability (`useNavModules`). */
|
||||
navModules: SurfaceModuleMap | undefined;
|
||||
/** The person's own preview opt-ins; null offers no preview page. */
|
||||
previews: PreviewFeatures | null;
|
||||
inSharedRecord: boolean;
|
||||
/** The shared record's covered sections, when there is one. */
|
||||
sections: ReadonlyArray<ShareDomain> | null;
|
||||
@@ -121,6 +124,7 @@ export function buildPaletteIndex(input: PaletteIndexInput): PaletteEntry[] {
|
||||
true,
|
||||
input.inSharedRecord,
|
||||
input.sections,
|
||||
input.previews,
|
||||
);
|
||||
const navHrefs = new Set(nav.map((d) => d.href));
|
||||
for (const d of nav) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { useAiCapability } from "@/hooks/use-ai-capability";
|
||||
import { useAuth } from "@/hooks/use-auth";
|
||||
import { useModuleEnabledState } from "@/hooks/use-module-toggle";
|
||||
import { useNavModules } from "@/hooks/use-nav-modules";
|
||||
import { usePreviewFeatures } from "@/hooks/use-preview-features";
|
||||
import { useRecordCapabilities } from "@/hooks/use-record-capabilities";
|
||||
import {
|
||||
buildPaletteIndex,
|
||||
@@ -32,6 +33,7 @@ export function usePaletteIndex(): PaletteEntry[] {
|
||||
const { t } = useTranslations();
|
||||
const { user } = useAuth();
|
||||
const navModules = useNavModules();
|
||||
const previews = usePreviewFeatures();
|
||||
const capabilities = useRecordCapabilities();
|
||||
const { inSharedRecord, sections, recordKind, level } = capabilities;
|
||||
const coach = useAiCapability("coach");
|
||||
@@ -64,6 +66,7 @@ export function usePaletteIndex(): PaletteEntry[] {
|
||||
t,
|
||||
modules: user?.modules,
|
||||
navModules,
|
||||
previews,
|
||||
inSharedRecord,
|
||||
sections,
|
||||
isAdmin: user?.role === "ADMIN",
|
||||
@@ -85,6 +88,7 @@ export function usePaletteIndex(): PaletteEntry[] {
|
||||
user?.modules,
|
||||
user?.role,
|
||||
navModules,
|
||||
previews,
|
||||
inSharedRecord,
|
||||
sections,
|
||||
recordKind,
|
||||
|
||||
Reference in new issue
Block a user