Rene 1 жил өмнө
parent
commit
0a5d5ebca6

BIN
db.sqlite3


+ 0 - 0
helper/__init__.py


+ 24 - 0
helper/admin.py

@@ -0,0 +1,24 @@
+from django.contrib import admin
+from django.contrib.auth.admin import UserAdmin
+from .models import CustomUser, Schichten, Rueckmeldungen
+
+
+# Register your models here.
+class CustomUserAdmin(UserAdmin):
+    list_display = ('username', 'email', 'telefon', 'is_staff', 'is_active', 'available', 'available_from', 'available_until')
+    fieldsets = (
+        (None, {'fields': ('username', 'password')}),
+        ('Persönliche Informationen', {'fields': ('first_name', 'last_name', 'email', 'telefon', 'available', 'available_from', 'available_until')}),
+        ('Berechtigungen', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
+        ('Wichtige Daten', {'fields': ('last_login', 'date_joined')}),
+    )
+    add_fieldsets = (
+        (None, {
+            'classes': ('wide',),
+            'fields': ('username', 'email', 'password1', 'password2', 'telefon'),
+        }),
+    )
+
+admin.site.register(CustomUser, CustomUserAdmin)
+admin.site.register(Schichten)
+admin.site.register(Rueckmeldungen)

+ 6 - 0
helper/apps.py

@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class HelperConfig(AppConfig):
+    default_auto_field = 'django.db.models.BigAutoField'
+    name = 'helper'

+ 13 - 0
helper/forms.py

@@ -0,0 +1,13 @@
+from django import forms
+from django.contrib.auth.forms import UserCreationForm
+from django.contrib.auth.models import User
+
+
+class UserRegistrationForm(UserCreationForm):
+    email = forms.EmailField(max_length=100)
+    first_name = forms.CharField(max_length=30)
+    last_name = forms.CharField(max_length=30)
+
+    class Meta:
+        model = User
+        fields = ('username', 'email', 'password1', 'password2', 'first_name', 'last_name')

+ 31 - 0
helper/models.py

@@ -0,0 +1,31 @@
+from django.db import models
+from django.contrib.auth.models import AbstractUser
+
+
+# Create your models here.
+class CustomUser(AbstractUser):
+    telefon = models.CharField(max_length=15, blank=True, null=True,verbose_name="Telefon")
+    available = models.BooleanField(default=False, verbose_name="Verfügbar")
+    available_from = models.DateField(blank=True, null=True,verbose_name="Verfügbar ab")
+    available_until = models.DateField(blank=True, null=True,verbose_name="Verfügbar bis")
+
+
+class Schichten(models.Model):
+    datum = models.DateField(verbose_name="Datum")
+    beginn = models.TimeField(verbose_name="Arbeitsbeginn")
+    ende = models.TimeField(verbose_name="Voraussichtliches Arbeitsende", null=True, blank=True)
+    anzahl = models.CharField(max_length=2, verbose_name="Benötigte Helfer")
+    beschreibung = models.TextField(verbose_name="Arbeitsbeschreibung")
+
+    def __str__(self):
+        return f"{self.datum} {self.beginn} - {self.beschreibung}"
+
+
+class Rueckmeldungen(models.Model):
+    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, verbose_name="Username")
+    datum = models.ForeignKey(Schichten, on_delete=models.CASCADE, verbose_name="Datum")
+    zusage = models.BooleanField(null=True, blank=True, verbose_name="Zusage")
+    bestaetigt = models.BooleanField(null=True, blank=True, verbose_name="Bestätigt")
+
+    def __str__(self):
+        return f"{self.datum}, {self.user}"

+ 3 - 0
helper/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 13 - 0
helper/urls.py

@@ -0,0 +1,13 @@
+from django.contrib import admin
+from django.urls import path, include
+from . import views
+from .views import register, zusagen_list
+
+
+urlpatterns = [
+    path('',  views.schichten_list, name="home"),
+    path('helfer_list/',views.helfer_list, name="helfer_list"),
+    path('register/', register, name='NewUser'),
+    path('zlist/', zusagen_list, name='zlist'),
+    path('accounts/', include("django.contrib.auth.urls")),
+]

