mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
Five independent atomic edits from the W5 simplify review, grouped in a single commit since none pull weight as a compound theme: - coach-input: collapse `!disabled && value.trim().length > 0` triplication onto a single `canSubmit` (S-01). - hero-strip: extract the duplicate weekly-report Button shell into a shared label fragment with the Link wrapping conditionally (S-02). - api-token-overview-section: extract `<TokenStatusBadge size>` so the desktop table and mobile card list stay in lock-step on the revoked / expired / active 3-way ternary (S-03). - trends-row: hoist the dynamic-load chart skeleton to a shared `ChartSkeleton` component (S-04). No chart-visual change — placeholder only. - correlation-row: collapse the grid className ternary onto `cn()` with a conditional `md:grid-cols-2` (S-05). Test count unchanged (2105). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
79 lines
2.4 KiB
TypeScript
79 lines
2.4 KiB
TypeScript
"use client";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
import { useTranslations } from "@/lib/i18n/context";
|
|
import type { CorrelationResult } from "@/lib/insights/correlations";
|
|
import { CorrelationCard } from "./correlation-card";
|
|
|
|
/**
|
|
* v1.4.20 phase B3 — Correlation row.
|
|
*
|
|
* Renders the pre-defined hypothesis cards in a 2-up grid on `>=md` and
|
|
* a single column on `<md`. A single correlation-disclaimer footer sits
|
|
* below the row — the disclaimer applies to every card so we don't
|
|
* repeat it per-card.
|
|
*
|
|
* v1.4.22 A4 — empty-state cards are dropped instead of rendered. Any
|
|
* hypothesis whose `status !== "ok"` is filtered out so the layout
|
|
* collapses cleanly: 2 ok cards → 50/50, 1 ok card → 100 %, 0 ok cards
|
|
* → the row hides itself entirely (no header, no disclaimer). Up to
|
|
* v1.4.21 the `<CorrelationCard>` painted an EmptyState for below-
|
|
* threshold results, which left half-rows of greyed-out placeholders
|
|
* on a sparse account.
|
|
*/
|
|
|
|
interface CorrelationRowProps {
|
|
results: {
|
|
bpCompliance: CorrelationResult;
|
|
moodPulse: CorrelationResult;
|
|
weightWeekday: CorrelationResult;
|
|
};
|
|
}
|
|
|
|
export function CorrelationRow({ results }: CorrelationRowProps) {
|
|
const { t } = useTranslations();
|
|
|
|
// Drop insufficient-data tiles up-front. The grid below picks 1-col vs
|
|
// 2-col automatically so 1 ok card spans 100 % width on its own row.
|
|
const okResults = [
|
|
results.bpCompliance,
|
|
results.moodPulse,
|
|
results.weightWeekday,
|
|
].filter((r) => r.status === "ok");
|
|
|
|
if (okResults.length === 0) return null;
|
|
|
|
return (
|
|
<section
|
|
data-slot="correlation-row"
|
|
aria-label={t("insights.correlationRow.title")}
|
|
className="space-y-3"
|
|
>
|
|
<div className="flex items-baseline justify-between">
|
|
<h2 className="text-lg font-semibold">
|
|
{t("insights.correlationRow.title")}
|
|
</h2>
|
|
<p className="text-muted-foreground text-xs">
|
|
{t("insights.correlationRow.subtitle")}
|
|
</p>
|
|
</div>
|
|
<div
|
|
className={cn(
|
|
"grid grid-cols-1 gap-4",
|
|
okResults.length > 1 && "md:grid-cols-2",
|
|
)}
|
|
>
|
|
{okResults.map((result) => (
|
|
<CorrelationCard key={result.kind} result={result} />
|
|
))}
|
|
</div>
|
|
<p
|
|
data-slot="correlation-row-disclaimer"
|
|
className="text-muted-foreground text-xs italic"
|
|
>
|
|
{t("insights.correlationRow.disclaimer")}
|
|
</p>
|
|
</section>
|
|
);
|
|
}
|