- Load training categories in ActivityPage
- Display colored badge next to activity name in list view
- Badge shows category icon + name with category color
- Only shown if training_category is set
- Completes v9d Phase 1b
Ready for testing and production deployment.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
UX improvements based on user feedback:
1. Move TrainingTypeDistribution from ActivityPage to History page
- ActivityPage is for data entry, not visualization
- History (Verlauf) shows personal development/progress
- Chart now respects period selector (7/30/90/365 days)
2. Improve AdminTrainingTypesPage form styling
- All input fields now full width (100%)
- Labels changed from inline to headings above fields
- Textareas increased from 2 to 4 rows
- Added resize: vertical for textareas
- Increased gap between fields from 12px to 16px
- Follows style guide conventions
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>
- Migration 005: Add cardio subcategories (Gehen, Tanzen)
- Migration 005: Add new category "Geist & Meditation" with 4 subcategories
(Meditation, Atemarbeit, Achtsamkeit, Visualisierung)
- Update categories endpoint with mind category metadata
- Update Apple Health mapping: dance → dance, add meditation/mindfulness
- 6 new training types total
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add get_training_type_for_apple_health() mapping function (23 workout types)
- CSV import now automatically assigns training_type_id/category/subcategory
- New endpoint: GET /activity/uncategorized (grouped by activity_type)
- New endpoint: POST /activity/bulk-categorize (bulk update training types)
- New component: BulkCategorize with two-level dropdown selection
- ActivityPage: new "Kategorisieren" tab for existing activities
- Update CLAUDE.md: v9d Phase 1b progress
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1b - UI Integration:
===========================
ActivityPage:
- Replace old activity type dropdown with TrainingTypeSelect
- Add training_type_id, training_category, training_subcategory to form
- Two-level selection (category → subcategory)
Dashboard:
- Add TrainingTypeDistribution card (pie chart)
- Shows last 28 days activity distribution by type
- Conditional rendering (only if activities exist)
Still TODO:
- History: Add type badge display (next commit)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Training types system: ✅ deployed to dev
- Logout button: ✅ tested and working
- Migration 004: ✅ applied successfully (23 types)
- API endpoints: ✅ functional
Next: Phase 1b (UI integration)
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>
- Mark v9c as deployed to production (21.03.2026)
- Add BUG-005 to BUG-008 (login/verify navigation fixes)
- Document TrialBanner mailto change (on develop)
- Mark v9d as in progress
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace subscription selection link with email contact for now.
Future: Central subscription system on jinkendo.de for all apps.
Button text:
- "Abo wählen" → "Abo anfragen"
- "Jetzt upgraden" → "Kontakt aufnehmen"
Opens mailto:mitai@jinkendo.de with pre-filled subject and body.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Parse JSON error responses to extract 'detail' field
Fixes: {"detail":"..."} shown as raw JSON instead of clean text
2. Redirect 'already_verified' to '/' instead of '/login'
Fixes: Users land on empty page when already logged in
3. Change button text: "Jetzt anmelden" → "Weiter zum Dashboard"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1. Use window.location.href instead of navigate() for reliable redirect
2. Improve backend error message for already-used verification tokens
3. Show user-friendly message when token was already verified
4. Reduce redirect delay from 2s to 1.5s for better UX
Fixes:
- Empty page after email verification
- Generic error when clicking verification link twice
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LoginScreen was not navigating after login, leaving users on empty page.
Now explicitly redirects to '/' (dashboard) after successful login.
This fixes the "empty page after first login" issue.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add .catch() handler to load() Promise to prevent infinite loading state
- Add console.log statements for component lifecycle debugging
- Make EmailVerificationBanner/TrialBanner conditional on activeProfile
- Ensure greeting header always renders with fallback
This should fix the empty dashboard issue for new users.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added hasVerified flag to prevent useEffect from running twice
in React 18 StrictMode (development mode).
This was causing:
1. First call: 200 OK - verification successful
2. Second call: 400 Bad Request - already verified
3. Error shown to user despite successful verification
The fix ensures verify() only runs once per component mount.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AuthContext:
- Added setAuthFromToken() for direct token/profile set
- Used for email verification auto-login (no /login request)
- Properly initializes session with token and profile
Verify.jsx:
- Fixed auto-login: now uses setAuthFromToken() instead of login()
- Added "already_verified" status for better UX
- Auto-redirect to /login after 3s if already verified
- Shows friendly message instead of error
This fixes:
- 422 Unprocessable Entity error during auto-login
- Empty dashboard page after verification (now redirects correctly)
- "Ungültiger Link" error on second click (now shows "bereits bestätigt")
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend fixes:
- Fixed timezone-aware datetime comparison in verify_email endpoint
- Added trial_ends_at (14 days) for new registrations
- All datetime.now() calls now use timezone.utc
Frontend additions:
- Added EmailVerificationBanner component for unverified users
- Banner shows warning before trial banner in Dashboard
- Clear messaging about verification requirement
This fixes the 500 error on email verification and ensures new users
see both verification and trial status correctly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updated CLAUDE.md to reflect new database migrations system:
- Added backend/migrations/ to directory structure
- Added schema_migrations table to database schema
- Updated deployment section with migration workflow
- Added reference to .claude/docs/technical/MIGRATIONS.md
The migrations system automatically applies SQL files (XXX_*.sql pattern)
on container startup, with tracking in schema_migrations table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Modified run_migrations() to only process files matching pattern: \d{3}_*.sql
This prevents utility scripts (check_features.sql) and manually applied
migrations (v9c_*.sql) from being executed.
Only properly numbered migrations like 003_add_email_verification.sql
will be processed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added migration tracking and execution to db_init.py:
- Created schema_migrations table to track applied migrations
- Added run_migrations() to automatically apply pending SQL files
- Migrations from backend/migrations/*.sql are now applied on startup
This fixes the missing email verification columns (migration 003).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed build error where AuthContext was imported directly instead of using the useAuth hook.
Changed from import { AuthContext } + useContext(AuthContext) to import { useAuth } + useAuth().
This was blocking the Docker build and production deployment of v9c.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updates:
- Bug-Fixes: Added BUG-003 (chart extrapolation) and BUG-004 (history refresh)
- v9c Finalization: Self-registration + Trial UI marked as complete
- Moved open items to v9d
v9c is now feature-complete and ready for production deployment.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Component:
- TrialBanner.jsx: Displays remaining trial days with urgency levels
Features:
- Calculates days left from profile.trial_ends_at
- Three urgency levels:
* Normal (>7 days): Accent blue, "Abo wählen"
* Warning (≤7 days): Orange, "Abo wählen"
* Urgent (≤3 days): Red + ⚠️, "Jetzt upgraden"
- Auto-hides when no trial or trial ended
- Responsive flex layout
- Call-to-action button links to /settings?tab=subscription
Integration:
- Added to Dashboard after header greeting
- Uses activeProfile from ProfileContext
- Clean, non-intrusive design
UX:
- Clear messaging: "Trial endet in X Tagen"
- Special case: "morgen" for 1 day left
- Color-coded severity (blue → orange → red)
- Prominent CTA button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Components:
- Register.jsx: Registration form with validation
- Verify.jsx: Email verification page with auto-login
- API calls: register(), verifyEmail()
Features:
- Form validation (name min 2, email format, password min 8, password confirm)
- Success screen after registration (check email)
- Auto-login after verification → redirect to dashboard
- Error handling for invalid/expired tokens
- Link to registration from login page
Routes:
- /register → public (no login required)
- /verify?token=xxx → public
- Pattern matches existing /reset-password handling
UX:
- Clean success/error states
- Loading spinners
- Auto-redirect after verify (2s)
- "Jetzt registrieren" link on login
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend:
- New endpoint: POST /api/auth/register
- New endpoint: GET /api/auth/verify/{token}
- Migration: Add email_verified, verification_token, verification_expires
- Helper: send_email() for reusable SMTP
- Validation: email format, password length (min 8), name
- Auto-login after verification (returns session token)
- Rate limit: 3 registrations per hour per IP
Features:
- Verification token valid for 24h
- Existing users marked as verified (grandfather clause)
- SMTP configured via .env (SMTP_HOST, SMTP_USER, SMTP_PASS)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Changes:
- Show all data points (kcal OR weight, not only both)
- Extrapolate missing kcal values at end (use last known value)
- Dashed lines (strokeDasharray) for extrapolated values
- Solid lines for real measurements
- Weight always interpolates gaps (connectNulls=true)
Visual distinction:
- Solid = Real measurements + gap interpolation
- Dashed = Extrapolation at chart end
Closes: BUG-003
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Solution: Force remount ImportHistory via key prop
- Added importHistoryKey state (timestamp)
- Update key after import → triggers useEffect reload
- ImportHistory now updates immediately after import
Closes: BUG-004
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Layout changes:
- Input tabs at top: ✏️ Einzelerfassung (default) | 📥 Import
- Single entry form shown by default (was hidden in data tab)
- Import panel + history only visible in Import tab
- Analysis section below (unchanged): OverviewCards + Analysis tabs
Benefits:
- Cleaner separation of input methods vs analysis
- Manual entry more discoverable (was buried in data tab)
- Import history only shown when relevant
- Reduces clutter on initial view
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Features:
- Manual entry form above data list
- Date picker with auto-load existing entries
- Upsert logic: creates new or updates existing entry
- Smart button text: "Hinzufügen" vs "Aktualisieren"
- Prevents duplicate entries per day
- Feature enforcement for nutrition_entries
Backend:
- POST /nutrition - Create or update entry (upsert)
- GET /nutrition/by-date/{date} - Load entry by date
- Auto-detects existing entry and switches to UPDATE mode
- Increments usage counter only on INSERT
Frontend:
- EntryForm component with date picker + macros inputs
- Auto-loads data when date changes
- Shows info message when entry exists
- Success/error feedback
- Disabled state while loading/saving
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added dropdown filter with options:
- Letzte 7 Tage
- Letzte 30 Tage (default)
- Letzte 90 Tage
- Letztes Jahr
- Alle anzeigen
Shows filtered count vs total count in title.
Handles large datasets (7+ years) efficiently.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Features:
- Import history panel showing all CSV imports with date, count, and range
- Edit/delete functionality for nutrition entries (inline editing)
- New backend endpoints: GET /import-history, PUT /{id}, DELETE /{id}
UI Changes:
- Import history displayed under import panel
- "Daten" tab now has edit/delete buttons per entry
- Inline form for editing macros (kcal, protein, fat, carbs)
- Confirmation dialog for deletion
Backend:
- nutrition.py: Added import_history, update_nutrition, delete_nutrition endpoints
- Groups imports by created date to show history
Frontend:
- NutritionPage: New DataTab and ImportHistory components
- api.js: Added nutritionImportHistory, updateNutrition, deleteNutrition
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Problem: Imported nutrition data not visible in UI
Root Cause: NutritionPage only had analysis tabs, no raw data view
Solution: Added "Daten" tab with entries list showing date, kcal, macros
Tested: Entries now visible after CSV import
Closes: BUG-002
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Problem:
- /api/nutrition/weekly crashed with 500 Internal Server Error
- TypeError: strptime() argument 1 must be str, not datetime.date
Root Cause:
- d['date'] from PostgreSQL is already datetime.date object
- datetime.strptime() expects string input
- Line 156: wk=datetime.strptime(d['date'],'%Y-%m-%d').strftime('%Y-W%V')
Solution:
- Added type check before strptime()
- If date already has strftime method → use directly
- Else → parse as string first
- Works with both datetime.date objects and strings
Tested:
- /nutrition page loads without error
- Weekly aggregation works correctly
- Chart displays nutrition data
Closes: BUG-001
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CLAUDE.md erweitert:
- Verweis auf PENDING_FEATURES.md (ausstehende Enforcement-Items)
- Verweis auf KNOWN_ISSUES.md (Bug-Tracking)
Lokal erstellt (in .claude/):
.claude/docs/PENDING_FEATURES.md:
- Dashboard-Assistent (keine Badges)
- Import-Endpoints ohne Enforcement (Activity CSV, Nutrition CSV)
- Weitere potenzielle Limitierungen (Export-Wiederholungen, etc.)
- Implementierungs-Richtlinien für späteres Nachziehen
.claude/docs/KNOWN_ISSUES.md:
- BUG-001: Nutrition Import-Seite zeigt keine bisherigen Importe
(Daten vorhanden in Verlauf, aber Import-Panel zeigt keine Historie)
- Technische Schulden (alte AI-Limit-Checks, deprecated export_enabled)
- Bug-Meldung-Prozess dokumentiert
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Feature-Enforcement komplett:
- ✅ Phase 1-4 alle abgeschlossen
- 11 Features mit Monitoring, UI-Badges + Blocking
- Verweis auf neue FEATURE_ENFORCEMENT.md Dokumentation
Lokale Dokumentation erstellt:
- .claude/docs/architecture/FEATURE_ENFORCEMENT.md
- Vollständiger Guide für neue Feature-Integration
- Backend + Frontend Pattern mit Beispielen
- Checkliste + Debugging-Tipps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Alle verbleibenden Screens mit proaktiver Limit-Anzeige:
- ActivityPage: Manuelle Einträge mit Badge + deaktiviertem Button
- Analysis: AI-Analysen (Pipeline + Einzelanalysen) mit Hover-Tooltip
- NutritionPage: Hat bereits Error-Handling (bulk import)
Konsistentes Pattern:
- Usage-Badge im Titel
- Button deaktiviert + Hover-Tooltip bei Limit
- "🔒 Limit erreicht" Button-Text
- Error-Handling für API-Fehler
- Usage reload nach erfolgreichem Speichern
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Dashboard QuickWeight: Feature limit enforcement hinzugefügt
- Hover-Tooltip Fix: Button in div wrapper (disabled buttons zeigen keine nativen tooltips)
- Error handling für Dashboard weight input
- Konsistentes UX über alle Eingabe-Screens
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implementiert User-freundliches Limit-Feedback für Daten-Einträge:
- Button wird deaktiviert wenn Limit erreicht
- Hover-Tooltip erklärt warum ("Limit erreicht X/Y")
- Button-Text zeigt "🔒 Limit erreicht"
- Error-Handling für alle API-Fehler
- Usage-Badge wird nach Speichern aktualisiert
Betrifft: Weight, Circumference, Caliper Screens
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Behebt IndentationError in Zeile 204 der _check_impl() Funktion.
Die Funktion wurde beim Connection-Pool-Fix erstellt, hatte aber
inkonsistente Einrückungen (8 statt 4 Spaces nach der ersten Zeile).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move all positioning logic from inline styles to CSS
- New classes: .badge-container-right, .badge-button-layout
- All badge styling now in UsageBadge.css (single source)
- Easier to maintain and adjust globally
- Mobile responsive adjustments in one place
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Smaller font (0.65rem), more spacing (10px margin)
- Reduced opacity (0.6), hover effect (0.9)
- OK status now gray instead of green (less prominent)
- Position: right-aligned in headings (flex space-between)
- Buttons: badge on right side of main text, description below
- Much more discreet overall appearance
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Weight page: badge on "Eintrag hinzufügen" heading
- Settings: badges on export buttons (ZIP/JSON)
- Analysis: badges on pipeline and individual analysis titles
- Shows real-time usage status (e.g., "7/5" with red color)
Phase 3: Frontend Display complete
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add user-facing usage overview endpoint
- Returns all features with usage, limits, reset info
- Fully dynamic - automatically includes new features
- Phase 3: Frontend Display preparation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>