+ 71 - 0
helper/views.py

@@ -0,0 +1,71 @@
+from django.http import HttpResponse, request, HttpResponseRedirect
+from django.template import Context, loader
+from django.shortcuts import render, redirect
+from django.contrib import auth, messages
+from .models import Schichten, Rueckmeldungen, CustomUser
+from django.contrib.auth.forms import UserCreationForm
+from .forms import UserRegistrationForm
+from django.contrib.auth.models import User
+from datetime import date, datetime
+# Create your views here.
+
+
+def zusagen_list(request):
+    if request.method == 'POST':
+        datum = request.POST['datum']
+        zusagen =Rueckmeldungen.objects.filter(datum=datum)
+        schicht = Schichten.objects.filter(id=datum)
+        print(schicht)
+
+    context = {
+        'zusagen': zusagen,
+        'schicht': schicht,
+    }
+
+    return render(request, 'helper/zusagen_list.html', context)
+
+
+def schichten_list(request):
+    if request.method == 'POST':
+        datum = request.POST['datum']
+        zusage = request.POST['zusage']
+        rueckmeldungen = Rueckmeldungen.objects.create(zusage=zusage, datum_id=datum, user=request.user)
+
+    loggedin = request.user
+    if request.user.is_superuser:
+        zusagen = Rueckmeldungen.objects.all()
+        schichten = Schichten.objects.filter(datum__gte=date.today())
+    elif request.user.is_authenticated:
+        zusagen = Rueckmeldungen.objects.filter(user=loggedin)
+        schichten = Schichten.objects.exclude(rueckmeldungen__user=loggedin)
+    else:
+        zusagen = []
+        schichten = []
+
+    context = {
+        'schichten': schichten,
+        'zusagen': zusagen
+
+    }
+
+    return render(request, 'helper/home.html', context)
+
+
+def helfer_list(request):
+    helfer = User.objects.filter(is_staff=False)
+    context = {
+        'helfer': helfer
+    }
+
+    return render(request, 'helper/helfer_list.html', context)
+
+
+def register(request):
+    if request.method == 'POST':
+        form = UserRegistrationForm(request.POST)
+        if form.is_valid():
+            form.save()
+            return redirect('login')
+    else:
+        form = UserRegistrationForm()
+    return render(request, 'helper/../templates/registration/register.html', {'form': form})

+ 9 - 1
main/admin.py

@@ -1,5 +1,5 @@
 from django.contrib import admin
-from .models import Employee, Shift
+from .models import Employee, Shift, Location, Event
 
 
 class EmployeeAdmin(admin.ModelAdmin):
@@ -13,5 +13,13 @@ class ShiftAdmin(admin.ModelAdmin):
     search_fields = ('date','employee')
 
 
+class EventAdmin(admin.ModelAdmin):
+    list_display = ('date', 'name', 'event_type')
+    list_filter = ('date', 'name', 'event_type')
+    search_fields = ('date', 'name', 'location', 'event_type')
+
+
 admin.site.register(Employee, EmployeeAdmin)
 admin.site.register(Shift, ShiftAdmin)
+admin.site.register(Event, EventAdmin)
+admin.site.register(Location)

+ 7 - 1
main/forms.py

@@ -1,5 +1,5 @@
 from django import forms
-from .models import Shift, Employee
+from .models import Shift, Employee, Event
 
 class MultipleShiftForm(forms.Form):
     employees = forms.ModelMultipleChoiceField(queryset=Employee.objects.all(), widget=forms.CheckboxSelectMultiple)
@@ -13,3 +13,9 @@ class ShiftForm(forms.ModelForm):
     class Meta:
         model = Shift
         fields = ['date', 'start', 'end', 'shifttype', 'employee']
+
+
+class EventForm(forms.ModelForm):
+    class Meta:
+        model = Event
+        fields = ['date', 'name', 'event_type', 'location', 'cvd', 'cvt']

+ 33 - 0
main/migrations/0002_location_event.py

