Files
WrestleDesk/docs/superpowers/specs/2026-03-23-training-log-design.md
T
Andrej Spielmann 3fefc550fe Initial commit: WrestleDesk full project
- 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
2026-03-26 13:24:57 +01:00

5.2 KiB
Raw Blame History

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

  1. Backend Model — Create TrainingLogEntry model in homework app (or new training_log app)
  2. Backend ViewSet — CRUD endpoints + stats endpoint + compare endpoint
  3. Frontend API Types — Add ITrainingLogEntry interface
  4. 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