feat: reformatted some templates and new filter for TicketListView

This commit is contained in:
2025-05-28 23:17:36 +02:00
parent 84ac0c1bac
commit 49e8a794af
5 changed files with 334 additions and 278 deletions

View File

@@ -1,45 +1,53 @@
{% extends "ticketsystem/base.html" %}
{% block content %}
<style>
.home-container {
max-width: 800px;
margin: 3rem auto;
text-align: center;
font-family: sans-serif;
}
.home-container h1 {
font-size: 2rem;
margin-bottom: 1rem;
}
.actions {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 1rem;
margin-top: 2rem;
}
.actions a {
padding: 1rem 2rem;
background: #007bff;
color: white;
border-radius: 8px;
text-decoration: none;
font-weight: bold;
transition: background 0.2s ease;
}
.actions a:hover {
background: #0056b3;
}
</style>
<div class="home-container">
<h1>Willkommen im Korrekturmanagementsystem 🎫</h1>
<p>Was möchten Sie tun?</p>
<div class="actions">
<a href="{% url 'ticket-list' %}">📄 Alle Tickets anzeigen</a>
<a href="{% url 'create' %}"> Neues Ticket erstellen</a>
<a href="{% url 'ticket-list' %}?status=open">📂 Offene Tickets</a>
<div class="max-w-4xl mx-auto px-4 py-12">
<!-- Header -->
<div class="text-center mb-12">
<div class="text-6xl mb-4">🎫</div>
<h1 class="text-4xl font-bold text-gray-900 mb-4">Willkommen im Ticketsystem</h1>
<p class="text-lg text-gray-600 mb-2">Verwalte deine Aufgaben und Tickets effizient</p>
<p class="text-gray-500">Was möchten Sie tun?</p>
</div>
<!-- Quick Actions -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-12">
<!-- Alle Tickets -->
<a href="{% url 'ticket-list' %}"
class="bg-white rounded-lg shadow-md p-6 text-center hover:shadow-lg transition-shadow duration-200 border border-gray-200">
<div class="text-3xl mb-3">📄</div>
<h3 class="text-lg font-bold text-gray-900 mb-2">Alle Tickets</h3>
<p class="text-sm text-gray-600">Übersicht aller Tickets anzeigen</p>
</a>
<!-- Neues Ticket -->
<a href="{% url 'create' %}"
class="bg-green-50 rounded-lg shadow-md p-6 text-center hover:shadow-lg transition-shadow duration-200 border border-green-200">
<div class="text-3xl mb-3"></div>
<h3 class="text-lg font-bold text-green-800 mb-2">Neues Ticket</h3>
<p class="text-sm text-green-600">Ein neues Ticket erstellen</p>
</a>
<!-- Offene Tickets -->
<a href="{% url 'ticket-list' %}?status=open"
class="bg-blue-50 rounded-lg shadow-md p-6 text-center hover:shadow-lg transition-shadow duration-200 border border-blue-200">
<div class="text-3xl mb-3">📂</div>
<h3 class="text-lg font-bold text-blue-800 mb-2">Offene Tickets</h3>
<p class="text-sm text-blue-600">Nur offene Tickets anzeigen</p>
</a>
</div>
<div class="bg-gray-50 rounded-lg p-6 text-center">
<h2 class="text-xl font-bold text-gray-900 mb-4">📊 Übersicht</h2>
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div class="bg-white rounded-lg p-4 shadow-sm">
<div class="text-2xl font-bold text-blue-600 mb-1">{{ total_tickets|default:"0" }}</div>
<div class="text-sm text-gray-600">Tickets insgesamt</div>
</div>
<div class="bg-white rounded-lg p-4 shadow-sm">
<div class="text-2xl font-bold text-red-600 mb-1">{{ open_tickets|default:"0" }}</div>
<div class="text-sm text-gray-600">Offene Tickets</div>
</div>
<div class="bg-white rounded-lg p-4 shadow-sm">
<div class="text-2xl font-bold text-green-600 mb-1">{{ closed_tickets|default:"0" }}</div>
<div class="text-sm text-gray-600">Erledigte Tickets</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -1,196 +1,229 @@
{% extends "ticketsystem/base.html" %}
{% block content %}
<!-- Messages -->
{% if messages %}
<div class="max-w-6xl mx-auto px-4 pt-4">
{% for message in messages %}
<div class="mb-4 p-3 rounded {% if message.tags == 'error' %}bg-red-100 text-red-700{% elif message.tags == 'success' %}bg-green-100 text-green-700{% else %}bg-yellow-100 text-yellow-700{% endif %}">
{{ message }}
</div>
{% endfor %}
</div>
{% endif %}
<div class="max-w-6xl mx-auto px-4 py-6">
<!-- Header -->
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-6">
<div>
<h1 class="text-3xl font-bold text-gray-900 mb-2">🎫 Ticket-Übersicht</h1>
<p class="text-gray-600">Verwalte und verfolge alle deine Tickets</p>
<!-- Messages -->
{% if messages %}
<div class="max-w-6xl mx-auto px-4 pt-4">
{% for message in messages %}
<div class="mb-4 p-3 rounded {% if message.tags == 'error' %}bg-red-100 text-red-700{% elif message.tags == 'success' %}bg-green-100 text-green-700{% else %}bg-yellow-100 text-yellow-700{% endif %}">
{{ message }}
</div>
{% endfor %}
</div>
<div class="mt-4 sm:mt-0">
<a href="{% url 'create' %}"
class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded font-medium">
Neues Ticket erstellen
</a>
</div>
</div>
<!-- Filter und Suche -->
<div class="bg-white rounded-lg shadow p-4 mb-6">
<div class="flex flex-col lg:flex-row gap-4">
<!-- Status Filter -->
<div class="flex-1">
<form method="get">
<label class="block text-sm font-medium mb-1">Status:</label>
<select name="status" onchange="this.form.submit()"
class="w-full p-2 border border-gray-300 rounded shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
<option value="">Alle Status</option>
<option value="open" {% if selected_status == "open" %}selected{% endif %}>🔴 Offen</option>
<option value="in_progress" {% if selected_status == "in_progress" %}selected{% endif %}>🟡 In Bearbeitung</option>
<option value="closed" {% if selected_status == "closed" %}selected{% endif %}>🟢 Erledigt</option>
</select>
</form>
</div>
<!-- Suche -->
<div class="flex-1 lg:flex-2">
<form method="get">
<label class="block text-sm font-medium mb-1">Suche:</label>
<div class="flex">
<input type="text" name="q" value="{{ search_query }}"
placeholder="Titel oder Beschreibung durchsuchen..."
class="flex-1 p-2 border border-gray-300 rounded-l shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
{% if selected_status %}
<input type="hidden" name="status" value="{{ selected_status }}">
{% endif %}
<button type="submit"
class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-r">
🔍
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Suchergebnisse Info -->
{% if search_query %}
<div class="mb-4 p-3 bg-blue-100 border-l-4 border-blue-400 rounded">
<span class="font-medium">Suchergebnisse für:</span> „{{ search_query }}"
<a href="?" class="ml-4 text-blue-600 hover:text-blue-800">Suche zurücksetzen</a>
</div>
{% endif %}
<!-- Ticket Tabelle -->
{% if tickets %}
<div class="bg-white rounded-lg shadow overflow-hidden">
<table class="w-full">
<thead class="bg-blue-600 text-white">
<tr>
<th class="px-4 py-3 text-center text-sm font-bold">#</th>
<th class="px-4 py-3 text-left text-sm font-bold">Titel</th>
<th class="px-4 py-3 text-center text-sm font-bold">Status</th>
<th class="px-4 py-3 text-center text-sm font-bold">Priorität</th>
<th class="px-4 py-3 text-left text-sm font-bold">Zugewiesen an</th>
<th class="px-4 py-3 text-center text-sm font-bold">Erstellt</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
{% for ticket in tickets %}
<tr class="hover:bg-gray-50">
<td class="px-4 py-3 text-center text-sm font-bold text-gray-500">
#{{ ticket.id }}
</td>
<td class="px-4 py-3">
<a href="{% url 'detail' ticket.pk %}"
class="font-bold text-blue-600 hover:text-blue-800 hover:underline">
{{ ticket.title }}
<div class="max-w-6xl mx-auto px-4 py-6">
<!-- Header -->
<div class="flex flex-col sm:flex-row sm:justify-between sm:items-center mb-6">
<div>
<h1 class="text-3xl font-bold text-gray-900 mb-2">🎫 Ticket-Übersicht</h1>
<p class="text-gray-600">Verwalte und verfolge alle deine Tickets</p>
</div>
<div class="mt-4 sm:mt-0">
<a href="{% url 'create' %}"
class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded font-medium">
Neues Ticket erstellen
</a>
</div>
</div>
<!-- Filter und Suche -->
<div class="bg-white rounded-lg shadow p-4 mb-6">
<div class="grid grid-cols-1 lg:grid-cols-4 gap-4">
<!-- Status Filter -->
<div>
<form method="get">
<label class="block text-sm font-medium mb-1">Status:</label>
<select name="status"
onchange="this.form.submit()"
class="w-full h-10 px-3 border border-gray-300 rounded shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
<option value="">Alle Status</option>
<option value="open" {% if selected_status == "open" %}selected{% endif %}>🔴 Offen</option>
<option value="in_progress"
{% if selected_status == "in_progress" %}selected{% endif %}>
🟡 In Bearbeitung
</option>
<option value="closed"
{% if selected_status == "closed" %}selected{% endif %}>🟢 Erledigt</option>
</select>
<!-- Andere Filter beibehalten -->
{% if request.GET.assigned_to %}
<input type="hidden"
name="assigned_to"
value="{{ request.GET.assigned_to }}">
{% endif %}
{% if search_query %}<input type="hidden" name="q" value="{{ search_query }}">{% endif %}
</form>
</div>
<!-- Meine Tickets Filter -->
<div>
<label class="block text-sm font-medium mb-1">Zuweisung:</label>
{% if request.GET.assigned_to == user.id|stringformat:'s' %}
<!-- Wenn aktiv: Button zum Deaktivieren -->
<a href="?{% if selected_status %}status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
class="block w-full h-10 px-3 border border-purple-300 rounded shadow-sm text-center bg-purple-200 hover:bg-purple-300 transition-colors flex items-center justify-center">
👤 Meine Tickets ✓
</a>
</td>
<td class="px-4 py-3 text-center">
{% if ticket.status == 'open' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-red-500 text-white">
{{ ticket.get_status_display }}
</span>
{% elif ticket.status == 'in_progress' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-yellow-400 text-gray-900">
{{ ticket.get_status_display }}
</span>
{% elif ticket.status == 'closed' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-green-500 text-white">
{{ ticket.get_status_display }}
{% else %}
<!-- Wenn nicht aktiv: Button zum Aktivieren -->
<a href="?assigned_to={{ user.id }}{% if selected_status %}&status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
class="block w-full h-10 px-3 border border-purple-300 rounded shadow-sm text-center bg-purple-50 hover:bg-purple-100 transition-colors flex items-center justify-center">
👤 Meine Tickets
</a>
{% endif %}
</div>
<!-- Suche -->
<div class="lg:col-span-2">
<form method="get">
<label class="block text-sm font-medium mb-1">Suche:</label>
<div class="flex">
<input type="text"
name="q"
value="{{ search_query }}"
placeholder="Titel oder Beschreibung durchsuchen..."
class="flex-1 h-10 px-3 border border-gray-300 rounded-l shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
{% if selected_status %}<input type="hidden" name="status" value="{{ selected_status }}">{% endif %}
{% if request.GET.assigned_to %}
<input type="hidden"
name="assigned_to"
value="{{ request.GET.assigned_to }}">
{% endif %}
<button type="submit"
class="bg-blue-500 hover:bg-blue-600 text-white h-10 px-4 rounded-r">🔍</button>
</div>
</form>
</div>
</div>
<!-- Aktive Filter Anzeige -->
{% if selected_status or request.GET.assigned_to or search_query %}
<div class="mt-4 p-3 bg-gray-50 rounded border-l-4 border-blue-400">
<div class="flex flex-wrap items-center gap-2">
<span class="font-medium text-gray-700">Aktive Filter:</span>
{% if selected_status %}
<span class="px-2 py-1 bg-blue-100 text-blue-800 text-sm rounded">
Status: {{ selected_status|title }}
<a href="?{% if search_query %}q={{ search_query }}{% endif %}{% if request.GET.assigned_to %}&assigned_to={{ request.GET.assigned_to }}{% endif %}"
class="ml-1 text-blue-600 hover:text-blue-800">×</a>
</span>
{% endif %}
</td>
<td class="px-4 py-3 text-center">
{% if ticket.priority == 'low' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-blue-500 text-white">
{{ ticket.get_priority_display }}
</span>
{% elif ticket.priority == 'medium' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-yellow-400 text-gray-900">
{{ ticket.get_priority_display }}
</span>
{% elif ticket.priority == 'high' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-orange-500 text-white">
{{ ticket.get_priority_display }}
</span>
{% elif ticket.priority == 'urgent' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-red-500 text-white">
{{ ticket.get_priority_display }}
{% if request.GET.assigned_to %}
<span class="px-2 py-1 bg-purple-100 text-purple-800 text-sm rounded">
Meine Tickets
<a href="?{% if selected_status %}status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
class="ml-1 text-purple-600 hover:text-purple-800">×</a>
</span>
{% endif %}
</td>
<td class="px-4 py-3 text-sm text-gray-600">
{% if ticket.assigned_to %}
{{ ticket.assigned_to.username }}
{% else %}
<span class="text-gray-400 italic">Nicht zugewiesen</span>
{% if search_query %}
<span class="px-2 py-1 bg-green-100 text-green-800 text-sm rounded">
Suche: "{{ search_query }}"
<a href="?{% if selected_status %}status={{ selected_status }}{% endif %}{% if request.GET.assigned_to %}&assigned_to={{ request.GET.assigned_to }}{% endif %}"
class="ml-1 text-green-600 hover:text-green-800">×</a>
</span>
{% endif %}
</td>
<td class="px-4 py-3 text-center text-sm text-gray-500">
<div>{{ ticket.created_at|date:"d.m.Y" }}</div>
<div class="text-xs text-gray-400">{{ ticket.created_at|date:"H:i" }}</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Pagination -->
{% if is_paginated %}
<div class="mt-6 flex justify-between items-center">
<div class="text-sm text-gray-600">
Seite {{ page_obj.number }} von {{ page_obj.paginator.num_pages }}
</div>
<div class="flex gap-2">
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}{% if selected_status %}&status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
class="px-3 py-1 border border-gray-300 rounded hover:bg-gray-50">Zurück</a>
{% endif %}
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}{% if selected_status %}&status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
class="px-3 py-1 border border-gray-300 rounded hover:bg-gray-50">Weiter</a>
<a href="{% url 'ticket-list' %}"
class="text-sm text-gray-600 hover:text-gray-800 font-medium">Alle Filter entfernen</a>
</div>
</div>
{% endif %}
</div>
</div>
{% endif %}
{% else %}
<!-- Keine Tickets -->
<div class="text-center py-12 bg-white rounded-lg shadow">
<div class="text-gray-400 text-6xl mb-4">📋</div>
{% if search_query %}
<h3 class="text-lg font-medium text-gray-900 mb-2">Keine Tickets gefunden</h3>
<p class="text-gray-500 mb-4">
Keine Tickets gefunden für die Suche „<strong>{{ search_query }}</strong>"
</p>
<a href="?" class="text-blue-600 hover:text-blue-800 font-medium">
Alle Tickets anzeigen
</a>
<!-- Ticket Tabelle -->
{% if tickets %}
<div class="bg-white rounded-lg shadow overflow-hidden">
<table class="w-full">
<thead class="bg-blue-600 text-white">
<tr>
<th class="px-4 py-3 text-center text-sm font-bold">#</th>
<th class="px-4 py-3 text-left text-sm font-bold">Titel</th>
<th class="px-4 py-3 text-center text-sm font-bold">Status</th>
<th class="px-4 py-3 text-center text-sm font-bold">Priorität</th>
<th class="px-4 py-3 text-left text-sm font-bold">Zugewiesen an</th>
<th class="px-4 py-3 text-center text-sm font-bold">Erstellt</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
{% for ticket in tickets %}
<tr class="hover:bg-gray-50">
<td class="px-4 py-3 text-center text-sm font-bold text-gray-500">#{{ ticket.id }}</td>
<td class="px-4 py-3">
<a href="{% url 'detail' ticket.pk %}"
class="font-bold text-blue-600 hover:text-blue-800 hover:underline">
{{ ticket.title }}
</a>
</td>
<td class="px-4 py-3 text-center">
{% if ticket.status == 'open' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-red-500 text-white">{{ ticket.get_status_display }}</span>
{% elif ticket.status == 'in_progress' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-yellow-400 text-gray-900">
{{ ticket.get_status_display }}
</span>
{% elif ticket.status == 'closed' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-green-500 text-white">{{ ticket.get_status_display }}</span>
{% endif %}
</td>
<td class="px-4 py-3 text-center">
{% if ticket.priority == 'low' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-blue-500 text-white">{{ ticket.get_priority_display }}</span>
{% elif ticket.priority == 'medium' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-yellow-400 text-gray-900">
{{ ticket.get_priority_display }}
</span>
{% elif ticket.priority == 'high' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-orange-500 text-white">
{{ ticket.get_priority_display }}
</span>
{% elif ticket.priority == 'urgent' %}
<span class="px-2 py-1 rounded-full text-xs font-bold bg-red-500 text-white">{{ ticket.get_priority_display }}</span>
{% endif %}
</td>
<td class="px-4 py-3 text-sm text-gray-600">
{% if ticket.assigned_to %}
{{ ticket.assigned_to.username }}
{% else %}
<span class="text-gray-400 italic">Nicht zugewiesen</span>
{% endif %}
</td>
<td class="px-4 py-3 text-center text-sm text-gray-500">
<div>{{ ticket.created_at|date:"d.m.Y" }}</div>
<div class="text-xs text-gray-400">{{ ticket.created_at|date:"H:i" }}</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Pagination -->
{% if is_paginated %}
<div class="mt-6 flex justify-between items-center">
<div class="text-sm text-gray-600">Seite {{ page_obj.number }} von {{ page_obj.paginator.num_pages }}</div>
<div class="flex gap-2">
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}{% if selected_status %}&status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
class="px-3 py-1 border border-gray-300 rounded hover:bg-gray-50">Zurück</a>
{% endif %}
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}{% if selected_status %}&status={{ selected_status }}{% endif %}{% if search_query %}&q={{ search_query }}{% endif %}"
class="px-3 py-1 border border-gray-300 rounded hover:bg-gray-50">Weiter</a>
{% endif %}
</div>
</div>
{% endif %}
{% else %}
<h3 class="text-lg font-medium text-gray-900 mb-2">Noch keine Tickets vorhanden</h3>
<p class="text-gray-500 mb-4">Erstelle dein erstes Ticket um loszulegen.</p>
<a href="{% url 'create' %}"
class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded font-medium">
Erstes Ticket erstellen
</a>
<!-- Keine Tickets -->
<div class="text-center py-12 bg-white rounded-lg shadow">
<div class="text-gray-400 text-6xl mb-4">📋</div>
{% if search_query %}
<h3 class="text-lg font-medium text-gray-900 mb-2">Keine Tickets gefunden</h3>
<p class="text-gray-500 mb-4">
Keine Tickets gefunden für die Suche „<strong>{{ search_query }}</strong>"
</p>
<a href="?" class="text-blue-600 hover:text-blue-800 font-medium">Alle Tickets anzeigen</a>
{% else %}
<h3 class="text-lg font-medium text-gray-900 mb-2">Noch keine Tickets vorhanden</h3>
<p class="text-gray-500 mb-4">Erstelle dein erstes Ticket um loszulegen.</p>
<a href="{% url 'create' %}"
class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded font-medium">
Erstes Ticket erstellen
</a>
{% endif %}
</div>
{% endif %}
</div>
{% endif %}
</div>
{% endblock %}
{% endblock %}