diff --git a/frontend/src/pages/HealthPage.jsx b/frontend/src/pages/HealthPage.jsx index 0e452b4..ed88c35 100644 --- a/frontend/src/pages/HealthPage.jsx +++ b/frontend/src/pages/HealthPage.jsx @@ -21,38 +21,40 @@ const RANGES = [ // ── VO2 Max gauge ──────────────────────────────────────────────────────────── -// ACSM sex-specific VO2 max thresholds -// [maxAge, [veryPoor_max, poor_max, fair_max, good_max]] (above good_max → Excellent) +// Garmin/Cooper Institute VO2 max thresholds +// [maxAge, [fair_min, good_min, excellent_min, superior_min]] +// value < fair_min → Poor; >= superior_min → Superior const VO2_MALE = [ - [29, [32, 36, 41, 45]], - [39, [30, 34, 38, 43]], - [49, [29, 33, 37, 42]], - [59, [25, 30, 34, 38]], - [69, [20, 24, 28, 32]], - [Infinity, [17, 21, 24, 28]], + [29, [41.7, 45.4, 51.1, 55.4]], + [39, [40.5, 44.0, 48.3, 54.0]], + [49, [38.5, 42.4, 46.4, 52.5]], + [59, [35.6, 39.2, 43.4, 48.9]], + [69, [32.3, 35.5, 39.5, 45.7]], + [Infinity, [29.4, 32.3, 36.7, 42.1]], ] const VO2_FEMALE = [ - [29, [27, 33, 36, 41]], - [39, [26, 30, 35, 39]], - [49, [24, 28, 32, 36]], - [59, [21, 24, 28, 32]], - [69, [18, 21, 24, 28]], - [Infinity, [15, 18, 22, 25]], + [29, [36.1, 39.5, 43.9, 49.6]], + [39, [34.4, 37.8, 42.4, 47.4]], + [49, [33.0, 36.3, 39.7, 45.3]], + [59, [30.1, 33.0, 36.7, 41.1]], + [69, [27.5, 30.0, 33.0, 37.8]], + [Infinity, [25.9, 28.1, 30.9, 36.7]], ] const VO2_CATEGORIES = [ - { label: 'Very Poor', color: '#ef4444' }, - { label: 'Poor', color: '#f97316' }, - { label: 'Fair', color: '#22c55e' }, - { label: 'Good', color: '#3b82f6' }, - { label: 'Excellent', color: '#a855f7' }, + { label: 'Poor', color: '#ef4444' }, + { label: 'Fair', color: '#f97316' }, + { label: 'Good', color: '#22c55e' }, + { label: 'Excellent', color: '#3b82f6' }, + { label: 'Superior', color: '#a855f7' }, ] function getVo2Category(value, age, sex) { const table = sex === 'female' ? VO2_FEMALE : VO2_MALE const row = table.find(([maxAge]) => age <= maxAge) || table[table.length - 1] const thresholds = row[1] - const idx = thresholds.findIndex(t => value <= t) - return idx === -1 ? VO2_CATEGORIES[4] : VO2_CATEGORIES[idx] + // thresholds are lower-bounds: count how many the value meets or exceeds + const idx = thresholds.reduce((n, t) => value >= t ? n + 1 : n, 0) + return VO2_CATEGORIES[idx] } function Vo2MaxGauge({ value, birthYear, biologicalSex }) {