Browse Source

20240613_1600

Rene 1 year ago
parent
commit
c51c359a79

+ 6 - 2
AD/settings.py

@@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/5.0/ref/settings/
 """
 
 from pathlib import Path
+import os
 
 # Build paths inside the project like this: BASE_DIR / 'subdir'.
 BASE_DIR = Path(__file__).resolve().parent.parent
@@ -37,7 +38,7 @@ INSTALLED_APPS = [
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
-    'bootstrap5'
+    'bootstrap5',
     'main',
 ]
 
@@ -118,7 +119,10 @@ USE_TZ = True
 # Static files (CSS, JavaScript, Images)
 # https://docs.djangoproject.com/en/5.0/howto/static-files/
 
-STATIC_URL = 'static/'
+STATIC_URL = '/static/'
+STATICFILES_DIRS = [
+    BASE_DIR / "static",
+]
 
 # Default primary key field type
 # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field

BIN
db.sqlite3


+ 7 - 1
main/forms.py

@@ -3,7 +3,13 @@ from .models import Shift, Employee
 
 class MultipleShiftForm(forms.Form):
     employees = forms.ModelMultipleChoiceField(queryset=Employee.objects.all(), widget=forms.CheckboxSelectMultiple)
-    date = forms.DateField(widget=forms.SelectDateWidget)
+    date = forms.DateField(widget=forms.DateInput)
     start = forms.TimeField(required=False, widget=forms.TimeInput(format='%H:%M'))
     end = forms.TimeField(required=False, widget=forms.TimeInput(format='%H:%M'))
     shifttype = forms.ChoiceField(choices=Shift.ShiftType.choices)
+
+
+class ShiftForm(forms.ModelForm):
+    class Meta:
+        model = Shift
+        fields = ['date', 'start', 'end', 'shifttype', 'employee']

+ 0 - 0
main/templatetags/__init__.py


+ 7 - 0
main/templatetags/custom_tags.py

@@ -0,0 +1,7 @@
+from django import template
+
+register = template.Library()
+
+@register.filter
+def get_item(dictionary, key):
+    return dictionary.get(key)

+ 4 - 1
main/urls.py

@@ -1,6 +1,9 @@
 from django.urls import path
-from .views import create_multiple_shifts
+from .views import create_multiple_shifts, current_week_shifts, edit_shift, delete_shift
 
 urlpatterns = [
     path('create-multiple-shifts/', create_multiple_shifts, name='create_multiple_shifts'),
+    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'),
 ]

+ 87 - 4
main/views.py

@@ -1,9 +1,17 @@
-from django.shortcuts import render, redirect
-from .forms import MultipleShiftForm
+from django.shortcuts import render, redirect, get_object_or_404
+from .forms import MultipleShiftForm, ShiftForm
 from .models import Shift, Employee
+from django.utils.timezone import datetime, timedelta
+from django.utils import timezone
+import calendar
 
 
 def create_multiple_shifts(request):
+    date_str = request.GET.get('date')
+    initial_data = {}
+    if date_str:
+        initial_data['date'] = date_str
+
     if request.method == 'POST':
         form = MultipleShiftForm(request.POST)
         if form.is_valid():
@@ -21,8 +29,83 @@ def create_multiple_shifts(request):
                     end=end,
                     shifttype=shifttype
                 )
-            return redirect('shift_success')  # Annahme, dass Sie eine Erfolgsmeldung anzeigen möchten
+            return redirect('current_week_shifts')  # Annahme, dass Sie eine Erfolgsmeldung anzeigen möchten
     else:
-        form = MultipleShiftForm()
+        form = MultipleShiftForm(initial=initial_data)
 
     return render(request, 'main/create_multiple_shifts.html', {'form': form})
+
+
+def current_week_shifts(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 = {}
+    employees = Employee.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
+    shifts = Shift.objects.filter(date__range=[start_of_week, end_of_week])
+
+    # 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
+
+    # 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,
+        '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/current_week_shifts.html', context)
+
+def edit_shift(request, pk):
+    shift = get_object_or_404(Shift, pk=pk)
+    if request.method == 'POST':
+        form = ShiftForm(request.POST, instance=shift)
+        if form.is_valid():
+            form.save()
+            return redirect('current_week_shifts')
+    else:
+        form = ShiftForm(instance=shift)
+    return render(request, 'main/edit_shift.html', {'form': form, 'shift': shift})
+
+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})

+ 86 - 0
static/main/css/styles.css

@@ -0,0 +1,86 @@
+/* Basic reset */
+* {
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
+}
+
+body {
+    font-family: 'Arial', sans-serif;
+    line-height: 1.6;
+    padding: 20px;
+    background-color: #f4f4f4;
+}
+
+header {
+    background: #333;
+    color: #fff;
+    padding-top: 30px;
+    min-height: 70px;
+    border-bottom: #0779e4 3px solid;
+}
+
+header a {
+    color: #fff;
+    text-decoration: none;
+    text-transform: uppercase;
+    margin: 0 15px;
+}
+
+header li {
+    display: inline;
+    padding: 0 20px;
+}
+
+header nav {
+    text-align: center;
+}
+
+main {
+    padding: 20px;
+}
+
+h2 {
+    color: #333;
+}
+
+table {
+    width: 100%;
+    margin-top: 20px;
+    border-collapse: collapse;
+}
+
+table, th, td {
+    border: 1px solid #bbbbbb;
+    padding: 10px;
+    text-align: left;
+}
+
+th {
+    background-color: #f8f8f8;
+}
+
+form {
+    background-color: #fff;
+    padding: 20px;
+    border-radius: 5px;
+}
+
+form p, form h3 {
+    margin: 15px 0;
+}
+
+button, input[type="submit"] {
+    background: #0d6efd;
+    color: #fff;
+    border: 0;
+    padding: 10px 20px;
+    cursor: pointer;
+    border-radius: 5px;
+}
+
+button:hover, input[type="submit"]:hover {
+    background: #0b5ed7;
+}
+
+/* Add any additional styles as needed */

+ 1 - 1
templates/base.html

@@ -5,7 +5,7 @@
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <title>{% block title %}Shift Manager{% endblock title %}</title>
-    <link rel="stylesheet" href="{% static 'roster/css/styles.css' %}">
+    <link rel="stylesheet" href="{% static 'main/css/styles.css' %}">
     <link rel="icon"href="{% static 'favicon.png' %}">
     {% load bootstrap5 %}
     {% bootstrap_css %}

+ 15 - 8
templates/main/create_multiple_shifts.html

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

+ 134 - 0
templates/main/current_week_shifts.html

@@ -0,0 +1,134 @@
+{% load static %}
+{% load custom_tags %}
+{% load bootstrap5 %}
+
+<!DOCTYPE html>
+<html lang="de">
+<head>
+    <meta charset="UTF-8">
+    <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;
+        }
+        .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;
+            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 */
+        }
+        .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="?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>
+        <div class="table-responsive">
+            <table class="table table-bordered table-hover w-100">
+                <thead class="table-dark">
+                    <tr>
+                        <th class="employee-name">Employee</th>
+                        {% for day, date in days_with_dates %}
+                        <th class="day-name">{{ day }} {{ date }}</th>
+                        {% endfor %}
+                    </tr>
+                </thead>
+                <tbody>
+                    {% 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>
+                                {% 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 %}
+                                    ">
+                                        <a 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 %}
+                        {% endfor %}
+                    </tr>
+                    {% endfor %}
+                </tbody>
+            </table>
+        </div>
+    </div>
+    {% bootstrap_javascript %}
+</body>
+</html>

+ 22 - 0
templates/main/delete_shift.html

@@ -0,0 +1,22 @@
+{% load bootstrap5 %}
+
+<!DOCTYPE html>
+<html lang="de">
+<head>
+    <meta charset="UTF-8">
+    <title>Schicht löschen</title>
+    {% bootstrap_css %}
+</head>
+<body>
+    <div class="container">
+        <h2>Schicht löschen</h2>
+        <p>Möchten Sie die Schicht von {{ shift.employee.name }} am {{ shift.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_shift.html

@@ -0,0 +1,25 @@
+{% load bootstrap5 %}
+<!DOCTYPE html>
+<html lang="de">
+<head>
+    <meta charset="UTF-8">
+    <title>Schicht bearbeiten</title>
+    {% bootstrap_css %}
+</head>
+<body>
+    <div class="container">
+        <h2>Schicht 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_shift' pk=shift.id %}" class="mt-3">
+            {% csrf_token %}
+            <button type="submit" class="btn btn-danger">Löschen</button>
+        </form>
+    </div>
+    {% bootstrap_javascript %}
+</body>
+</html>