diff --git a/backend/routers/vitals.py b/backend/routers/vitals.py index 9180c5f..36ecb09 100644 --- a/backend/routers/vitals.py +++ b/backend/routers/vitals.py @@ -140,63 +140,66 @@ def create_vitals( x_profile_id: Optional[str] = Header(default=None), session: dict = Depends(require_auth) ): - """Create or update vitals entry (upsert).""" + """ + Create or update vitals entry (upsert). + + Post-Migration-015: Routes to vitals_baseline (for RHR, HRV, etc.) + Note: BP measurements should use /api/blood-pressure endpoint instead. + """ pid = get_pid(x_profile_id, session) - # Validation: at least one vital must be provided - has_data = any([ - entry.resting_hr, entry.hrv, entry.blood_pressure_systolic, - entry.blood_pressure_diastolic, entry.vo2_max, entry.spo2, - entry.respiratory_rate + # Validation: at least one baseline vital must be provided + has_baseline = any([ + entry.resting_hr, entry.hrv, entry.vo2_max, + entry.spo2, entry.respiratory_rate ]) - if not has_data: - raise HTTPException(400, "Mindestens ein Vitalwert muss angegeben werden") + + if not has_baseline: + raise HTTPException(400, "Mindestens ein Vitalwert muss angegeben werden (RHR, HRV, VO2Max, SpO2, oder Atemfrequenz)") with get_db() as conn: cur = get_cursor(conn) - # Upsert: insert or update if date already exists + # Upsert into vitals_baseline (Migration 015) cur.execute( """ - INSERT INTO vitals_log ( + INSERT INTO vitals_baseline ( profile_id, date, resting_hr, hrv, - blood_pressure_systolic, blood_pressure_diastolic, pulse, vo2_max, spo2, respiratory_rate, - irregular_heartbeat, possible_afib, note, source ) - VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'manual') + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, 'manual') ON CONFLICT (profile_id, date) DO UPDATE SET - resting_hr = COALESCE(EXCLUDED.resting_hr, vitals_log.resting_hr), - hrv = COALESCE(EXCLUDED.hrv, vitals_log.hrv), - blood_pressure_systolic = COALESCE(EXCLUDED.blood_pressure_systolic, vitals_log.blood_pressure_systolic), - blood_pressure_diastolic = COALESCE(EXCLUDED.blood_pressure_diastolic, vitals_log.blood_pressure_diastolic), - pulse = COALESCE(EXCLUDED.pulse, vitals_log.pulse), - vo2_max = COALESCE(EXCLUDED.vo2_max, vitals_log.vo2_max), - spo2 = COALESCE(EXCLUDED.spo2, vitals_log.spo2), - respiratory_rate = COALESCE(EXCLUDED.respiratory_rate, vitals_log.respiratory_rate), - irregular_heartbeat = COALESCE(EXCLUDED.irregular_heartbeat, vitals_log.irregular_heartbeat), - possible_afib = COALESCE(EXCLUDED.possible_afib, vitals_log.possible_afib), - note = COALESCE(EXCLUDED.note, vitals_log.note), + resting_hr = COALESCE(EXCLUDED.resting_hr, vitals_baseline.resting_hr), + hrv = COALESCE(EXCLUDED.hrv, vitals_baseline.hrv), + vo2_max = COALESCE(EXCLUDED.vo2_max, vitals_baseline.vo2_max), + spo2 = COALESCE(EXCLUDED.spo2, vitals_baseline.spo2), + respiratory_rate = COALESCE(EXCLUDED.respiratory_rate, vitals_baseline.respiratory_rate), + note = COALESCE(EXCLUDED.note, vitals_baseline.note), updated_at = CURRENT_TIMESTAMP RETURNING id, profile_id, date, resting_hr, hrv, - blood_pressure_systolic, blood_pressure_diastolic, pulse, vo2_max, spo2, respiratory_rate, - irregular_heartbeat, possible_afib, note, source, created_at, updated_at """, (pid, entry.date, entry.resting_hr, entry.hrv, - entry.blood_pressure_systolic, entry.blood_pressure_diastolic, entry.pulse, entry.vo2_max, entry.spo2, entry.respiratory_rate, - entry.irregular_heartbeat, entry.possible_afib, entry.note) ) row = cur.fetchone() conn.commit() - logger.info(f"[VITALS] Upserted vitals for {pid} on {entry.date}") - return r2d(row) + logger.info(f"[VITALS] Upserted baseline vitals for {pid} on {entry.date}") + + # Return in legacy format for backward compatibility + result = r2d(row) + result['blood_pressure_systolic'] = None + result['blood_pressure_diastolic'] = None + result['pulse'] = None + result['irregular_heartbeat'] = None + result['possible_afib'] = None + + return result @router.put("/{vitals_id}") diff --git a/frontend/src/pages/GoalsPage.jsx b/frontend/src/pages/GoalsPage.jsx index b085279..5492acb 100644 --- a/frontend/src/pages/GoalsPage.jsx +++ b/frontend/src/pages/GoalsPage.jsx @@ -228,7 +228,8 @@ export default function GoalsPage() { unit: formData.unit, target_date: formData.target_date || null, name: formData.name || null, - description: formData.description || null + description: formData.description || null, + focus_contributions: formData.focus_contributions || [] // v2.0: Focus area assignments } console.log('[DEBUG] Saving goal:', { editingGoal, data }) @@ -888,7 +889,15 @@ export default function GoalsPage() { ) : (
- {Object.entries(focusAreasGrouped).map(([category, areas]) => ( + {Object.entries(focusAreasGrouped).map(([category, areas]) => { + // Filter to only show focus areas the user has weighted + const userWeightedAreaIds = new Set(userFocusWeights.map(w => w.id)) + const filteredAreas = areas.filter(area => userWeightedAreaIds.has(area.id)) + + // Skip category if no weighted areas + if (filteredAreas.length === 0) return null + + return (
- {areas.map(area => { + {filteredAreas.map(area => { const isSelected = formData.focus_contributions?.some( fc => fc.focus_area_id === area.id ) @@ -960,7 +969,8 @@ export default function GoalsPage() { })}
- ))} + ) + })}
)}