-- Migration 027: Focus Areas System (Goal System v2.0) -- Date: 2026-03-27 -- Purpose: Replace single primary goal with weighted multi-goal system -- ============================================================================ -- Focus Areas Table -- ============================================================================ CREATE TABLE IF NOT EXISTS focus_areas ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), profile_id UUID NOT NULL REFERENCES profiles(id) ON DELETE CASCADE, -- Six focus dimensions (percentages, sum = 100) weight_loss_pct INTEGER DEFAULT 0 CHECK (weight_loss_pct >= 0 AND weight_loss_pct <= 100), muscle_gain_pct INTEGER DEFAULT 0 CHECK (muscle_gain_pct >= 0 AND muscle_gain_pct <= 100), strength_pct INTEGER DEFAULT 0 CHECK (strength_pct >= 0 AND strength_pct <= 100), endurance_pct INTEGER DEFAULT 0 CHECK (endurance_pct >= 0 AND endurance_pct <= 100), flexibility_pct INTEGER DEFAULT 0 CHECK (flexibility_pct >= 0 AND flexibility_pct <= 100), health_pct INTEGER DEFAULT 0 CHECK (health_pct >= 0 AND health_pct <= 100), -- Status active BOOLEAN DEFAULT true, -- Audit created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW(), -- Constraints CONSTRAINT sum_equals_100 CHECK ( weight_loss_pct + muscle_gain_pct + strength_pct + endurance_pct + flexibility_pct + health_pct = 100 ) ); -- Only one active focus_areas per profile CREATE UNIQUE INDEX IF NOT EXISTS idx_focus_areas_profile_active ON focus_areas(profile_id) WHERE active = true; COMMENT ON TABLE focus_areas IS 'User-defined focus area weights (replaces simple goal_mode). Enables multi-goal prioritization with custom percentages.'; COMMENT ON COLUMN focus_areas.weight_loss_pct IS 'Focus on fat loss (0-100%)'; COMMENT ON COLUMN focus_areas.muscle_gain_pct IS 'Focus on muscle growth (0-100%)'; COMMENT ON COLUMN focus_areas.strength_pct IS 'Focus on strength gains (0-100%)'; COMMENT ON COLUMN focus_areas.endurance_pct IS 'Focus on aerobic capacity (0-100%)'; COMMENT ON COLUMN focus_areas.flexibility_pct IS 'Focus on mobility/flexibility (0-100%)'; COMMENT ON COLUMN focus_areas.health_pct IS 'Focus on general health (0-100%)'; -- ============================================================================ -- Migrate existing goal_mode to focus_areas -- ============================================================================ -- For each profile with a goal_mode, create initial focus_areas INSERT INTO focus_areas ( profile_id, weight_loss_pct, muscle_gain_pct, strength_pct, endurance_pct, flexibility_pct, health_pct ) SELECT id AS profile_id, CASE goal_mode WHEN 'weight_loss' THEN 60 WHEN 'recomposition' THEN 30 WHEN 'health' THEN 5 ELSE 0 END AS weight_loss_pct, CASE goal_mode WHEN 'strength' THEN 40 ELSE 0 END + CASE goal_mode WHEN 'recomposition' THEN 30 ELSE 0 END AS muscle_gain_pct, CASE goal_mode WHEN 'strength' THEN 50 WHEN 'recomposition' THEN 25 WHEN 'weight_loss' THEN 10 WHEN 'health' THEN 10 ELSE 0 END AS strength_pct, CASE goal_mode WHEN 'endurance' THEN 70 WHEN 'recomposition' THEN 10 WHEN 'weight_loss' THEN 20 WHEN 'health' THEN 20 ELSE 0 END AS endurance_pct, CASE goal_mode WHEN 'endurance' THEN 10 ELSE 0 END + CASE goal_mode WHEN 'health' THEN 15 ELSE 0 END + CASE goal_mode WHEN 'recomposition' THEN 5 ELSE 0 END + CASE goal_mode WHEN 'weight_loss' THEN 5 ELSE 0 END AS flexibility_pct, CASE goal_mode WHEN 'health' THEN 50 WHEN 'endurance' THEN 20 WHEN 'strength' THEN 10 WHEN 'weight_loss' THEN 5 ELSE 0 END AS health_pct FROM profiles WHERE goal_mode IS NOT NULL ON CONFLICT DO NOTHING; -- For profiles without goal_mode, use balanced health focus INSERT INTO focus_areas ( profile_id, weight_loss_pct, muscle_gain_pct, strength_pct, endurance_pct, flexibility_pct, health_pct ) SELECT id AS profile_id, 0, 0, 10, 20, 15, 55 FROM profiles WHERE goal_mode IS NULL AND id NOT IN (SELECT profile_id FROM focus_areas WHERE active = true) ON CONFLICT DO NOTHING;