mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 13:22:14 +00:00
feat(insights): regroup tab-strip pills by metric category
The wave-A HealthKit pills (HRV, resting HR, SpO2, body temperature, active energy) added in v1.4.32 stacked at the end of the strip in insertion order so a left-to-right scan jumped across metric domains multiple times. Reorder the pills to mirror the MeasurementCategory overlay at src/lib/measurements/categories.ts: vitals → body → activity → sleep → cardiovascular → mood → events. No pill added or removed. The single source of truth is SUB_PAGE_METRIC in src/lib/insights/sub-page-metric.ts; the strip iterates SUB_PAGE_SLUGS (derived from the same record) and inherits the new order automatically. Heavier regrouping (collapse five wave-A pills under one Apple-Health pill, fold BMI into Gewicht) is deferred to v1.4.34 — see .planning/round-v1433-audit-menu.md §7 for the design-review rationale. Per .planning/round-v1433-audit-runtime.md F9.
This commit is contained in:
1 parent
c98d07effd
commit
85d74dd913
3 files changed
+55
-28
No files matched your search
@@ -81,7 +81,7 @@ describe("<InsightStatusCard>", () => {
|
||||
text="ignored when hasProvider is false"
|
||||
/>,
|
||||
);
|
||||
expect(html).toContain("AI provider not configured.");
|
||||
expect(html).toContain("Assessment unavailable.");
|
||||
expect(html).not.toContain("ignored when hasProvider is false");
|
||||
});
|
||||
|
||||
|
||||
@@ -80,31 +80,20 @@ interface TabEntry {
|
||||
* stay in sync from a single source of truth — adding a sub-page is
|
||||
* one row.
|
||||
*/
|
||||
// v1.4.33 F9 — label + gating-metric for every routed sub-page. Pill
|
||||
// ORDER is owned by `SUB_PAGE_SLUGS` (which iterates the keys of
|
||||
// `SUB_PAGE_METRIC`) so adding a new metric is one row in
|
||||
// `sub-page-metric.ts` and the strip picks it up automatically.
|
||||
const SUB_PAGE_TABS: Record<
|
||||
SubPageSlug,
|
||||
{ labelKey: string; metric: InsightMetric }
|
||||
> = {
|
||||
// ── vitals ──
|
||||
blutdruck: {
|
||||
labelKey: "insights.navBloodPressure",
|
||||
metric: "BLOOD_PRESSURE_SYS",
|
||||
},
|
||||
gewicht: { labelKey: "insights.navWeight", metric: "WEIGHT" },
|
||||
puls: { labelKey: "insights.navPulse", metric: "PULSE" },
|
||||
stimmung: { labelKey: "insights.navMood", metric: "MOOD" },
|
||||
medikamente: { labelKey: "insights.navMedication", metric: "MEDICATION" },
|
||||
bmi: { labelKey: "insights.navBmi", metric: "BMI" },
|
||||
schlaf: { labelKey: "insights.navSleep", metric: "SLEEP_DURATION" },
|
||||
// v1.4.32 — workouts pill. Gate is event-driven; the
|
||||
// availability helper reads `inputs.hasWorkouts` rather than a
|
||||
// `summaries[…].count`.
|
||||
workouts: { labelKey: "insights.navWorkouts", metric: "WORKOUTS" },
|
||||
// v1.4.32 — five wave-A HealthKit pills. Each one reads its own
|
||||
// MeasurementType count from the analytics summaries.
|
||||
hrv: { labelKey: "insights.navHrv", metric: "HEART_RATE_VARIABILITY" },
|
||||
ruhepuls: {
|
||||
labelKey: "insights.navRestingHr",
|
||||
metric: "RESTING_HEART_RATE",
|
||||
},
|
||||
sauerstoff: {
|
||||
labelKey: "insights.navOxygenSaturation",
|
||||
metric: "OXYGEN_SATURATION",
|
||||
@@ -113,10 +102,30 @@ const SUB_PAGE_TABS: Record<
|
||||
labelKey: "insights.navBodyTemperature",
|
||||
metric: "BODY_TEMPERATURE",
|
||||
},
|
||||
// ── body composition ──
|
||||
gewicht: { labelKey: "insights.navWeight", metric: "WEIGHT" },
|
||||
bmi: { labelKey: "insights.navBmi", metric: "BMI" },
|
||||
// ── activity ──
|
||||
"aktive-energie": {
|
||||
labelKey: "insights.navActiveEnergy",
|
||||
metric: "ACTIVE_ENERGY_BURNED",
|
||||
},
|
||||
// v1.4.32 — workouts pill. Gate is event-driven; the
|
||||
// availability helper reads `inputs.hasWorkouts` rather than a
|
||||
// `summaries[…].count`.
|
||||
workouts: { labelKey: "insights.navWorkouts", metric: "WORKOUTS" },
|
||||
// ── sleep ──
|
||||
schlaf: { labelKey: "insights.navSleep", metric: "SLEEP_DURATION" },
|
||||
// ── cardiovascular ──
|
||||
ruhepuls: {
|
||||
labelKey: "insights.navRestingHr",
|
||||
metric: "RESTING_HEART_RATE",
|
||||
},
|
||||
hrv: { labelKey: "insights.navHrv", metric: "HEART_RATE_VARIABILITY" },
|
||||
// ── mood ──
|
||||
stimmung: { labelKey: "insights.navMood", metric: "MOOD" },
|
||||
// ── events ──
|
||||
medikamente: { labelKey: "insights.navMedication", metric: "MEDICATION" },
|
||||
};
|
||||
|
||||
function buildTabs(availability: InsightInputs | undefined): TabEntry[] {
|
||||
|
||||
@@ -24,27 +24,45 @@
|
||||
* enum, the slug array, and the per-slug metric list all derive from
|
||||
* the keys of this record — adding a sub-page is a one-place change.
|
||||
*/
|
||||
// v1.4.33 F9 — order follows the MeasurementCategory overlay
|
||||
// (`src/lib/measurements/categories.ts`):
|
||||
//
|
||||
// vitals → body → activity → sleep → cardiovascular → mood → events
|
||||
//
|
||||
// The wave-A HealthKit entries added in v1.4.32 (HRV, resting HR, SpO2,
|
||||
// body temperature, active energy) used to stack at the end of the
|
||||
// strip in insertion order; the regrouping below interleaves them into
|
||||
// their categorical neighbours so a user reading left-to-right scans
|
||||
// each metric domain as a block. Heavier regrouping (collapse five
|
||||
// wave-A pills under a single "Apple Health" pill, fold BMI into
|
||||
// Gewicht, fold Sauerstoff/Körpertemperatur into a single Vitals pill)
|
||||
// is deferred to v1.4.34 — that needs a screenshot review per
|
||||
// .planning/round-v1433-audit-menu.md §7.
|
||||
export const SUB_PAGE_METRIC = {
|
||||
// ── vitals ──
|
||||
blutdruck: ["BLOOD_PRESSURE_SYS", "BLOOD_PRESSURE_DIA", "PULSE"],
|
||||
gewicht: ["WEIGHT"],
|
||||
puls: ["PULSE"],
|
||||
stimmung: ["MOOD"],
|
||||
// medication adherence is event-driven; no measurement series.
|
||||
medikamente: [],
|
||||
sauerstoff: ["OXYGEN_SATURATION"],
|
||||
koerpertemperatur: ["BODY_TEMPERATURE"],
|
||||
// ── body composition ──
|
||||
gewicht: ["WEIGHT"],
|
||||
// BMI is derived from WEIGHT + profile height (no separate series).
|
||||
bmi: ["WEIGHT"],
|
||||
schlaf: ["SLEEP_DURATION"],
|
||||
// ── activity ──
|
||||
"aktive-energie": ["ACTIVE_ENERGY_BURNED"],
|
||||
// v1.4.32 — workouts surface; the page reads `Workout` rows directly
|
||||
// through `useWorkouts()` rather than the `summaries` map, so the
|
||||
// metric list stays empty.
|
||||
workouts: [],
|
||||
// v1.4.32 — five new HealthKit wave-A sub-pages. Each one reads its
|
||||
// own MeasurementType series via the standard analytics path.
|
||||
hrv: ["HEART_RATE_VARIABILITY"],
|
||||
// ── sleep ──
|
||||
schlaf: ["SLEEP_DURATION"],
|
||||
// ── cardiovascular ──
|
||||
ruhepuls: ["RESTING_HEART_RATE"],
|
||||
sauerstoff: ["OXYGEN_SATURATION"],
|
||||
koerpertemperatur: ["BODY_TEMPERATURE"],
|
||||
"aktive-energie": ["ACTIVE_ENERGY_BURNED"],
|
||||
hrv: ["HEART_RATE_VARIABILITY"],
|
||||
// ── mood ──
|
||||
stimmung: ["MOOD"],
|
||||
// ── events (medication adherence is event-driven; no measurement series) ──
|
||||
medikamente: [],
|
||||
} as const satisfies Record<string, readonly string[]>;
|
||||
|
||||
export type SubPageSlug = keyof typeof SUB_PAGE_METRIC;
|
||||
|
||||
Reference in new issue
Block a user