@@ -0,0 +1,33 @@
+# Generated by Django 5.0.2 on 2024-06-14 08:30
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('main', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Location',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=100)),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Event',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('date', models.DateField()),
+                ('name', models.CharField(max_length=100)),
+                ('event_type', models.CharField(choices=[('', 'None'), ('AU', 'Aufbau'), ('AB', 'Abbau'), ('UM', 'Umbau'), ('VA', 'VA-Tag'), ('ST', 'Spieltag'), ('TR', 'Training')], default='', max_length=2, null=True)),
+                ('cvd', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='cvt', to='main.employee')),
+                ('cvt', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='cvd', to='main.employee')),
+                ('location', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.location')),
+            ],
+        ),
+    ]

+ 33 - 0
main/models.py

@@ -37,3 +37,36 @@ class Shift(models.Model):
 
     def __str__(self):
         return f"{self.date} - {self.get_shifttype_display()}"
+
+
+class Location(models.Model):
+    name = models.CharField(max_length=100)
+
+    def __str__(self):
+        return self.name
+
+
+class Event(models.Model):
+    class EventType(models.TextChoices):
+        NONE = '', _('None')
+        AUFBAU = 'AU', _('Aufbau')
+        ABBAU = 'AB', _('Abbau')
+        UMBAU = 'UM', _('Umbau')
+        VATAG = 'VA', _('VA-Tag')
+        SPIELTAG = 'ST', _('Spieltag')
+        TRAINING = 'TR', _('Training')
+
+    date = models.DateField()
+    name = models.CharField(max_length=100)
+    event_type = models.CharField(
+        max_length=2,
+        choices=EventType.choices,
+        default=EventType.NONE,
+        null=True,
+    )
+    location = models.ForeignKey(Location, on_delete=models.CASCADE)
+    cvd = models.ForeignKey(Employee, related_name='cvt', on_delete=models.SET_NULL, null=True, blank=True)
+    cvt = models.ForeignKey(Employee, related_name='cvd', on_delete=models.SET_NULL, null=True, blank=True)
+
+    def __str__(self):
+        return f"{self.date} - {self.name}"

+ 5 - 1
main/urls.py

@@ -1,9 +1,13 @@
 from django.urls import path
-from .views import create_multiple_shifts, current_week_shifts, edit_shift, delete_shift
+from .views import create_multiple_shifts, current_week_shifts, edit_shift, delete_shift, delete_event, edit_event, create_event, public
 
 urlpatterns = [
     path('create-multiple-shifts/', create_multiple_shifts, name='create_multiple_shifts'),
+    path('create-event/', create_event, name='create_event'),
     path('current-week-shifts/', current_week_shifts, name='current_week_shifts'),
     path('edit-shift/<int:pk>/', edit_shift, name='edit_shift'),
     path('delete-shift/<int:pk>/', delete_shift, name='delete_shift'),
+    path('edit-event/<int:pk>/', edit_event, name='edit_event'),
+    path('delete-event/<int:pk>/', delete_event, name='delete_event'),
+    path('public/', public, name='public'),
 ]

+ 143 - 4
main/views.py

@@ -1,6 +1,6 @@
 from django.shortcuts import render, redirect, get_object_or_404
-from .forms import MultipleShiftForm, ShiftForm
-from .models import Shift, Employee
+from .forms import MultipleShiftForm, ShiftForm, EventForm
+from .models import Shift, Employee, Location, Event
 from django.utils.timezone import datetime, timedelta
 from django.utils import timezone
 import calendar
@@ -36,6 +36,36 @@ def create_multiple_shifts(request):
     return render(request, 'main/create_multiple_shifts.html', {'form': form})
 
 
