**Bug 1: Focus contributions not saved**
- GoalsPage: Added focus_contributions to data object (line 232)
- Was missing from API payload, causing loss of focus area assignments
**Bug 2: Filter focus areas in goal form**
- Only show focus areas user has weighted (weight > 0)
- Cleaner UX, avoids confusion with non-prioritized areas
- Filters focusAreasGrouped by userFocusWeights
**Bug 3: Vitals RHR entry - Internal Server Error**
- Fixed: Endpoint tried to INSERT into vitals_log (renamed in Migration 015)
- Now uses vitals_baseline table (correct post-migration table)
- Removed BP fields from baseline endpoint (use /blood-pressure instead)
- Backward compatible return format
All fixes tested and ready for production.
**Migration 032:**
- user_focus_area_weights table (profile_id, focus_area_id, weight)
- Migrates legacy 6 preferences to dynamic weights
**Backend (focus_areas.py):**
- GET /user-preferences: Returns dynamic focus weights with percentages
- PUT /user-preferences: Saves user weights (dict: focus_area_id → weight)
- Auto-calculates percentages from relative weights
- Graceful fallback if Migration 032 not applied
**Frontend (GoalsPage.jsx):**
- REMOVED: Goal Mode cards (obsolete)
- REMOVED: 6 hardcoded legacy focus sliders
- NEW: Dynamic focus area cards (weight > 0 only)
- NEW: Edit mode with sliders for all 26 areas (grouped by category)
- Clean responsive design
**How it works:**
1. Admin defines focus areas in /admin/focus-areas (26 default)
2. User sets weights for areas they care about (0-100 relative)
3. System calculates percentages automatically
4. Cards show only weighted areas
5. Goals assign to 1-n focus areas (existing functionality)
- Restored GOAL_MODES constant and selection cards at top
- Fixed focusAreas/focusPreferences variable confusion
- Legacy 6 focus preferences show correctly in Fokus-Bereiche card
- Dynamic 26 focus areas should display in goal form
- Goal Mode cards now visible and functional again
- get_focus_areas now tries user_focus_preferences first (Migration 031)
- Falls back to old focus_areas table if Migration 031 not applied
- get_goals_grouped wraps focus_contributions loading in try/catch
- Graceful degradation until migrations run
- Wrap focus_contributions loading in try/catch
- If tables don't exist (migration not run), continue without them
- Backward compatible with pre-migration state
- Logs warning but doesn't crash
- Changed prefix from '/focus-areas' to '/api/focus-areas'
- Consistent with all other routers (goals, prompts, etc.)
- Fixes 404 Not Found on /admin/focus-areas page
- Line 60: focusPreferences (user's legacy preferences)
- Line 74: focusAreas (focus area definitions)
- Updated all references to avoid name collision
- Fixes build error in vite
**Goal Form Extended:**
- Load focus area definitions on page load
- Multi-Select UI grouped by category (7 categories)
- Chip-style selection (click to toggle)
- Weight sliders per selected area (0-100%)
- Selected areas highlighted in accent color
- Focus contributions saved/loaded on create/edit
**Goal Cards:**
- Focus Area badges below status
- Shows icon + name + weight percentage
- Hover shows full details
- Color-coded (accent-light background)
**Integration Complete:**
- State: focusAreas, focusAreasGrouped
- Handlers: handleCreateGoal, handleEditGoal
- Data flow: Backend → Frontend → Display
**Result:**
- User can assign goals to multiple focus areas
- Visual indication of what each goal contributes to
- Foundation for Phase 0b (goal-aware AI scoring)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- AdminFocusAreasPage: Full CRUD for focus area definitions
- Route: /admin/focus-areas
- AdminPanel: Link zu Focus Areas (neben Goal Types)
- api.js: 7 neue Focus Area Endpoints
Features:
- Category-grouped display (7 categories)
- Inline editing
- Active/Inactive toggle
- Create form with validation
- Show/Hide inactive areas
Next: Goal Form Multi-Select
**Backend Safeguards:**
- get_goals_grouped: Added source_table, source_column, direction to SELECT
- create_goal_progress: Check source_table before allowing manual entry
- Returns HTTP 400 if user tries to log progress for automatic goals (weight, activity, etc.)
**Prevents:**
- Data confusion: Manual entries in goal_progress_log for weight/activity/etc.
- Dual tracking: Same data in multiple tables
- User error: Wrong data entry location
**Result:**
- Frontend filter (!goal.source_table) now works correctly
- CustomGoalsPage shows ONLY custom goals (flexibility, strength, etc.)
- Clear error message if manual entry attempted via API
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implemented progress tracking system for all goals.
**Backend:**
- Migration 030: goal_progress_log table with unique constraint per day
- Trigger: Auto-update goal.current_value from latest progress
- Endpoints: GET/POST/DELETE /api/goals/{id}/progress
- Pydantic Models: GoalProgressCreate, GoalProgressUpdate
**Features:**
- Manual progress tracking for custom goals (flexibility, strength, etc.)
- Full history with date, value, note
- current_value always reflects latest progress entry
- One entry per day per goal (unique constraint)
- Cascade delete when goal is deleted
**API:**
- GET /api/goals/{goal_id}/progress - List all entries
- POST /api/goals/{goal_id}/progress - Log new progress
- DELETE /api/goals/{goal_id}/progress/{progress_id} - Delete entry
**Next:** Frontend UI (progress button, modal, history list)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These goal types existed but were inactive or misconfigured.
Uses UPSERT (INSERT ... ON CONFLICT DO UPDATE):
- If exists → activate + fix labels/icons/category
- If not exists → create properly
Idempotent: Safe to run multiple times, works on dev + prod.
Both types have no automatic data source (source_table = NULL),
so current_value must be updated manually.
Fixes: flexibility and strength goals not visible in admin
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enhanced fallback chain for goal display:
1. goal.name (custom name if set)
2. goal.label_de (from backend JOIN)
3. typeInfo.label_de (from goalTypesMap)
4. goal.goal_type (raw key as last resort)
Also use goal.icon from backend if available.
Fixes: Empty goal names showing blank in list
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
goals table doesn't have is_active column.
Removed AND g.is_active = true from WHERE clause.
Fixes: psycopg2.errors.UndefinedColumn: column g.is_active does not exist
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed: column 'date' does not exist in blood_pressure_log
blood_pressure_log uses 'measured_at' instead of 'date'.
Added DATE_COLUMN_MAP for table-specific date columns:
- blood_pressure_log → measured_at
- fitness_tests → test_date
- all others → date
Replaced all hardcoded 'date' with dynamic date_col variable.
Fixes error: [ERROR] Failed to fetch value from blood_pressure_log.systolic
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed SQL error: column g.linear_projection does not exist
Replaced with: g.on_track, g.projection_date (actual columns)
This was causing Internal Server Error on /api/goals/grouped
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migration 028 failed because goals table doesn't have is_active column yet.
Removed WHERE clause from index definition.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed multiple issues with relative weight sliders:
1. Sanitize focusData on load (ensure all 6 fields are numeric)
2. Sync focusTemp when clicking "Anpassen" button
3. Robust sum calculation filtering only *_pct fields
4. Convert NaN/undefined to 0 in all calculations
5. Safe Number() coercion before normalization
Fixes errors:
- "Gewichtung gesamt: NaN"
- "Input should be a valid integer, input: null"
- Prozent always showing 0%
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Improved UX for focus area configuration:
- Sliders now use relative weights (0-10) instead of percentages
- System automatically normalizes to percentages (sum=100%)
- Live preview shows "weight → percent%" (e.g., "5 → 50%")
- No more manual balancing required from user
User sets: Kraft=5, Ausdauer=3, Flexibilität=2
System calculates: 50%, 30%, 20%
Addresses user feedback: "Summe muss 100% sein" not user-friendly
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed health mode calculation to include all 6 dimensions.
Simplified CASE statements (single CASE instead of multiple additions).
Before: health mode only set flexibility (15%) + health (55%) = 70% ❌
After: health mode sets all dimensions = 100% ✅
- weight_loss: 5%
- muscle_gain: 0%
- strength: 10%
- endurance: 20%
- flexibility: 15%
- health: 50%
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed health mode calculation in focus_areas migration.
Changed health_pct from 50 to 55 to ensure sum equals 100%.
Before: 0+0+10+20+15+50 = 95% (constraint violation)
After: 0+0+10+20+15+55 = 100% (valid)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces single goal mode cards with weighted multi-focus system
UI Features:
- 6 sliders for focus dimensions (5% increments)
- Live sum calculation with visual feedback
- Validation: Sum must equal 100%
- Color-coded sliders per dimension
- Edit/Display mode toggle
- Shows derived values if not customized
UX Flow:
1. Default: Shows focus distribution (bars)
2. Click 'Anpassen': Shows sliders
3. Adjust percentages (sum = 100%)
4. Save → Updates backend + reloads
Visual:
- Active dimensions shown as colored cards (display mode)
- Gradient sliders with percentage labels (edit mode)
- Green box when sum = 100%, red when != 100%
- Info message if derived from old goal_mode
Complete v2.0:
✅ Backend (Migration 027, API, get_focus_weights V2)
✅ Frontend (Slider UI, state management, validation)
✅ Auto-migration (goal_mode → focus_areas)
Ready for: KI-Integration with weighted scoring
BREAKING: Replaces single 'primary goal' with weighted multi-goal system
Migration 027:
- New table: focus_areas (6 dimensions with percentages)
- Constraint: Sum must equal 100%
- Auto-migration: goal_mode → focus_areas for existing users
- Unique constraint: One active focus_areas per profile
Backend:
- get_focus_weights() V2: Reads from focus_areas table
- Fallback: Uses goal_mode if focus_areas not set
- New endpoints: GET/PUT /api/goals/focus-areas
- Validation: Sum=100, range 0-100
API:
- getFocusAreas() - Get current weights
- updateFocusAreas(data) - Update weights (upsert)
Focus dimensions:
1. weight_loss_pct (Fettabbau)
2. muscle_gain_pct (Muskelaufbau)
3. strength_pct (Kraftsteigerung)
4. endurance_pct (Ausdauer)
5. flexibility_pct (Beweglichkeit)
6. health_pct (Allgemeine Gesundheit)
Benefits:
- Multiple goals with custom priorities
- More flexible than single primary goal
- KI can use weighted scores
- Ready for Phase 0b placeholder integration
UI: Coming in next commit (slider interface)
NEW FEATURE: Filter conditions for goal types
Enables counting/aggregating specific subsets of data.
Example use case: Count only strength training sessions per week
- Create goal type with filter: {"training_type": "strength"}
- count_7d now counts only strength training, not all activities
Implementation:
- Migration 026: filter_conditions JSONB column
- Backend: Dynamic WHERE clause building from JSON filters
- Supports single value: {"training_type": "strength"}
- Supports multiple values: {"training_type": ["strength", "hiit"]}
- Works with all 8 aggregation methods (count, avg, sum, min, max)
- Frontend: JSON textarea with example + validation
- Pydantic models: filter_conditions field added
Technical details:
- SQL injection safe (parameterized queries)
- Graceful degradation (invalid JSON ignored with warning)
- Backward compatible (NULL filters = no filtering)
Answers user question: 'Kann ich Trainingstypen wie Krafttraining separat zählen?'
Answer: YES! 🎯
Admin can now easily create custom goal types:
- New endpoint /api/goals/schema-info with table/column metadata
- 9 tables documented (weight, caliper, activity, nutrition, sleep, vitals, BP, rest_days, circumference)
- Table dropdown with descriptions (e.g., 'activity_log - Trainingseinheiten')
- Column dropdown dependent on selected table
- All columns documented in German with data types
- Fields optional (for complex calculation formulas)
UX improvements:
- No need to guess table/column names
- Clear descriptions for each field
- Type-safe selection (no typos)
- Cascading dropdowns (column depends on table)
Closes user feedback: 'Admin weiß nicht welche Tabellen/Spalten verfügbar sind'
- try-catch around entire endpoint
- try-catch for each goal progress update
- Detailed error logging with traceback
- Continue processing other goals if one fails
- Clear error message to frontend
This will show exact error location in logs.
Fixes cases where Migration 024 partially ran:
- Removes created_by/updated_by columns if they exist
- Re-inserts seed data with ON CONFLICT DO NOTHING
- Fully automated, no manual intervention needed
- Production-safe (idempotent)
This ensures clean deployment to production without manual DB changes.
Goal type definitions are global system entities, not user-specific.
System types seeded in migration cannot have created_by FK.
Changes:
- Remove created_by/updated_by columns from goal_type_definitions
- Update CREATE/UPDATE endpoints to not use these fields
- Migration now runs cleanly on container start
- No manual intervention needed for production deployment
Removed faulty EXISTS check that was causing "0" error.
Added debug logging and better error messages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Check if goal_type_definitions table exists
- Detailed error messages
- Fallback if goalTypes is empty
- Prevent form opening without types
Helps debugging Migration 024 issues.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>