- Add sleep_log table with JSONB sleep_segments (Migration 009)
- Add sleep router with CRUD + stats endpoints (7d avg, 14d debt, trend, phases)
- Add SleepPage with quick/detail entry forms and inline edit
- Add SleepWidget to Dashboard showing last night + 7d average
- Add sleep navigation entry with Moon icon
- Register sleep router in main.py
- Add 9 new API methods in api.js
Phase 2b complete - ready for testing on dev
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend (v9d Phase 1b):
- Migration 006: Add abilities JSONB column + descriptions
- admin_training_types.py: Full CRUD endpoints for training types
- List, Get, Create, Update, Delete
- Abilities taxonomy endpoint (5 dimensions: koordinativ, konditionell, kognitiv, psychisch, taktisch)
- Validation: Cannot delete types in use
- Register admin_training_types router in main.py
Frontend:
- AdminTrainingTypesPage: Full CRUD UI
- Create/edit form with all fields (category, subcategory, names, icon, descriptions, sort_order)
- List grouped by category with color coding
- Delete with usage check
- Note about abilities mapping coming in v9f
- Add TrainingTypeDistribution to ActivityPage stats tab
- Add admin link in AdminPanel (v9d section)
- Update api.js with admin training types methods
Notes:
- Abilities mapping UI deferred to v9f (flexible prompt system)
- Placeholders (abilities column) in place for future AI analysis
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1: Training Types Basis
=============================
Backend:
- Migration 004: training_types table + seed data (24 types)
- New router: /api/training-types (grouped, flat, categories)
- Extend activity_log: training_type_id, training_category, training_subcategory
- Extend ActivityEntry model: support training type fields
Frontend:
- TrainingTypeSelect component (two-level dropdown)
- TrainingTypeDistribution component (pie chart)
- API functions: listTrainingTypes, listTrainingTypesFlat, getTrainingCategories
Quick Win: Logout Button
========================
- Add LogOut icon button in app header
- Confirm dialog before logout
- Redirect to / after logout
- Hover effect: red color on hover
Not yet integrated:
- TrainingTypeSelect not yet in ActivityPage form
- TrainingTypeDistribution not yet in Dashboard
(will be added in next commit)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New router: routers/coupons.py
Admin endpoints:
- GET /api/coupons - List all coupons with stats
- POST /api/coupons - Create new coupon
- PUT /api/coupons/{id} - Update coupon
- DELETE /api/coupons/{id} - Soft-delete (set active=false)
- GET /api/coupons/{id}/redemptions - Redemption history
User endpoints:
- POST /api/coupons/redeem - Redeem coupon code
Features:
- Three coupon types: single_use, period, wellpass
- Wellpass logic: Pauses existing personal grants, resumes after expiry
- Max redemptions limit (NULL = unlimited)
- Validity period checks
- Activity logging
- Duplicate redemption prevention
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New router: routers/subscription.py
Endpoints:
- GET /api/subscription/me - Own subscription info (tier, trial, grants)
- GET /api/subscription/usage - Feature usage with limits
- GET /api/subscription/limits - All feature limits for current tier
Features:
- Shows effective tier (considers access_grants)
- Lists active access grants (from coupons, trials)
- Per-feature usage tracking
- Email verification status
Uses new middleware: get_effective_tier(), check_feature_access()
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PROBLEM:
- Backend crasht beim Start auf Prod
- Login zeigt HTML statt JSON (Backend nicht erreichbar)
- Ursache: init_db() wirft Exception beim Startup
FIX:
1. startup_event() wrapped in try-except (non-fatal)
2. init_db() prüft ob ai_prompts Tabelle existiert
3. init_db() hat eigenen try-except
4. Bessere Fehlermeldungen in stdout
ERGEBNIS:
- Backend startet auch wenn init_db() fehlschlägt
- Pipeline-Prompt kann manuell angelegt werden falls nötig
- Login funktioniert wieder
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- /api/prompts checkt nun ob User admin ist
- Admins sehen ALLE Prompts (inkl. pipeline_ und inaktive)
- Normale User sehen nur aktive Einzelanalysen (wie bisher)
- Frontend (Analysis.jsx) zeigt Pipeline-Prompts bereits korrekt:
* Gruppiert nach "Einzelanalysen" und "Mehrstufige Pipeline"
* JSON-Prompts (Stage 1) mit oranger Border und Badge
* Warnung über JSON-Format bereits vorhanden
- CSS-Variablen --warn, --warn-bg, --warn-text bereits definiert
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Backend: POST /api/import/zip endpoint with validation and rollback
- CSV import with ON CONFLICT DO NOTHING for duplicate detection
- Photo import with existence check
- AI insights import
- Frontend: file upload UI in SettingsPage
- Import summary showing count per category
- Full transaction rollback on error
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PostgreSQL returns dob as datetime.date object, not string.
Changed from prof['dob'][:4] to prof['dob'].year
Error was: TypeError: 'datetime.date' object is not subscriptable
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed TypeError when preparing AI prompt template variables.
PostgreSQL returns NUMERIC columns as decimal.Decimal, not float.
**Fixed in _prepare_template_vars:**
- Weight calculations (protein targets, delta)
- Nutrition averages (kcal, protein, fat, carbs)
- Activity totals (kcal_active)
All Decimal values now converted to float before math operations.
Error was: "TypeError: unsupported operand type(s) for *: 'decimal.Decimal' and 'float'"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed 11 critical endpoint mismatches found during codebase audit.
**Renamed Endpoints (consistency):**
- /api/ai/analyze/{slug} → /api/insights/run/{slug}
- /api/ai/analyze-pipeline → /api/insights/pipeline
- /api/auth/password-reset-request → /api/auth/forgot-password
- /api/auth/password-reset-confirm → /api/auth/reset-password
- /api/admin/test-email → /api/admin/email/test
**Added Missing Endpoints:**
- POST /api/auth/pin (change PIN/password for current user)
- PUT /api/admin/profiles/{id}/permissions (set permissions)
- PUT /api/admin/profiles/{id}/email (set email)
- PUT /api/admin/profiles/{id}/pin (admin set PIN)
- GET /api/admin/email/status (check SMTP config)
- PUT /api/prompts/{id} (edit prompt templates, admin only)
- GET /api/export/json (export all data as JSON)
- GET /api/export/zip (export data + photos as ZIP)
**Updated:**
- Added imports: json, zipfile, Response
- Fixed admin email test endpoint to accept dict body
All frontend API calls now have matching backend implementations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add GET /api/insights (returns all insights for profile)
- Add DELETE /api/insights/{id} (delete by ID, not scope)
- Frontend Analysis.jsx needs these endpoints to load/delete insights
Fixes 404 error preventing prompts from displaying.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Change WHERE active=1 to WHERE active=true (PostgreSQL uses boolean)
- Change endpoint from /api/ai/prompts to /api/prompts (simpler path)
- Fixed 5 occurrences across prompt-related queries
This fixes the issue where no prompts were returned, causing empty
prompt list in Admin and no AI analysis options.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add GET /api/insights/latest (returns latest 10 insights)
- Add GET /api/auth/status (health check endpoint)
These endpoints were called by frontend but returned 404,
causing uncaught promise errors that blocked page loading.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
RealDictCursor returns dicts, not tuples. Cannot use [0] for index access.
Changed all COUNT(*) to COUNT(*) as count and access via ['count'].
Fixes: KeyError: 0 on cur.fetchone()[0]
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All conn.cursor() calls replaced with get_cursor(conn) to enable
dict-like row access (prof['pin_hash'] instead of prof[column_index]).
This fixes KeyError when accessing PostgreSQL query results.
Fixes: 'tuple' object has no attribute '__getitem__' with string keys
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>