3fefc550fe
- Django backend with DRF (clubs, wrestlers, trainers, exercises, templates, trainings, homework, locations, leistungstest) - Next.js 16 frontend with React, Shadcn UI, Tailwind - JWT authentication - Full CRUD for all entities - Calendar view for trainings - Homework management system - Leistungstest tracking
5.2 KiB
5.2 KiB
Training Log & Progress Analysis Design
Date: 2026-03-23
Status: Approved
Overview
Create a "Training Log" page for recording actual exercises performed by wrestlers during training sessions. The system tracks detailed exercise data (reps, sets, time, weight, rating) and provides analysis features including wrestler comparison and progress tracking over time.
Design
Layout
Single page with 3 tabs:
- Log (📋) — Quick entry form for new exercise records
- Historie (📜) — Filterable list of all entries
- Analyse (📊) — Summary stats, progress tracking, and wrestler comparison
Tab 1: Log
Entry Form:
- Ringer dropdown (required)
- Training dropdown (optional — links to specific training session)
- Übung dropdown (required — from exercises)
- reps input (number, required)
- sets input (number, default 1)
- zeit input (minutes, optional)
- Gewicht input (kg, optional)
- Bewertung — 5-star rating selector
- Notizen textarea (optional)
- Speichern button
Tab 2: Historie
Filter Bar:
- Ringer dropdown (filter by wrestler)
- Datum dropdown (date range)
- Übung dropdown (filter by exercise)
- Suchen button
Entry List:
- Table showing: Datum, Ringer, Übung, reps×sets, Zeit, Gewicht, Bewertung
- Clickable rows for potential editing
- Sorted by date (newest first)
Tab 3: Analyse
Wrestler Selector:
- Dropdown to select specific wrestler
- OR "Alle vergleichen" option
Summary Card:
- Gesamt: total entries
- Verschiedene Übungen: count of unique exercises
- Wiederholungen: total reps
- Ø Sätze: average sets per entry
- Ø Bewertung: average rating
- Diese Woche: entries this week
Top Übungen Card:
- List of most performed exercises with counts
- Bar visualization
Fortschritt Card:
- Shows improvement over time for selected wrestler
- Progress bars with percentage change
- Only exercises with measurable progress
Übungsvergleich Card:
- Side-by-side comparison of two wrestlers
- Bar chart showing reps for same exercise types
- Only shows exercises both wrestlers have done
Data Models
Backend Model: TrainingLogEntry
class TrainingLogEntry(models.Model):
wrestler = ForeignKey('wrestlers.Wrestler')
training = ForeignKey('trainings.Training', null=True, blank=True)
exercise = ForeignKey('exercises.Exercise')
reps = PositiveIntegerField()
sets = PositiveIntegerField(default=1)
time_minutes = PositiveIntegerField(null=True, blank=True)
weight_kg = DecimalField(null=True, blank=True, max_digits=5, decimal_places=2)
rating = PositiveIntegerField(choices=[(1,1),(2,2),(3,3),(4,4),(5,5)])
notes = TextField(blank=True)
logged_at = DateTimeField(default=timezone.now)
created_at = DateTimeField(auto_now_add=True)
updated_at = DateTimeField(auto_now=True)
class Meta:
ordering = ['-logged_at']
indexes = [
Index(fields=['wrestler']),
Index(fields=['exercise']),
Index(fields=['logged_at']),
]
API Endpoints
GET /api/v1/training-log/ — List entries (filterable)
POST /api/v1/training-log/ — Create entry
GET /api/v1/training-log/{id}/ — Get single entry
PATCH /api/v1/training-log/{id}/ — Update entry
DELETE /api/v1/training-log/{id}/ — Delete entry
GET /api/v1/training-log/stats/ — Analysis stats
GET /api/v1/training-log/compare/ — Comparison data
Response Shapes
List Response (GET /training-log/)
{
"count": 156,
"results": [
{
"id": 1,
"wrestler": 1,
"wrestler_name": "Max M.",
"training": 5,
"training_date": "2026-03-23",
"exercise": 1,
"exercise_name": "Pushups",
"reps": 50,
"sets": 3,
"time_minutes": 2,
"weight_kg": 10.0,
"rating": 4,
"notes": "",
"logged_at": "2026-03-23T15:30:00Z"
}
]
}
Stats Response (GET /training-log/stats/?wrestler=1)
{
"total_entries": 156,
"unique_exercises": 12,
"total_reps": 4230,
"avg_sets": 3.2,
"avg_rating": 3.8,
"this_week": 23,
"top_exercises": [
{"name": "Pushups", "count": 45},
{"name": "Klimmzüge", "count": 32}
],
"progress": {
"Pushups": {"before": 40, "after": 50, "change_percent": 25},
"Klimmzüge": {"before": 8, "after": 10, "change_percent": 40}
}
}
Compare Response (GET /training-log/compare/?wrestler1=1&wrestler2=2)
{
"wrestler1": {"id": 1, "name": "Max M."},
"wrestler2": {"id": 2, "name": "Anna S."},
"exercises": [
{
"exercise": "Pushups",
"wrestler1_avg": 50,
"wrestler2_avg": 30
}
]
}
Implementation Steps
- Backend Model — Create TrainingLogEntry model in homework app (or new training_log app)
- Backend ViewSet — CRUD endpoints + stats endpoint + compare endpoint
- Frontend API Types — Add ITrainingLogEntry interface
- Frontend Page — Create /training-log page with 3 tabs
Notes
- Training dropdown should only show trainings from the past (can't log future)
- Weight should accept decimals (e.g., 10.5 kg)
- Rating is 1-5 stars
- All timestamps stored in UTC, displayed in local time