AdminPanel.jsx:
- Removed ai_enabled, ai_limit_day, export_enabled UI
- Kept only role selection (Admin/User)
- Added link to Feature-Overrides page
- Simplified perms state to only role
- Changed display to show tier and email
AdminUserRestrictionsPage.jsx:
- Removed legacy system warning
- Clean interface, no confusion
Result:
- ONE consistent permission system (feature-overrides)
- Clear separation: role in AdminPanel, limits in Feature-Overrides
- No data migration needed (no old users exist)
- System ready for production
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Button position fixed:
- Moved from fixed bottom bar to header (like TierLimitsPage)
- No longer covers bottom navigation menu
- Always visible when user selected
- "Abbrechen" only shown when changes exist
Legacy system warning added:
- Yellow warning box explaining old permission system
- Old system: ai_enabled, ai_limit_day, export_enabled in profiles table
- New system: feature_restrictions table with overrides
- Warning: both systems can conflict, new system has priority
- Recommendation: use only feature-overrides going forward
This addresses:
1. UI overlap issue (buttons covering navigation)
2. System architecture confusion (two permission systems)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Bottom bar changes:
- Always visible when user selected (not hidden)
- Buttons disabled when no changes (clearer state)
- Moved outside inner block to prevent hiding
Action column changes:
- "↺ Zurück" button always visible per feature
- Disabled when no override exists (grayed out)
- Consistent button presence improves UX
This fixes the issue where buttons were not shown
because they were conditionally rendered.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added tier limits column:
- Shows current tier-limit value for each feature
- Loads from tier-limits matrix based on user's tier
- Visual display for boolean (✓ AN / ✗ AUS) and count features
- Clear comparison: Tier-Limit vs Override-Wert
Added per-feature reset button:
- "↺ Zurück zu Standard" button per feature
- Only shown when override exists
- Removes override with single click
Improved bottom bar buttons:
- Renamed "Zurücksetzen" to "Abbrechen" (clearer)
- Always visible (not hidden when no changes)
- Disabled state when no changes
- Shows "Keine Änderungen" when nothing to save
Better UX:
- Tier-Limit column shows what user gets without override
- Override input highlighted when active (accent-light background)
- Clear action buttons per row
- Global save/cancel at bottom
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed all reported bugs:
1. Initial values now correct (empty = no override, not defaults)
2. Save/Reset buttons always visible (fixed bottom bar)
3. Toggle buttons work correctly (can be toggled multiple times)
4. Simplified table columns (removed confusing Tier-Limit/Aktiv/Aktion)
New logic:
- Empty input = no override (user uses tier standard)
- Value entered = override set
- Change tracking with 3 actions: set, remove, toggle
- Clear status display: "Override aktiv" vs "Tier-Standard"
Simplified table structure:
- Feature (name + type)
- Override-Wert (input/toggle)
- Status (has override yes/no)
Better UX:
- Placeholder text explains empty = tier standard
- Status badge shows if override is active
- Fixed bottom bar always present
- Buttons disabled only when no changes
- Legend explains all input options
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Per-user feature limit overrides:
- Select user from dropdown (shows tier)
- View all features with tier limits
- Set individual overrides that supersede tier limits
- Toggle buttons for boolean features
- Text inputs for count features
- Remove overrides to revert to tier limits
Features:
- User info card (avatar, name, email, tier)
- Feature table grouped by category
- Visual indicators for active overrides
- Change tracking with fixed bottom save bar
- Conditional rendering based on limit type
- Info box explaining override priority
UX improvements:
- Clear "Tier-Limit" vs "Override" columns
- Active/Inactive status per feature
- Batch save with change counter
- Confirmation before removing overrides
- Legend for input values
Use cases:
- Beta testers with extended limits
- Support requests for special access
- Temporary feature grants
- Custom enterprise configurations
Integrated in AdminPanel navigation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full CRUD interface for coupons:
- Create, edit, delete coupons
- Three coupon types supported:
- Single-Use: one-time redemption per user
- Multi-Use Period: unlimited redemptions in timeframe (Wellpass)
- Gift: bonus system coupons
Features:
- Auto-generate random coupon codes
- Configure tier, duration, validity period
- Set max redemptions (or unlimited)
- View redemption history per coupon (modal)
- Active/inactive state management
- Card-based layout with visual type indicators
Form improvements:
- Conditional fields based on coupon type
- Date pickers for period coupons
- Duration config for single-use/gift
- Help text for each field
- Labels above inputs (consistent with other pages)
Integrated in AdminPanel navigation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Layout improvements:
- Labels now above inputs (not beside)
- Inputs use full width for better readability
- Better spacing and visual hierarchy
Field changes:
- Removed "Einheit" field (unused, confusing)
- "Sortierung" renamed to "Anzeigereihenfolge" with help text
- Added help text under inputs for clarity
Conditional rendering:
- Boolean features: hide Reset-Periode and Standard-Limit
- Show info box explaining Boolean features
- Count features: show all relevant fields
Better UX:
- Clear explanations what each field does
- Visual feedback for different limit types
- Cleaner, more focused interface
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Philosophy change:
- Features are registered via code/migrations, not UI
- AdminFeaturesPage now only configures existing features
- No create/delete functionality
Changes:
- Removed "Neues Feature" button and create form
- Removed delete functionality
- Feature ID now read-only in edit mode
- Added info box explaining feature registration
- Improved status display (Aktiv/Inaktiv)
- Added legend for limit types and reset periods
- Focus on configuration: limit type, reset period, defaults, active state
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AdminFeaturesPage:
- Full CRUD for features registry
- Add/edit features with all properties
- Category, limit type, reset period configuration
- Default limits and sorting
AdminTiersPage:
- Full CRUD for subscription tiers
- Pricing configuration (monthly/yearly in cents)
- Active/inactive state management
- Card-based layout with edit/delete actions
Both pages:
- Form validation
- Success/error messaging
- Clean table/card layouts
- Integrated in AdminPanel navigation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Boolean features now show as visual toggle buttons (AN/AUS)
- Desktop: compact toggle (✓ AN / ✗ AUS)
- Mobile: full-width toggle (✓ Aktiviert / ✗ Deaktiviert)
- Prevents invalid values for boolean features
- Green when enabled, gray when disabled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove active=true filter - admins need to configure all tiers
- Add reset_period to features query for frontend display
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix input bug: cells now editable after deletion (temp value tracking)
- Add responsive design: mobile card view, desktop table view
- Mobile: accordion-style FeatureMobileCard with fixed bottom bar
- Desktop: enhanced table with better visual feedback
- Maintains PWA compatibility (no media query conflicts)
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>
Changed all profile_id columns from TEXT to UUID to match profiles.id type.
Changed all auto-generated IDs from gen_random_uuid() to uuid_generate_v4()
to match existing schema.sql convention.
Fixed tables:
- tier_limits: id TEXT → UUID
- user_feature_restrictions: id, profile_id, created_by TEXT → UUID
- user_feature_usage: id, profile_id TEXT → UUID
- coupons: id, created_by TEXT → UUID
- coupon_redemptions: id, coupon_id, profile_id, access_grant_id TEXT → UUID
- access_grants: id, profile_id, coupon_id, paused_by TEXT → UUID
- user_activity_log: id, profile_id TEXT → UUID
- user_stats: profile_id TEXT → UUID
- profiles.invited_by: TEXT → UUID
This fixes: foreign key constraint "user_feature_restrictions_profile_id_fkey"
cannot be implemented - Key columns "profile_id" and "id" are of
incompatible types: text and uuid
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaced hardcoded tier limits with flexible Feature-Registry Pattern:
- features table: All limitable features (weight, AI, photos, export, etc.)
- tier_limits: Tier x Feature matrix (admin-configurable)
- user_feature_restrictions: Individual user overrides
- user_feature_usage: Usage tracking with configurable reset periods
Key capabilities:
- Add new limitable features without schema changes
- Admin UI for matrix-based limit configuration
- User-level overrides for specific restrictions
- Access hierarchy: User restriction > Tier limit > Feature default
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PROBLEM:
- Backend crasht beim Start auf Prod
- Migration schlägt fehl: column 'meas_id' does not exist
- SQLite ai_insights hat Legacy-Spalte meas_id
- PostgreSQL schema hat diese Spalte nicht mehr
FIX:
- COLUMN_WHITELIST für ai_insights hinzugefügt
- Nur erlaubte Spalten werden migriert:
id, profile_id, scope, content, created
- meas_id wird beim Import gefiltert
DATEIEN:
- backend/migrate_to_postgres.py
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>
PROBLEM 1: Deaktivierte Prompts auf Verlaufsseiten sichtbar
- Deaktivierte Analysen (z.B. "Komposition") wurden auf Verlaufsseiten
(Körper, Ernährung, etc.) als klickbare Buttons angezeigt
FIX:
- Prompts werden jetzt in History.jsx geladen (api.listPrompts)
- filterActiveSlugs() filtert nur aktive Prompts
- InsightBox zeigt nur Buttons für aktive Analysen
PROBLEM 2: Pipeline konnte nicht deaktiviert werden
- Mehrstufige Gesamtanalyse war immer sichtbar
FIX:
- Pipeline ist nur verfügbar wenn ALLE Sub-Prompts aktiv sind
- Prüft: pipeline_body, pipeline_nutrition, pipeline_activity,
pipeline_synthesis, pipeline_goals
- Deaktiviere einen Sub-Prompt → Pipeline verschwindet
PROBLEM 3: Fehler "z.text is not a function"
- Nach Analyse-Ausführung auf Verlaufsseiten kam Fehler
- Code behandelte api.runInsight() wie fetch()-Response
FIX:
- api.runInsight() gibt bereits JSON zurück, nicht Response
- Entfernte fehlerhafte if(!r.ok) und await r.text()
- Error-Handling wie in Analysis.jsx (catch e.message)
DATEIEN:
- frontend/src/pages/History.jsx: alle 3 Fixes
- frontend/src/pages/Analysis.jsx: Pipeline-Verfügbarkeit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
KRITISCHER BUG behoben:
- savePrompt() und Aktivieren/Deaktivieren sendeten KEIN Auth-Token
- Backend require_admin() warf deshalb 401 Unauthorized
- Prompt-Bearbeitung funktionierte überhaupt nicht (auch für Admins)
Fix:
- X-Auth-Token Header zu beiden fetch()-Calls hinzugefügt
- Token aus localStorage wie in anderen Admin-Funktionen
Rechtesystem BESTÄTIGT korrekt:
✅ Backend: nur require_admin() darf Prompts ändern
✅ DB: ai_prompts hat KEINE profile_id → universell
✅ Frontend: Tab "Prompts" nur für isAdmin sichtbar
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>
SettingsPage was still calling window.open() directly,
bypassing the auth-enabled fetch methods in api.js.
Changed buttons to use api.exportZip() and api.exportJson()
which properly include authentication headers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Changed from window.open() to fetch() + Blob download.
window.open() cannot send custom headers, causing 401 errors.
**Changed:**
- exportZip: fetch with auth, download blob as .zip
- exportJson: fetch with auth, download blob as .json
- exportCsv: fetch with auth, download blob as .csv
All exports now work with authenticated sessions.
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>