feat: Implementierung von Phase 6 (Frontend und finale Anpassungen)

This commit is contained in:
Matthias Nagel 2025-10-01 09:33:29 +02:00
parent 51bf727885
commit 1d61821f9f
16 changed files with 246 additions and 73 deletions

View File

@ -11,9 +11,16 @@ def handle_absence_period(sender, instance, **kwargs):
start_time__date__gte=instance.start_date,
start_time__date__lte=instance.end_date
)
for event in events_in_period:
EventParticipation.objects.update_or_create(
user=user,
event=event,
defaults={'status': 'rejected'}
)
# Get existing participations for the user and events in the period
existing_participations = EventParticipation.objects.filter(user=user, event__in=events_in_period).values_list('event_id', flat=True)
# Bulk update existing participations
EventParticipation.objects.filter(user=user, event__in=events_in_period).update(status='rejected')
# Bulk create new participations
new_participations = [
EventParticipation(user=user, event=event, status='rejected')
for event in events_in_period if event.id not in existing_participations
]
EventParticipation.objects.bulk_create(new_participations)

View File

@ -1,10 +1,20 @@
{% extends "base.html" %}
{% block content %}
<h2>Edit Profile</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save Changes</button>
</form>
{% endblock %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h2>Edit Profile</h2>
</div>
<div class="card-body">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save Changes</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,10 +1,20 @@
{% extends "base.html" %}
{% block content %}
<h2>Enter Invitation Code</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
{% endblock %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h2>Enter Invitation Code</h2>
</div>
<div class="card-body">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,10 +1,20 @@
{% extends "base.html" %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h2>Login</h2>
</div>
<div class="card-body">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,10 +1,20 @@
{% extends "base.html" %}
{% block content %}
<h2>Create Player</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Create Player</button>
</form>
{% endblock %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h2>Create Player</h2>
</div>
<div class="card-body">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Create Player</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,10 +1,20 @@
{% extends "base.html" %}
{% block content %}
<h2>Register</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Register</button>
</form>
{% endblock %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h2>Register</h2>
</div>
<div class="card-body">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -58,7 +58,7 @@ ROOT_URLCONF = 'baseball_organisator.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
@ -81,6 +81,14 @@ DATABASES = {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
# 'default': {
# 'ENGINE': 'django.db.backends.mysql',
# 'NAME': 'baseball_organisator',
# 'USER': 'your_mysql_user',
# 'PASSWORD': 'your_mysql_password',
# 'HOST': 'localhost',
# 'PORT': '3306',
# }
}
@ -120,6 +128,8 @@ USE_TZ = True
STATIC_URL = 'static/'
STATICFILES_DIRS = [BASE_DIR / 'static']
# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field

View File

@ -1,11 +1,21 @@
{% extends "base.html" %}
{% block content %}
<h2>Delete Event</h2>
<p>Are you sure you want to delete "{{ object.title }}"?</p>
<form method="post">
{% csrf_token %}
<button type="submit">Confirm Delete</button>
<a href="{% url 'dashboard' %}">Cancel</a>
</form>
{% endblock %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h2>Delete Event</h2>
</div>
<div class="card-body">
<p>Are you sure you want to delete "{{ object.title }}"?</p>
<form method="post">
{% csrf_token %}
<button type="submit" class="btn btn-danger">Confirm Delete</button>
<a href="{% url 'dashboard' %}" class="btn btn-secondary">Cancel</a>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,10 +1,20 @@
{% extends "base.html" %}
{% block content %}
<h2>{% if object %}Edit Event{% else %}Create Event{% endif %}</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save</button>
</form>
{% endblock %}
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h2>{% if object %}Edit Event{% else %}Create Event{% endif %}</h2>
</div>
<div class="card-body">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,29 +1,33 @@
{% extends "base.html" %}
{% block content %}
<h2>Dashboard</h2>
{% if user.coached_teams.all or user.assisted_teams.all %}
<a href="{% url 'event-add' %}">Create New Event</a>
{% endif %}
<div class="d-flex justify-content-between align-items-center mb-3">
<h2>Dashboard</h2>
{% if user.coached_teams.all or user.assisted_teams.all %}
<a href="{% url 'event-add' %}" class="btn btn-primary">Create New Event</a>
{% endif %}
</div>
<h3>Your Team's Events</h3>
{% if events %}
<ul>
<div class="list-group">
{% for event in events %}
<li>
<strong>{{ event.title }}</strong> ({{ event.start_time }})
<p>{{ event.description }}</p>
<p>Location: {{ event.location_address }}</p>
<a href="{{ event.maps_shortlink }}" target="_blank">View on Map</a>
<div class="list-group-item list-group-item-action flex-column align-items-start">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{ event.title }}</h5>
<small>{{ event.start_time }}</small>
</div>
<p class="mb-1">{{ event.description }}</p>
<small>Location: {{ event.location_address }}</small>
<a href="{{ event.maps_shortlink }}" target="_blank" class="btn btn-secondary btn-sm">View on Map</a>
{% if user == event.team.head_coach or user in event.team.assistant_coaches.all %}
<a href="{% url 'event-update' event.pk %}">Edit</a>
<a href="{% url 'event-delete' event.pk %}">Delete</a>
<a href="{% url 'event-update' event.pk %}" class="btn btn-warning btn-sm">Edit</a>
<a href="{% url 'event-delete' event.pk %}" class="btn btn-danger btn-sm">Delete</a>
{% endif %}
</li>
</div>
{% endfor %}
</ul>
</div>
{% else %}
<p>No events found for your team.</p>
{% endif %}
{% endblock %}
{% endblock %}

25
docs/phase6.md Normal file
View File

@ -0,0 +1,25 @@
## Phase 6: Frontend und finale Anpassungen
Dies ist die letzte Phase, in der das Layout und die Leistung optimiert werden.
Schritt 1: Django Templates erstellen
Erstelle die HTML-Templates für alle Views (Login, Dashboard, Termine erstellen, etc.) im templates-Verzeichnis.
Sorge für ein modernes, responsives Layout, das der Projektbeschreibung entspricht.
Schritt 2: Statische Dateien verwalten
Konfiguriere STATICFILES_DIRS in settings.py.
Stelle sicher, dass CSS, JavaScript und Bilder korrekt geladen werden.
Schritt 3: Code-Optimierung und Performance
Führe Performance-Tests durch, um sicherzustellen, dass die App performant ist, besonders bei der Anzeige von Kalendern mit vielen Terminen.
Schritt 4: Dokumentation und Fertigstellung
Führe die finalen Migrationen aus.
Die App ist nun einsatzbereit für die Bereitstellung auf dem Webserver mit MySQL als Backend, wie in den Anforderungen definiert. Die Übergabe des Codes vom Entwicklungsrechner zum Webspeicher sollte, wie gefordert, unkompliziert möglich sein.

6
static/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

7
static/js/bootstrap.bundle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

44
templates/base.html Normal file
View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
{% load static %}
<html>
<head>
<title>Baseball Organisator</title>
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="{% url 'dashboard' %}">Baseball Organisator</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'edit_profile' %}">Profile</a>
</li>
<li class="nav-item">
<form method="post" action="{% url 'logout' %}">
{% csrf_token %}
<button type="submit" class="btn btn-link nav-link">Log Out</button>
</form>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}">Login</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
<div class="container mt-4">
{% block content %}
{% endblock %}
</div>
<script src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
</body>
</html>