Problem: Creating new training types via Admin UI resulted in
'Internal Server Error' because abilities dict was passed directly
to PostgreSQL JSONB column without Json() wrapper.
Solution:
- Import Json from psycopg2.extras
- Wrap abilities_json with Json() in INSERT
- Wrap data.abilities with Json() in UPDATE
Same issue as rest_days JSONB fix (commit 7d627cf).
Closes#13
- Add RestDaysWidget component showing today's rest days with icons & colors
- Integrate widget into Dashboard (above training distribution)
- Highlight current day in RestDaysPage (accent border + HEUTE badge)
- Fix: Improve error handling in api.js (parse JSON detail field)
Part of v9d Phase 2 (Vitals & Recovery)
Problem: User can create multiple rest days of same type per date
(e.g., 2x Mental Rest on 2026-03-23) - makes no sense.
Solution: UNIQUE constraint on (profile_id, date, focus)
## Migration 012:
- Add focus column (extracted from rest_config JSONB)
- Populate from existing data
- Add NOT NULL constraint
- Add CHECK constraint (valid focus values)
- Add UNIQUE constraint (profile_id, date, focus)
- Add index for performance
## Backend:
- Insert focus column alongside rest_config
- Handle UniqueViolation gracefully
- User-friendly error: "Du hast bereits einen Ruhetag 'Muskelregeneration' für 23.03."
## Benefits:
- DB-level enforcement (clean)
- Fast queries (no JSONB scan)
- Clear error messages
- Prevents: 2x muscle_recovery same day
- Allows: muscle_recovery + mental_rest same day ✓
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migration 011 removed UNIQUE constraint (profile_id, date) to allow
multiple rest days per date, but INSERT still used ON CONFLICT.
Error: psycopg2.errors.InvalidColumnReference: there is no unique or
exclusion constraint matching the ON CONFLICT specification
Solution: Remove ON CONFLICT clause, use plain INSERT.
Multiple entries per date now allowed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Error: psycopg2.ProgrammingError: can't adapt type 'dict'
Solution: Import psycopg2.extras.Json and wrap config_dict
Changes:
- Import Json from psycopg2.extras
- Wrap config_dict with Json() in INSERT
- Wrap config_dict with Json() in UPDATE
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Problem: Photos were always getting NULL date instead of form date,
causing frontend to fallback to created timestamp (today).
Root cause: FastAPI requires Form() wrapper for form fields when
mixing with File() parameters. Without it, the date parameter was
treated as query parameter and always received empty string.
Solution:
- Import Form from fastapi
- Change date parameter from str="" to str=Form("")
- Return photo_date instead of date in response (consistency)
Now photos correctly use the date from the upload form and can be
backdated when uploading later.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Problem:
- Photo upload with empty date parameter (date='')
- PostgreSQL rejects empty string for DATE field
- Error: "invalid input syntax for type date: ''"
- Occurred when saving circumference entry with only photo
Fix:
- Convert empty string to NULL before INSERT
- Check: date if date and date.strip() else None
- NULL is valid for optional date field
Test case:
- Circumference entry with only photo → should work now
- Photo without date → stored with date=NULL ✓
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>