feat: add missing migration 008 (vitals, rest days, sleep_goal_minutes)
- Creates rest_days table for rest day tracking - Creates vitals_log table for resting HR + HRV - Creates weekly_goals table for training planning - Extends profiles with hf_max and sleep_goal_minutes columns - Extends activity_log with avg_hr and max_hr columns - Fixes sleep_goal_minutes missing column error in stats endpoint - Includes stats error handling in SleepWidget Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9e4d6fa715
commit
b65efd3b71
59
backend/migrations/008_vitals_rest_days.sql
Normal file
59
backend/migrations/008_vitals_rest_days.sql
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
-- Migration 008: Vitals, Rest Days, Weekly Goals
|
||||
-- v9d Phase 2: Sleep & Vitals Module
|
||||
-- Date: 2026-03-22
|
||||
|
||||
-- Rest Days
|
||||
CREATE TABLE IF NOT EXISTS rest_days (
|
||||
id SERIAL PRIMARY KEY,
|
||||
profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
|
||||
date DATE NOT NULL,
|
||||
type VARCHAR(20) NOT NULL CHECK (type IN ('full_rest', 'active_recovery')),
|
||||
note TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT unique_rest_day_per_profile UNIQUE(profile_id, date)
|
||||
);
|
||||
CREATE INDEX idx_rest_days_profile_date ON rest_days(profile_id, date DESC);
|
||||
|
||||
-- Vitals (Resting HR + HRV)
|
||||
CREATE TABLE IF NOT EXISTS vitals_log (
|
||||
id SERIAL PRIMARY KEY,
|
||||
profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
|
||||
date DATE NOT NULL,
|
||||
resting_hr INTEGER CHECK (resting_hr > 0 AND resting_hr < 200),
|
||||
hrv INTEGER CHECK (hrv > 0),
|
||||
note TEXT,
|
||||
source VARCHAR(20) DEFAULT 'manual' CHECK (source IN ('manual', 'apple_health', 'garmin')),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT unique_vitals_per_day UNIQUE(profile_id, date)
|
||||
);
|
||||
CREATE INDEX idx_vitals_profile_date ON vitals_log(profile_id, date DESC);
|
||||
|
||||
-- Extend activity_log for heart rate data
|
||||
ALTER TABLE activity_log
|
||||
ADD COLUMN IF NOT EXISTS avg_hr INTEGER CHECK (avg_hr > 0 AND avg_hr < 250),
|
||||
ADD COLUMN IF NOT EXISTS max_hr INTEGER CHECK (max_hr > 0 AND max_hr < 250);
|
||||
|
||||
-- Extend profiles for HF max and sleep goal
|
||||
ALTER TABLE profiles
|
||||
ADD COLUMN IF NOT EXISTS hf_max INTEGER CHECK (hf_max > 0 AND hf_max < 250),
|
||||
ADD COLUMN IF NOT EXISTS sleep_goal_minutes INTEGER DEFAULT 450 CHECK (sleep_goal_minutes > 0);
|
||||
|
||||
-- Weekly Goals (Soll/Ist Wochenplanung)
|
||||
CREATE TABLE IF NOT EXISTS weekly_goals (
|
||||
id SERIAL PRIMARY KEY,
|
||||
profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE,
|
||||
week_start DATE NOT NULL,
|
||||
goals JSONB NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT unique_weekly_goal_per_profile UNIQUE(profile_id, week_start)
|
||||
);
|
||||
CREATE INDEX idx_weekly_goals_profile_week ON weekly_goals(profile_id, week_start DESC);
|
||||
|
||||
-- Comments for documentation
|
||||
COMMENT ON TABLE rest_days IS 'v9d Phase 2: Rest days tracking (full rest or active recovery)';
|
||||
COMMENT ON TABLE vitals_log IS 'v9d Phase 2: Daily vitals (resting HR, HRV)';
|
||||
COMMENT ON TABLE weekly_goals IS 'v9d Phase 2: Weekly training goals (Soll/Ist planning)';
|
||||
COMMENT ON COLUMN profiles.hf_max IS 'Maximum heart rate for HR zone calculation';
|
||||
COMMENT ON COLUMN profiles.sleep_goal_minutes IS 'Sleep goal in minutes (default: 450 = 7h 30min)';
|
||||
|
|
@ -24,7 +24,7 @@ export default function SleepWidget() {
|
|||
const load = () => {
|
||||
Promise.all([
|
||||
api.listSleep(1), // Get last entry
|
||||
api.getSleepStats(7)
|
||||
api.getSleepStats(7).catch(() => null) // Stats optional
|
||||
]).then(([sleepData, statsData]) => {
|
||||
setLastNight(sleepData[0] || null)
|
||||
setStats(statsData)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user