+def create_event(request):
+    date_str = request.GET.get('date')
+    initial_data = {}
+    if date_str:
+        initial_data['date'] = date_str
+
+    if request.method == 'POST':
+        form = EventForm(request.POST)
+        if form.is_valid():
+            name = form.cleaned_data['name']
+            date = form.cleaned_data['date']
+            event_type = form.cleaned_data['event_type']
+            location = form.cleaned_data['location']
+            cvd = form.cleaned_data['cvd']
+            cvt = form.cleaned_data['cvt']
+            Event.objects.create(
+                name=name,
+                date=date,
+                event_type=event_type,
+                location=location,
+                cvd=cvd,
+                cvt=cvt
+                )
+            return redirect('current_week_shifts')  # Annahme, dass Sie eine Erfolgsmeldung anzeigen möchten
+    else:
+        form = EventForm(initial=initial_data)
+
+    return render(request, 'main/create_event.html', {'form': form})
+
+
 def current_week_shifts(request):
     # Standardmäßig die aktuelle Woche anzeigen
     today = timezone.now().date()
@@ -61,19 +91,33 @@ def current_week_shifts(request):
 
     # Initialisiere ein Dictionary für die Schichten der Mitarbeiter
     shifts_by_employee = {}
+    events_by_location = {}
     employees = Employee.objects.all()
+    locations = Location.objects.all()
+
     for employee in employees:
         shifts_by_employee[employee] = {day: None for day in range(7)}
 
-    # Hole alle Schichten für die aktuelle Woche
+    for location in locations:
+        events_by_location[location] = {day: None for day in range(7)}
+
+        # Hole alle Schichten für die aktuelle Woche
     shifts = Shift.objects.filter(date__range=[start_of_week, end_of_week])
 
+    events = Event.objects.filter(date__range=[start_of_week, end_of_week])
+
+    print(events)
     # Fülle das Dictionary mit den Schichtdaten
     for shift in shifts:
         employee = shift.employee
         day_of_week = (shift.date - start_of_week).days
         shifts_by_employee[employee][day_of_week] = shift
 
+    for event in events:
+        location = event.location
+        day_of_week = (event.date - start_of_week).days
+        events_by_location[location][day_of_week] = event
+
     # Bereite die Daten der Woche für das Template vor
     week_dates = [(start_of_week + timedelta(days=i)).strftime("%d.%m.%Y") for i in range(7)]
     days_of_week = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
@@ -81,6 +125,7 @@ def current_week_shifts(request):
 
     context = {
         'shifts_by_employee': shifts_by_employee,
+        'events_by_location': events_by_location,
         'start_of_week': start_of_week,
         'end_of_week': end_of_week,
         'days_with_dates': days_with_dates,
@@ -89,9 +134,82 @@ def current_week_shifts(request):
         'next_week': next_week.strftime('%Y-%m-%d'),
         'calendar_week': calendar_week,
     }
-
+    print(shifts_by_employee)
+    print(events_by_location)
     return render(request, 'main/current_week_shifts.html', context)
 
+
+def public(request):
+    # Standardmäßig die aktuelle Woche anzeigen
+    today = timezone.now().date()
+
+    # Überprüfen, ob ein Startdatum in der URL angegeben ist
+    start_date_str = request.GET.get('start_date')
+    if start_date_str:
+        try:
+            start_of_week = datetime.strptime(start_date_str, '%Y-%m-%d').date()
+        except ValueError:
+            start_of_week = today - timedelta(days=today.weekday())  # Fallback auf die aktuelle Woche bei Fehler
+    else:
+        start_of_week = today - timedelta(days=today.weekday())  # Montag der aktuellen Woche
+
+    end_of_week = start_of_week + timedelta(days=6)  # Sonntag der aktuellen Woche
+
+    # Berechnung für die nächste und vorherige Woche
+    previous_week = start_of_week - timedelta(days=7)
+    next_week = start_of_week + timedelta(days=7)
+
+    # Berechnung der Kalenderwoche
+    calendar_week = start_of_week.isocalendar()[1]
+
+    # Initialisiere ein Dictionary für die Schichten der Mitarbeiter
+    shifts_by_employee = {}
+    events_by_location = {}
+    employees = Employee.objects.all()
+    locations = Location.objects.all()
+
+    for employee in employees:
+        shifts_by_employee[employee] = {day: None for day in range(7)}
+
+    for location in locations:
+        events_by_location[location] = {day: None for day in range(7)}
+
+        # Hole alle Schichten für die aktuelle Woche
+    shifts = Shift.objects.filter(date__range=[start_of_week, end_of_week])
+
+    events = Event.objects.filter(date__range=[start_of_week, end_of_week])
+
+    print(events)
+    # Fülle das Dictionary mit den Schichtdaten
+    for shift in shifts:
+        employee = shift.employee
+        day_of_week = (shift.date - start_of_week).days
+        shifts_by_employee[employee][day_of_week] = shift
+
+    for event in events:
+        location = event.location
+        day_of_week = (event.date - start_of_week).days
+        events_by_location[location][day_of_week] = event
+
+    # Bereite die Daten der Woche für das Template vor
+    week_dates = [(start_of_week + timedelta(days=i)).strftime("%d.%m.%Y") for i in range(7)]
+    days_of_week = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']
+    days_with_dates = list(zip(days_of_week, week_dates))
+
+    context = {
+        'shifts_by_employee': shifts_by_employee,
+        'events_by_location': events_by_location,
+        'start_of_week': start_of_week,
+        'end_of_week': end_of_week,
+        'days_with_dates': days_with_dates,
+        'range_days': range(7),
+        'previous_week': previous_week.strftime('%Y-%m-%d'),
+        'next_week': next_week.strftime('%Y-%m-%d'),
+        'calendar_week': calendar_week,
+    }
+    return render(request, 'main/public.html', context)
+
+
 def edit_shift(request, pk):
     shift = get_object_or_404(Shift, pk=pk)
     if request.method == 'POST':
