mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
feat(insights): surface ring/strap HRV and rank wearable activity sources
This commit is contained in:
1 parent
46f9dfa47f
commit
bd9f03805c
7 files changed
+166
-13
No files matched your search
@@ -54,6 +54,24 @@ import { SubPageShell } from "@/components/insights/sub-page-shell";
|
||||
export interface HealthKitMetricPageProps {
|
||||
/** The MeasurementType that backs the chart. */
|
||||
measurementType: string;
|
||||
/**
|
||||
* v1.17.0 — optional secondary MeasurementType the page falls back to
|
||||
* when the primary type has no rows but the fallback does. Used by HRV:
|
||||
* the primary `HEART_RATE_VARIABILITY` (SDNN, Apple / Fitbit) is empty
|
||||
* for a ring / strap user whose nightly HRV is stored as `HRV_RMSSD`
|
||||
* (Oura / Polar / WHOOP). When the swap is active the chart, stat strip,
|
||||
* "all values" list, and diversity nudge key off the fallback type and
|
||||
* `fallbackMeasureLabel` names the measure so the two are never silently
|
||||
* merged. Omit it and every other page renders byte-identically.
|
||||
*/
|
||||
fallbackMeasurementType?: string;
|
||||
/**
|
||||
* v1.17.0 — short label naming the fallback measure (e.g. "RMSSD") shown
|
||||
* beneath the chart title when the fallback series is active, so the user
|
||||
* sees which measure their reading is. Required in practice whenever
|
||||
* `fallbackMeasurementType` is set.
|
||||
*/
|
||||
fallbackMeasureLabel?: string;
|
||||
/** The InsightMetric key used by `useInsightsAnalytics()`. */
|
||||
insightMetric: InsightMetric;
|
||||
/** The chart-overlay slot id. */
|
||||
@@ -167,6 +185,8 @@ export interface HealthKitMetricPageProps {
|
||||
|
||||
export function HealthKitMetricPage({
|
||||
measurementType,
|
||||
fallbackMeasurementType,
|
||||
fallbackMeasureLabel,
|
||||
insightMetric,
|
||||
chartKey,
|
||||
i18nPrefix,
|
||||
@@ -204,7 +224,22 @@ export function HealthKitMetricPage({
|
||||
// stat strip reads it back for this page's single series.
|
||||
const { statsByType, onVisibleStats } = useChartDomainStats();
|
||||
|
||||
const rawSummary = analytics?.summaries?.[measurementType] ?? null;
|
||||
// v1.17.0 — fallback-type swap. When the primary type has no rows but the
|
||||
// declared fallback does (HRV: SDNN empty, RMSSD present), key the chart,
|
||||
// stat strip, and "all values" list off the fallback so a ring / strap
|
||||
// user's stored HRV renders instead of an empty state. The swap only
|
||||
// triggers once analytics has loaded and the primary is genuinely empty.
|
||||
const primaryCount = analytics?.summaries?.[measurementType]?.count ?? 0;
|
||||
const fallbackCount = fallbackMeasurementType
|
||||
? (analytics?.summaries?.[fallbackMeasurementType]?.count ?? 0)
|
||||
: 0;
|
||||
const usingFallback =
|
||||
primaryCount === 0 && fallbackCount > 0 && !!fallbackMeasurementType;
|
||||
const effectiveType = usingFallback
|
||||
? (fallbackMeasurementType as string)
|
||||
: measurementType;
|
||||
|
||||
const rawSummary = analytics?.summaries?.[effectiveType] ?? null;
|
||||
// The stat strip renders display-unit values. The summary holds stored
|
||||
// values, so when the page renders a scaled unit (e.g. WALKING_SPEED
|
||||
// stores m/s but displays km/h via `valueScale`), fold the same scale
|
||||
@@ -316,24 +351,28 @@ export function HealthKitMetricPage({
|
||||
fractionDigits={statFractionDigits}
|
||||
seriesLabel={title}
|
||||
icon={statIcon}
|
||||
windowStats={statsByType?.[measurementType] ?? null}
|
||||
windowStats={statsByType?.[effectiveType] ?? null}
|
||||
medianLabel={statMedianLabel}
|
||||
/>
|
||||
}
|
||||
diversityNudge={
|
||||
<MeasurementDiversityNudge
|
||||
measurementType={measurementType}
|
||||
measurementType={effectiveType}
|
||||
metricLabel={title}
|
||||
timeZone={user?.timezone ?? undefined}
|
||||
/>
|
||||
}
|
||||
coachLaunch
|
||||
showAllValuesType={measurementType}
|
||||
showAllValuesType={effectiveType}
|
||||
>
|
||||
<HealthChartDynamic
|
||||
chartKey={chartKey}
|
||||
types={[measurementType]}
|
||||
title={t(`${i18nPrefix}.chartTitle`)}
|
||||
types={[effectiveType]}
|
||||
title={
|
||||
usingFallback && fallbackMeasureLabel
|
||||
? `${t(`${i18nPrefix}.chartTitle`)} · ${fallbackMeasureLabel}`
|
||||
: t(`${i18nPrefix}.chartTitle`)
|
||||
}
|
||||
titleIcon={statIcon}
|
||||
colors={[color]}
|
||||
unit={unit}
|
||||
|
||||
Reference in new issue
Block a user