mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
fix(demo): keep the demo dashboard to the measurement charts
The shared demo account carries onboarding answers, so the setup checklist stayed on its dashboard for every visitor although none of its rows can be done there. Under DEMO_MODE the dashboard leaves it out, as the shell already does with the tour. The demo seed hides the mood and medication cards, achievements, recent workouts and check-ups, opens weight, BMI and blood pressure on 90 days, and resting heart rate on 30 with its 7-day trend and trend line.
This commit is contained in:
1 parent
5502342ec5
commit
52c6c8dc9b
4 files changed
+79
-7
No files matched your search
+28
-3
@@ -90,6 +90,7 @@ import {
|
||||
import { ENVIRONMENT_LOCATION_AAD } from "../src/lib/crypto/encrypted-columns";
|
||||
import { sealInsightsCachedText } from "../src/lib/insights/cached-text-cipher";
|
||||
import {
|
||||
DEFAULT_CHART_OVERLAY_PREFS,
|
||||
DEFAULT_DASHBOARD_LAYOUT,
|
||||
serializeDashboardLayout,
|
||||
} from "../src/lib/dashboard-layout";
|
||||
@@ -497,16 +498,40 @@ async function seed() {
|
||||
// One row of six tiles (weight, the two blood-pressure values, resting
|
||||
// heart rate, HRV and mood) and the weight chart right below it, so the
|
||||
// first screen of the public demo shows the summary, the tiles and the
|
||||
// start of a chart together. Every other tile stays one switch away in
|
||||
// the layout settings; its data is seeded either way. Writing the layout
|
||||
// verbatim keeps the demo's home page stable across default tweaks.
|
||||
// start of a chart together. Below it only the measurement charts: the
|
||||
// mood and medication cards, achievements, recent workouts and check-ups
|
||||
// stay one switch away in the layout settings, their data seeded either
|
||||
// way. Weight, BMI and blood pressure open on 90 days, resting heart rate
|
||||
// on 30 with its 7-day trend and trend line, so each chart shows a shape
|
||||
// rather than a flat week. Writing the layout verbatim keeps the demo's
|
||||
// home page stable across default tweaks.
|
||||
const SHOWCASE_TILE_IDS = new Set(["weight", "bp", "pulse", "hrv", "mood"]);
|
||||
const HIDDEN_CARD_IDS = new Set([
|
||||
"mood",
|
||||
"medications",
|
||||
"achievements",
|
||||
"recentWorkouts",
|
||||
"vorsorge",
|
||||
]);
|
||||
const demoDashboardLayout = serializeDashboardLayout({
|
||||
...DEFAULT_DASHBOARD_LAYOUT,
|
||||
widgets: DEFAULT_DASHBOARD_LAYOUT.widgets.map((w) => ({
|
||||
...w,
|
||||
visible: w.visible && !HIDDEN_CARD_IDS.has(w.id),
|
||||
tileVisible: SHOWCASE_TILE_IDS.has(w.id),
|
||||
})),
|
||||
chartOverlayPrefs: {
|
||||
weight: { ...DEFAULT_CHART_OVERLAY_PREFS, rangePoints: 90 },
|
||||
bmi: { ...DEFAULT_CHART_OVERLAY_PREFS, rangePoints: 90 },
|
||||
bp: { ...DEFAULT_CHART_OVERLAY_PREFS, rangePoints: 90 },
|
||||
// The resting heart rate chart is the dashboard's `pulse` chart.
|
||||
pulse: {
|
||||
...DEFAULT_CHART_OVERLAY_PREFS,
|
||||
rangePoints: 30,
|
||||
showTrendIndicator: true,
|
||||
showTrendArrow: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
await client.query(
|
||||
`UPDATE users SET dashboard_widgets_json = $1 WHERE id = $2`,
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
/**
|
||||
* The setup checklist on a demo instance.
|
||||
*
|
||||
* The demo is one shared, read-only account carrying onboarding answers, so
|
||||
* `isStillInSetup` keeps the checklist on screen for every visitor although
|
||||
* none of its rows can be done there. The shell already leaves out the tour
|
||||
* under `DEMO_MODE`; the dashboard leaves out the checklist the same way.
|
||||
* Pinned here: every render path of the page threads the flag, and the
|
||||
* client mounts the checklist only without it.
|
||||
*/
|
||||
const PAGE_PATH = join(process.cwd(), "src/app/page.tsx");
|
||||
const CLIENT_PATH = join(process.cwd(), "src/app/page-client.tsx");
|
||||
|
||||
describe("dashboard setup checklist on a demo instance", () => {
|
||||
it("threads DEMO_MODE into every render of the dashboard client", () => {
|
||||
const src = readFileSync(PAGE_PATH, "utf8");
|
||||
expect(src).toContain('process.env.DEMO_MODE === "true"');
|
||||
const renders = src.match(/<DashboardPageClient\b[^>]*>/g) ?? [];
|
||||
expect(renders.length).toBeGreaterThan(0);
|
||||
for (const render of renders) {
|
||||
expect(render).toContain("demoMode={demoMode}");
|
||||
}
|
||||
});
|
||||
|
||||
it("mounts the checklist only outside demo mode", () => {
|
||||
const src = readFileSync(CLIENT_PATH, "utf8");
|
||||
const mounts = src.match(/<GettingStartedChecklist\b[^>]*\/>/g) ?? [];
|
||||
expect(mounts).toHaveLength(1);
|
||||
expect(src).toContain("{demoMode ? null : <GettingStartedChecklist />}");
|
||||
});
|
||||
});
|
||||
@@ -193,6 +193,7 @@ import {
|
||||
|
||||
export default function DashboardPageClient({
|
||||
batchWindow: batchWindowProp,
|
||||
demoMode = false,
|
||||
}: {
|
||||
/**
|
||||
* v1.30.9 — the batched-series ISO window computed server-side from the
|
||||
@@ -204,6 +205,12 @@ export default function DashboardPageClient({
|
||||
* under, so the prefetched slice lands instead of triggering a refetch.
|
||||
*/
|
||||
batchWindow?: BatchWindow;
|
||||
/**
|
||||
* True on a `DEMO_MODE` instance. The demo is one shared, read-only
|
||||
* account a visitor cannot set up, so the setup checklist has nothing to
|
||||
* offer there, as the shell already leaves out the tour.
|
||||
*/
|
||||
demoMode?: boolean;
|
||||
} = {}) {
|
||||
const { isAuthenticated } = useAuth();
|
||||
const mounted = useMounted();
|
||||
@@ -2312,7 +2319,7 @@ export default function DashboardPageClient({
|
||||
* content (tiles, charts) keeps a stable position, and the
|
||||
* near-empty dashboards of the new accounts the card targets keep
|
||||
* it visible without scrolling anyway. */}
|
||||
<GettingStartedChecklist />
|
||||
{demoMode ? null : <GettingStartedChecklist />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+8
-3
@@ -76,12 +76,15 @@ const DIGEST_SOFT_BUDGET_MS = 400;
|
||||
* others.
|
||||
*/
|
||||
export default async function DashboardPage() {
|
||||
// `DEMO_MODE` is a server-only env var; resolved here and threaded in, as
|
||||
// the layout does for the shell.
|
||||
const demoMode = process.env.DEMO_MODE === "true";
|
||||
// Operator/test escape hatch: `DASHBOARD_SSR_PREFETCH=false` renders the
|
||||
// pure client-fetch dashboard (pre-prefetch behaviour). The e2e server
|
||||
// sets it so Playwright route mocks — which only see CLIENT fetches —
|
||||
// keep governing what the dashboard paints. It gates EVERY prefetch below.
|
||||
if (process.env.DASHBOARD_SSR_PREFETCH === "false") {
|
||||
return <DashboardPageClient />;
|
||||
return <DashboardPageClient demoMode={demoMode} />;
|
||||
}
|
||||
let dehydratedState = null;
|
||||
let batchWindow: BatchWindow | undefined;
|
||||
@@ -171,11 +174,13 @@ export default async function DashboardPage() {
|
||||
}
|
||||
|
||||
if (dehydratedState === null) {
|
||||
return <DashboardPageClient batchWindow={batchWindow} />;
|
||||
return (
|
||||
<DashboardPageClient batchWindow={batchWindow} demoMode={demoMode} />
|
||||
);
|
||||
}
|
||||
return (
|
||||
<HydrationBoundary state={dehydratedState}>
|
||||
<DashboardPageClient batchWindow={batchWindow} />
|
||||
<DashboardPageClient batchWindow={batchWindow} demoMode={demoMode} />
|
||||
</HydrationBoundary>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user