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
This commit is contained in:
Andrej Spielmann
2026-03-26 13:24:57 +01:00
commit 3fefc550fe
256 changed files with 38295 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
from django.db import models
from django.utils import timezone
class LeistungstestTemplate(models.Model):
name = models.CharField(max_length=200)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created_at']
def __str__(self):
return self.name
@property
def usage_count(self):
return LeistungstestResult.objects.filter(template_id=self.pk).count()
class LeistungstestTemplateExercise(models.Model):
template = models.ForeignKey(LeistungstestTemplate, on_delete=models.CASCADE, related_name='exercises')
exercise = models.ForeignKey('exercises.Exercise', on_delete=models.CASCADE)
target_reps = models.PositiveIntegerField()
order = models.IntegerField(default=0)
class Meta:
ordering = ['template', 'order']
unique_together = ['template', 'exercise']
def __str__(self):
return f"{self.template.name} - {self.exercise.name}"
class LeistungstestResult(models.Model):
template = models.ForeignKey(LeistungstestTemplate, on_delete=models.CASCADE, related_name='results')
wrestler = models.ForeignKey('wrestlers.Wrestler', on_delete=models.CASCADE, related_name='leistungstest_results')
total_time_seconds = models.PositiveIntegerField(null=True, blank=True)
rating = models.PositiveSmallIntegerField(choices=[(1,1),(2,2),(3,3),(4,4),(5,5)], default=3)
notes = models.TextField(blank=True)
completed_at = models.DateTimeField(default=timezone.now)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-completed_at']
indexes = [
models.Index(fields=['wrestler']),
models.Index(fields=['template']),
models.Index(fields=['completed_at']),
]
def __str__(self):
return f"{self.wrestler} - {self.template.name}"
@property
def score_percent(self):
items = self.items.all()
if not items.exists():
return 0
total_target = sum(item.target_reps for item in items)
total_actual = sum(item.actual_reps for item in items)
if total_target == 0:
return 0
return round((total_actual / total_target) * 100, 1)
class LeistungstestResultItem(models.Model):
result = models.ForeignKey(LeistungstestResult, on_delete=models.CASCADE, related_name='items')
exercise = models.ForeignKey('exercises.Exercise', on_delete=models.CASCADE)
target_reps = models.PositiveIntegerField()
actual_reps = models.PositiveIntegerField()
order = models.IntegerField(default=0)
elapsed_seconds = models.PositiveIntegerField(default=0)
class Meta:
ordering = ['result', 'order']
def __str__(self):
return f"{self.result} - {self.exercise.name}: {self.actual_reps}/{self.target_reps}"