@@ -103,9 +221,30 @@ def edit_shift(request, pk):
         form = ShiftForm(instance=shift)
     return render(request, 'main/edit_shift.html', {'form': form, 'shift': shift})
 
+
+def edit_event(request, pk):
+    event = get_object_or_404(Event, pk=pk)
+    if request.method == 'POST':
+        form = EventForm(request.POST, instance=event)
+        if form.is_valid():
+            form.save()
+            return redirect('current_week_shifts')
+    else:
+        form = EventForm(instance=event)
+    return render(request, 'main/edit_event.html', {'form': form, 'event': event})
+
+
 def delete_shift(request, pk):
     shift = get_object_or_404(Shift, pk=pk)
     if request.method == 'POST':
         shift.delete()
         return redirect('current_week_shifts')
     return render(request, 'main/delete_shift.html', {'shift': shift})
+
+
+def delete_event(request, pk):
+    event = get_object_or_404(Event, pk=pk)
+    if request.method == 'POST':
+        event.delete()
+        return redirect('current_week_shifts')
+    return render(request, 'main/delete_event.html', {'event': event})

+ 21 - 0
templates/main/create_event.html

@@ -0,0 +1,21 @@
+{% load bootstrap5 %}
+<!DOCTYPE html>
+<html lang="de">
+<head>
+    <meta charset="UTF-8">
+    <title>Event erstellen</title>
+    {% bootstrap_css %}
+</head>
+<body>
+    <div class="container">
+        <h2>Event erstellen</h2>
+        <form method="post">
+            {% csrf_token %}
+            {% bootstrap_form form %}
+            <button type="submit" class="btn btn-primary">Event erstellen</button>
+            <a href="{% url 'current_week_shifts' %}" class="btn btn-secondary">Abbrechen</a>
+        </form>
+    </div>
+    {% bootstrap_javascript %}
+</body>
+</html>

+ 46 - 7
templates/main/current_week_shifts.html

@@ -6,6 +6,7 @@
 <html lang="de">
 <head>
     <meta charset="UTF-8">
+    <meta http-equiv="refresh" content="120; URL=/current-week-shifts/" >
     <title>Schichten der aktuellen Woche</title>
     <link rel="icon" href="{% static 'favicon.png' %}">
     {% bootstrap_css %}
