mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 14:40:52 +00:00
Merge work/hero-score-panel
This commit is contained in:
commit
f8074e1b07
10 files changed
+1811
-367
No files matched your search
@@ -268,42 +268,55 @@ describe("v1.16.8 — insights overview cold paint", () => {
|
||||
expect(src).not.toMatch(/useDashboardDerived\([^)]*data/);
|
||||
});
|
||||
|
||||
it("reserves the health-score card's footprint while the payload is pending", () => {
|
||||
it("reserves the score column's footprint while the payload is pending", () => {
|
||||
const src = load(INSIGHTS_PATH);
|
||||
// The pinned slot holds the collapsed card's footprint from first paint,
|
||||
// so the resolved card is a swap rather than a push.
|
||||
// The reserve holds the column from first paint, so the resolved panel is
|
||||
// a swap rather than a push.
|
||||
expect(src).toMatch(
|
||||
/analyticsQuery\.isPending && !analytics \? \(\s*<HealthScoreCardSkeleton/,
|
||||
/scorePending=\{analyticsQuery\.isPending && !analytics\}/,
|
||||
);
|
||||
});
|
||||
|
||||
it("pins the health score under the hero, outside the section registry", () => {
|
||||
it("mounts the health score once, in the hero, outside the section registry", () => {
|
||||
const src = load(INSIGHTS_PATH);
|
||||
// An id a saved layout has never seen merges in as default-INVISIBLE, so
|
||||
// registering the score would delete it for every customised page. It is
|
||||
// also no longer inside the briefing branch, which used to take the whole
|
||||
// also outside the briefing branch, which used to take the whole
|
||||
// breakdown down with the flag.
|
||||
const hero = src.indexOf("<HeroStrip");
|
||||
const score = src.indexOf("<HealthScoreCard");
|
||||
const region = src.indexOf("orderedSectionIds.map");
|
||||
// The JSX mount, not the `<HeroStrip>` mentioned in the file's header
|
||||
// comment — matching the comment would have made the slice below read a
|
||||
// block of prose and pass on nothing.
|
||||
const hero = src.search(/\n\s*<HeroStrip\n/);
|
||||
expect(hero).toBeGreaterThan(-1);
|
||||
expect(score).toBeGreaterThan(hero);
|
||||
expect(score).toBeLessThan(region);
|
||||
expect(src).not.toMatch(/"health-score":/);
|
||||
|
||||
// Exactly one score surface on the page, and it is the hero's prop.
|
||||
expect(src.match(/healthScore=\{/g) ?? []).toHaveLength(1);
|
||||
expect(src).not.toContain("<HealthScoreCard");
|
||||
expect(src).not.toContain("<HealthScoreCardSkeleton");
|
||||
|
||||
const briefingBranch = src.slice(
|
||||
src.indexOf('"daily-briefing": flags.briefing'),
|
||||
src.indexOf("vitals: <VitalsDashboard"),
|
||||
);
|
||||
expect(briefingBranch).not.toContain("HealthScoreCard");
|
||||
expect(briefingBranch).not.toContain("healthScore");
|
||||
// The band itself is not gated on the briefing flag either.
|
||||
const heroCall = src.slice(hero, src.indexOf("/>", hero));
|
||||
expect(heroCall).toContain("healthScore={analytics?.healthScore ?? null}");
|
||||
expect(heroCall).not.toContain("flags.briefing");
|
||||
});
|
||||
|
||||
it("hero strip carries no score surface at all", () => {
|
||||
it("hero strip owns the one score surface", () => {
|
||||
const heroSrc = readFileSync(
|
||||
join(ROOT, "src/components/insights/hero-strip.tsx"),
|
||||
"utf8",
|
||||
);
|
||||
expect(heroSrc).not.toContain("HealthScoreCard");
|
||||
expect(heroSrc).not.toContain("health-score-card-skeleton");
|
||||
expect(heroSrc).not.toContain("healthScorePending");
|
||||
expect(heroSrc).toContain("<HealthScoreCard");
|
||||
expect(heroSrc).toContain("<HealthScoreCardSkeleton");
|
||||
// The split appears only when the column has something in it.
|
||||
expect(heroSrc).toContain("md:flex-row md:items-stretch");
|
||||
expect(heroSrc).toMatch(
|
||||
/\(healthScore \|\| scorePending\) &&\s*"md:flex-row/,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -26,10 +26,6 @@ import { QueryErrorCard } from "@/components/ui/query-error-card";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { HeroStrip } from "@/components/insights/hero-strip";
|
||||
import {
|
||||
HealthScoreCard,
|
||||
HealthScoreCardSkeleton,
|
||||
} from "@/components/insights/health-score-card";
|
||||
import { useInsightsAdvisorQuery } from "@/components/insights/use-insights-advisor";
|
||||
import { useAnalyticsQuery } from "@/lib/queries/use-analytics-query";
|
||||
import { useDashboardSnapshot } from "@/lib/queries/use-dashboard-snapshot";
|
||||
@@ -561,33 +557,27 @@ export default function InsightsPageClient() {
|
||||
// <relative>" line with a discreet connect-provider hint, matching
|
||||
// the briefing card footer. Only when a briefing is actually shown.
|
||||
noProviderStale={briefingPayload !== null && !advisor.hasProvider}
|
||||
// The Health Score lives in the band's right column and NOWHERE else
|
||||
// on this page. It is deliberately not a registry section: an id a
|
||||
// saved layout has never seen merges in as default-INVISIBLE
|
||||
// (`orderedVisibleSectionIds`), so registering it would silently
|
||||
// delete the score for every account that has ever customised this
|
||||
// page. It is also outside the daily-briefing branch, so an instance
|
||||
// with the briefing switched off keeps the whole breakdown.
|
||||
healthScore={analytics?.healthScore ?? null}
|
||||
// `isPending` settles false on success AND error, so a no-score
|
||||
// account drops the reserve exactly once.
|
||||
scorePending={analyticsQuery.isPending && !analytics}
|
||||
// v1.21.2 (A5 / A6) — server-resolved Tension Verdict + return-to-
|
||||
// baseline off the dashboard snapshot. The panel localises the keys;
|
||||
// null leaves it quiet.
|
||||
tension={heroTension}
|
||||
returnToBand={heroReturnToBand}
|
||||
// A pillar whose read FAILED is a named line inside the panel, and the
|
||||
// retry there refetches the payload that carries every pillar.
|
||||
onScoreRetry={() => void analyticsQuery.refetch()}
|
||||
/>
|
||||
|
||||
{/* The Health Score is PINNED here, between the greeting and the
|
||||
customizable region, and is deliberately NOT a registry section: an
|
||||
id a saved layout has never seen merges in as default-INVISIBLE
|
||||
(`orderedVisibleSectionIds`), so registering it would silently delete
|
||||
the score for every account that has ever customised this page. It
|
||||
also used to render inside the daily-briefing branch, which meant an
|
||||
instance with the briefing switched off lost the whole breakdown.
|
||||
`isPending` settles false on success AND error, so a no-score account
|
||||
drops the reserve exactly once. */}
|
||||
{analyticsQuery.isPending && !analytics ? (
|
||||
<HealthScoreCardSkeleton />
|
||||
) : analytics?.healthScore ? (
|
||||
<HealthScoreCard
|
||||
report={analytics.healthScore}
|
||||
// v1.21.2 (A5 / A6) — server-resolved Tension Verdict + return-to-
|
||||
// baseline off the dashboard snapshot. The card localises the keys;
|
||||
// null leaves it quiet.
|
||||
tension={heroTension}
|
||||
returnToBand={heroReturnToBand}
|
||||
// A pillar whose read FAILED is an error row inside the card, and a
|
||||
// retry there refetches the payload that carries every pillar.
|
||||
onRetry={() => void analyticsQuery.refetch()}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{/* v1.15.18 — the inline "Anpassen" toggle was removed. Customising the
|
||||
overview (section show/hide + order) and sorting the nav pills now
|
||||
live ONLY in Settings → Insights, reached via the top-right cog on the
|
||||
|
||||
Reference in new issue
Block a user