feat(measurements): wire walking-steadiness + audio-exposure-event through every registry

v1.4.30 commit 7 follow-up. The new MeasurementType values land in
every derived registry the canonical enum drives:

  - measurement-list-meta.ts label keys + icons + colors so the
    measurements list view renders both types (Gauge for steadiness,
    Volume2 for the loud-listening event)
  - 6 locale files (de/en/es/fr/it/pl) carry typeWalkingSteadiness +
    typeAudioExposureEvent keys; English-fallback copy for the four
    non-EN/DE locales matches the existing v1.4.25 W8d pattern
  - chart-tokens.ts ALLOWED_CHART_TOKENS list so the LLM can
    reference `metric:WALKING_STEADINESS` + `metric:AUDIO_EXPOSURE_EVENT`
    in prose; dedicated chart components ship alongside the iOS sync
  - the enum-coverage drift-guard test's EXPECTED_TYPES + PDF
    exclusion set so the canonical enum-extension lint stays green

Full unit suite passes (4035 specs).
This commit is contained in:
Marc-André Bombeck committed 2026-05-16 12:23:30 +02:00
1 parent a3b00f49ef
commit 0522652ae2
9 files changed
+39 -1

No files matched your search

+2
View File
@@ -299,6 +299,8 @@
"typeAudioExposureEnv": "Lärmbelastung (Umgebung)",
"typeAudioExposureHeadphone": "Lärmbelastung (Kopfhörer)",
"typeTimeInDaylight": "Zeit im Tageslicht",
"typeWalkingSteadiness": "Gehstabilität",
"typeAudioExposureEvent": "Lautes-Hören-Ereignis",
"glucoseContext": "Kontext",
"glucoseContextFasting": "Nüchtern (≥8 h ohne Nahrung)",
"glucoseContextPostprandial": "Postprandial (2 h nach dem Essen)",
+2
View File
@@ -299,6 +299,8 @@
"typeAudioExposureEnv": "Audio Exposure (Environment)",
"typeAudioExposureHeadphone": "Audio Exposure (Headphones)",
"typeTimeInDaylight": "Time in Daylight",
"typeWalkingSteadiness": "Walking Steadiness",
"typeAudioExposureEvent": "Loud-Listening Event",
"glucoseContext": "Context",
"glucoseContextFasting": "Fasting (≥8h without food)",
"glucoseContextPostprandial": "Post-meal (2h after eating)",
+2
View File
@@ -299,6 +299,8 @@
"typeAudioExposureEnv": "Audio Exposure (Environment)",
"typeAudioExposureHeadphone": "Audio Exposure (Headphones)",
"typeTimeInDaylight": "Time in Daylight",
"typeWalkingSteadiness": "Walking Steadiness",
"typeAudioExposureEvent": "Loud-Listening Event",
"glucoseContext": "Context",
"glucoseContextFasting": "Fasting (≥8h without food)",
"glucoseContextPostprandial": "Post-meal (2h after eating)",
+2
View File
@@ -299,6 +299,8 @@
"typeAudioExposureEnv": "Audio Exposure (Environment)",
"typeAudioExposureHeadphone": "Audio Exposure (Headphones)",
"typeTimeInDaylight": "Time in Daylight",
"typeWalkingSteadiness": "Walking Steadiness",
"typeAudioExposureEvent": "Loud-Listening Event",
"glucoseContext": "Context",
"glucoseContextFasting": "Fasting (≥8h without food)",
"glucoseContextPostprandial": "Post-meal (2h after eating)",
+2
View File
@@ -299,6 +299,8 @@
"typeAudioExposureEnv": "Audio Exposure (Environment)",
"typeAudioExposureHeadphone": "Audio Exposure (Headphones)",
"typeTimeInDaylight": "Time in Daylight",
"typeWalkingSteadiness": "Walking Steadiness",
"typeAudioExposureEvent": "Loud-Listening Event",
"glucoseContext": "Context",
"glucoseContextFasting": "Fasting (≥8h without food)",
"glucoseContextPostprandial": "Post-meal (2h after eating)",
+2
View File
@@ -299,6 +299,8 @@
"typeAudioExposureEnv": "Audio Exposure (Environment)",
"typeAudioExposureHeadphone": "Audio Exposure (Headphones)",
"typeTimeInDaylight": "Time in Daylight",
"typeWalkingSteadiness": "Walking Steadiness",
"typeAudioExposureEvent": "Loud-Listening Event",
"glucoseContext": "Context",
"glucoseContextFasting": "Fasting (≥8h without food)",
"glucoseContextPostprandial": "Post-meal (2h after eating)",
@@ -68,6 +68,9 @@ export const MEASUREMENT_TYPE_LABEL_KEYS: Record<string, string> = {
AUDIO_EXPOSURE_ENV: "measurements.typeAudioExposureEnv",
AUDIO_EXPOSURE_HEADPHONE: "measurements.typeAudioExposureHeadphone",
TIME_IN_DAYLIGHT: "measurements.typeTimeInDaylight",
// ── v1.4.30 R-F T1.4 + T1.5 ──
WALKING_STEADINESS: "measurements.typeWalkingSteadiness",
AUDIO_EXPOSURE_EVENT: "measurements.typeAudioExposureEvent",
};
export const MEASUREMENT_TYPE_ICONS: Record<string, LucideIcon> = {
@@ -110,6 +113,12 @@ export const MEASUREMENT_TYPE_ICONS: Record<string, LucideIcon> = {
AUDIO_EXPOSURE_ENV: Volume2,
AUDIO_EXPOSURE_HEADPHONE: Headphones,
TIME_IN_DAYLIGHT: Sun,
// ── v1.4.30 R-F T1.4 + T1.5 ──
// Activity/Gauge carries the mobility-steadiness signal (same
// family as VO2_MAX). Volume2 is reused for the loud-listening
// event flag — the event is a louder-cousin of the env quantity.
WALKING_STEADINESS: Gauge,
AUDIO_EXPOSURE_EVENT: Volume2,
};
export const MEASUREMENT_TYPE_COLORS: Record<string, string> = {
@@ -149,4 +158,7 @@ export const MEASUREMENT_TYPE_COLORS: Record<string, string> = {
AUDIO_EXPOSURE_ENV: "bg-chart-5/20 text-chart-5",
AUDIO_EXPOSURE_HEADPHONE: "bg-chart-5/20 text-chart-5",
TIME_IN_DAYLIGHT: "bg-chart-2/20 text-chart-2",
// ── v1.4.30 R-F T1.4 + T1.5 ──
WALKING_STEADINESS: "bg-chart-2/20 text-chart-2",
AUDIO_EXPOSURE_EVENT: "bg-chart-5/20 text-chart-5",
};
@@ -46,10 +46,13 @@ const EXPECTED_TYPES = [
"AUDIO_EXPOSURE_ENV",
"AUDIO_EXPOSURE_HEADPHONE",
"TIME_IN_DAYLIGHT",
// ── v1.4.30 R-F T1.4 + T1.5 ──
"WALKING_STEADINESS",
"AUDIO_EXPOSURE_EVENT",
] as const;
describe("measurementTypeEnum coverage", () => {
it("exposes the 28 canonical measurement types", () => {
it("exposes the 30 canonical measurement types", () => {
expect([...measurementTypeEnum.options].sort()).toEqual(
[...EXPECTED_TYPES].sort(),
);
@@ -96,6 +99,12 @@ describe("measurementTypeEnum coverage", () => {
"AUDIO_EXPOSURE_ENV",
"AUDIO_EXPOSURE_HEADPHONE",
"TIME_IN_DAYLIGHT",
// v1.4.30 R-F T1.4 + T1.5 additions held under the same v1.5 gate.
// Walking-steadiness pairs with a mobility chip; audio-exposure
// events surface on the Insights audio sub-page. Neither belongs
// in the clinical PDF until the iOS-app sync lands.
"WALKING_STEADINESS",
"AUDIO_EXPOSURE_EVENT",
]);
it("doctor-report PDF vital types cover the canonical enum minus documented exclusions", () => {
+5
View File
@@ -60,6 +60,11 @@ export const ALLOWED_CHART_TOKENS = [
"metric:AUDIO_EXPOSURE_ENV",
"metric:AUDIO_EXPOSURE_HEADPHONE",
"metric:TIME_IN_DAYLIGHT",
// v1.4.30 — R-F T1.4 + T1.5 Tier-1 additions. Same posture: the
// LLM can reference the tokens in prose; the chart components land
// alongside the iOS-app sync.
"metric:WALKING_STEADINESS",
"metric:AUDIO_EXPOSURE_EVENT",
] as const;
export type ChartToken = (typeof ALLOWED_CHART_TOKENS)[number];