@@ -19,6 +20,7 @@
         .shift-none {
             background-color: white !important;
             text-align: center;
+            cursor: pointer;
         }
         .shift-vacation {
             background-color: blue !important;
@@ -53,6 +55,7 @@
         }
         .employee-name {
             text-align: left;
+            font-weight: bold;
             width: 150px; /* Set a fixed width for the employee column */
         }
         .day-name {
@@ -62,6 +65,8 @@
         .table th, .table td {
             vertical-align: middle;
             width: 100px; /* Set a fixed width for all other columns */
+            padding: 4px; /* Reduce padding to decrease row height */
+            line-height: 1.2; /* Adjust line height to decrease row height */
         }
         .custom-heading {
             margin: 0; /* Remove margin to eliminate extra space */
@@ -76,29 +81,58 @@
 <body>
     <div class="buttons-container">
         <a href="?start_date={{ previous_week }}" class="btn btn-primary">Eine Woche zurück</a>
+        <a href="/current-week-shifts/" class="btn btn-primary">Aktuelle Woche</a>
         <a href="?start_date={{ next_week }}" class="btn btn-primary">Eine Woche vorwärts</a>
     </div>
     <div class="container-fluid">
-        <h4 class="custom-heading">Dienstplan für KW {{ calendar_week }} - {{ start_of_week }} bis {{ end_of_week }}</h4>
+        <h4 class="custom-heading">Dienstplan für KW {{ calendar_week }}</h4>
         <div class="table-responsive">
             <table class="table table-bordered table-hover w-100">
                 <thead class="table-dark">
                     <tr>
-                        <th class="employee-name">Employee</th>
+                        <th class="employee-name">Veranstaltungen</th>
                         {% for day, date in days_with_dates %}
                         <th class="day-name">{{ day }} {{ date }}</th>
                         {% endfor %}
                     </tr>
                 </thead>
                 <tbody>
+                    {% for location, events in events_by_location.items %}
+                    <tr>
+                        <td class="employee-name">{{ location.name }}</td>
+                        {% for day, date in days_with_dates %}
+                            {% with event=events|get_item:forloop.counter0 %}
+                                {% if event == None %}
+                                    <td class="shift-none" onclick="window.location.href='{% url 'create_event' %}?date={{ date }}'"></td>
+                                {% else %}
+                                    <td class="shift-none" onclick="window.location.href='{% url 'edit_event' pk=event.id %}'" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" title="Name: {{ event.name }}<br> Location: {{ event.location }}<br> CVD: {{ event.cvd }}<br> CVT: {{ event.cvt }}">
+                                            {% if event.name %}
+                                                {{ event.name }}
+                                            {% else %}
+                                                F
+                                            {% endif %}
+                                    </td>
+                                {% endif %}
+                            {% endwith %}
+                        {% endfor %}
+                    </tr>
+                    {% endfor %}
+                </tbody>
+                <tbody>
+                    <tr class="table-dark">
+                        <th class="employee-name">Mitarbeiter</th>
+                        {% for day, date in days_with_dates %}
+                        <th class="day-name">{{ day }} {{ date }}</th>
+                        {% endfor %}
+                    </tr>
                     {% for employee, shifts in shifts_by_employee.items %}
                     <tr>
                         <td class="employee-name">{{ employee.name }}</td>
                         {% for day, date in days_with_dates %}
                             {% with shift=shifts|get_item:forloop.counter0 %}
                                 {% if shift == None %}
-                                    <td class="shift-none">
-                                        <a href="{% url 'create_multiple_shifts' %}?date={{ date }}">F</a>
+                                    <td class="shift-none" onclick="window.location.href='{% url 'create_multiple_shifts' %}?date={{ date }}'">
+                                        F
                                     </td>
                                 {% else %}
                                     <td class="
@@ -111,14 +145,12 @@
                                         {% else %}
                                             shift-other
                                         {% endif %}
-                                    ">
-                                        <a href="{% url 'edit_shift' pk=shift.id %}">
+                                    " onclick="window.location.href='{% url 'edit_shift' pk=shift.id %}'">
                                             {% if shift.start and shift.end %}
                                                 {{ shift.start|time:"H:i" }} - {{ shift.end|time:"H:i" }}
                                             {% else %}
                                                 {{ shift.get_shifttype_display }}
                                             {% endif %}
-                                        </a>
                                     </td>
                                 {% endif %}
                             {% endwith %}
@@ -130,5 +162,12 @@
         </div>
     </div>
     {% bootstrap_javascript %}
+    <script>
+        // Initialize all tooltips on the page
+        var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
+        var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
+            return new bootstrap.Tooltip(tooltipTriggerEl)
+        })
+    </script>
 </body>
 </html>

+ 22 - 0
templates/main/delete_event.html

@@ -0,0 +1,22 @@
+{% load bootstrap5 %}
+
+<!DOCTYPE html>
+<html lang="de">
+<head>
+    <meta charset="UTF-8">
+    <title>Event löschen</title>
+    {% bootstrap_css %}
+</head>
+<body>
+    <div class="container">
+        <h2>Event löschen</h2>
+        <p>Möchten Sie die VA {{ event.name }} am {{ event.date }} wirklich löschen?</p>
+        <form method="post">
+            {% csrf_token %}
+            <button type="submit" class="btn btn-danger">Löschen</button>
+            <a href="{% url 'current_week_shifts' %}" class="btn btn-secondary">Abbrechen</a>
+        </form>
+    </div>
+    {% bootstrap_javascript %}
+</body>
+</html>

+ 25 - 0
templates/main/edit_event.html

@@ -0,0 +1,25 @@
+{% load bootstrap5 %}
+<!DOCTYPE html>
+<html lang="de">
+<head>
+    <meta charset="UTF-8">
+    <title>Event bearbeiten</title>
+    {% bootstrap_css %}
+</head>
+<body>
+    <div class="container">
+        <h2>Event bearbeiten</h2>
+        <form method="post">
+            {% csrf_token %}
+            {% bootstrap_form form %}
+            <button type="submit" class="btn btn-primary">Speichern</button>
+            <a href="{% url 'current_week_shifts' %}" class="btn btn-secondary">Abbrechen</a>
+        </form>
+        <form method="post" action="{% url 'delete_event' pk=event.id %}" class="mt-3">
+            {% csrf_token %}
+            <button type="submit" class="btn btn-danger">Löschen</button>
+        </form>
+    </div>
+    {% bootstrap_javascript %}
+</body>
+</html>

+ 173 - 0
templates/main/public.html

@@ -0,0 +1,173 @@
+{% load static %}
+{% load custom_tags %}
+{% load bootstrap5 %}
+
+<!DOCTYPE html>
+<html lang="de">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="refresh" content="120; URL=/current-week-shifts/" >
+    <title>Schichten der aktuellen Woche</title>
+    <link rel="icon" href="{% static 'favicon.png' %}">
+    {% bootstrap_css %}
+    <style>
+        body {
+            font-family: Tahoma, sans-serif;
+            margin: 0;
+            padding: 0;
+            font-size: 10px; /* Set the base font size */
+        }
+        .shift-none {
+            background-color: white !important;
+            text-align: center;
+            cursor: pointer;
+        }
+        .shift-vacation {
+            background-color: blue !important;
+            color: white !important;
+            text-align: center;
+        }
+        .shift-sick {
+            background-color: yellow !important;
+            text-align: center;
+        }
+        .shift-other {
+            background-color: gray !important;
+            color: white !important;
+            text-align: center;
+        }
+        .buttons-container {
+            display: flex;
+            justify-content: space-between;
+            padding: 10px;
+            background-color: #f8f9fa;
+            border-bottom: 1px solid #dee2e6;
+        }
+        .container-fluid {
+            padding-top: 10px; /* Reduce the padding to remove extra space */
+        }
+        a {
+            color: black;
+            text-decoration: none;
+        }
+        a:hover {
+            color: black;
+        }
+        .employee-name {
+            text-align: left;
+            font-weight: bold;
+            width: 150px; /* Set a fixed width for the employee column */
+        }
+        .day-name {
+            text-align: center;
+            width: 150px; /* Set a fixed width for the employee column */
+        }
+        .table th, .table td {
+            vertical-align: middle;
+            width: 100px; /* Set a fixed width for all other columns */
+            padding: 4px; /* Reduce padding to decrease row height */
+            line-height: 1.2; /* Adjust line height to decrease row height */
+        }
+        .custom-heading {
+            margin: 0; /* Remove margin to eliminate extra space */
+        }
+        @media print {
+            .buttons-container {
+                display: none; /* Hide the buttons when printing */
+            }
+        }
+    </style>
+</head>
+<body>
+    <div class="buttons-container">
+        <a href="?start_date={{ previous_week }}" class="btn btn-primary">Eine Woche zurück</a>
+        <a href="/current-week-shifts/" class="btn btn-primary">Aktuelle Woche</a>
+        <a href="?start_date={{ next_week }}" class="btn btn-primary">Eine Woche vorwärts</a>
+    </div>
+    <div class="container-fluid">
+        <h4 class="custom-heading">Dienstplan für KW {{ calendar_week }}</h4>
+        <div class="table-responsive">
+            <table class="table table-bordered table-hover w-100">
+                <thead class="table-dark">
+                    <tr>
+                        <th class="employee-name">Veranstaltungen</th>
+                        {% for day, date in days_with_dates %}
+                        <th class="day-name">{{ day }} {{ date }}</th>
+                        {% endfor %}
+                    </tr>
+                </thead>
+                <tbody>
+                    {% for location, events in events_by_location.items %}
+                    <tr>
+                        <td class="employee-name">{{ location.name }}</td>
+                        {% for day, date in days_with_dates %}
+                            {% with event=events|get_item:forloop.counter0 %}
+                                {% if event == None %}
+                                    <td class="shift-none" onclick="window.location.href='{% url 'create_event' %}?date={{ date }}'"></td>
+                                {% else %}
+                                    <td class="shift-none" onclick="window.location.href='{% url 'edit_event' pk=event.id %}'" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-html="true" title="Name: {{ event.name }}<br> Location: {{ event.location }}<br> CVD: {{ event.cvd }}<br> CVT: {{ event.cvt }}">
+                                            {% if event.name %}
+                                                {{ event.name }}
+                                            {% else %}
+                                                F
+                                            {% endif %}
+                                    </td>
+                                {% endif %}
+                            {% endwith %}
+                        {% endfor %}
+                    </tr>
+                    {% endfor %}
+                </tbody>
+                <tbody>
+                    <tr class="table-dark">
+                        <th class="employee-name">Mitarbeiter</th>
+                        {% for day, date in days_with_dates %}
+                        <th class="day-name">{{ day }} {{ date }}</th>
+                        {% endfor %}
+                    </tr>
+                    {% for employee, shifts in shifts_by_employee.items %}
+                    <tr>
+                        <td class="employee-name">{{ employee.name }}</td>
+                        {% for day, date in days_with_dates %}
+                            {% with shift=shifts|get_item:forloop.counter0 %}
+                                {% if shift == None %}
+                                    <td class="shift-none" onclick="window.location.href='{% url 'create_multiple_shifts' %}?date={{ date }}'">
+                                        F
+                                    </td>
+                                {% else %}
+                                    <td class="
+                                        {% if shift.start and shift.end %}
+                                            shift-none
+                                        {% elif shift.shifttype == 'U' %}
+                                            shift-vacation
+                                        {% elif shift.shifttype == 'K' %}
+                                            shift-sick
+                                        {% else %}
+                                            shift-other
+                                        {% endif %}
+                                    " onclick="window.location.href='{% url 'edit_shift' pk=shift.id %}'">
+                                            {% if shift.start and shift.end %}
+                                                {{ shift.start|time:"H:i" }} - {{ shift.end|time:"H:i" }}
+                                            {% else %}
+                                                {{ shift.get_shifttype_display }}
+                                            {% endif %}
+                                    </td>
+                                {% endif %}
+                            {% endwith %}
+                        {% endfor %}
+                    </tr>
+                    {% endfor %}
+                </tbody>
+            </table>
+        </div>
+    </div>
+    {% bootstrap_javascript %}
+    <script>
+        // Initialize all tooltips on the page
+        var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
+        var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
+            return new bootstrap.Tooltip(tooltipTriggerEl)
+        })
+    </script>
+</body>
+</html>