manage-your-printer/templates/admin_guest_requests.html
2025-06-04 10:03:22 +02:00

372 lines
25 KiB
HTML

{% extends "base.html" %}
{% block title %}Gastaufträge verwalten - Mercedes-Benz MYP Platform{% endblock %}
{% block head %}
{{ super() }}
<!-- CSRF Token für AJAX-Anfragen -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<script src="{{ url_for('static', filename='js/admin-guest-requests.js') }}" defer></script>
<!-- Loading Overlay -->
<div id="loading-overlay" class="fixed inset-0 bg-black/60 backdrop-blur-sm z-50 flex items-center justify-center hidden">
<div class="bg-white dark:bg-slate-900 rounded-2xl p-8 shadow-2xl border border-gray-200 dark:border-slate-700">
<div class="flex items-center space-x-4">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 dark:border-blue-400"></div>
<span class="text-lg font-medium text-gray-900 dark:text-slate-100">Wird geladen...</span>
</div>
</div>
</div>
{% endblock %}
{% block content %}
<!-- Moderne Gastaufträge-Verwaltung -->
<div class="min-h-screen">
<!-- Hero Header -->
<div class="relative overflow-hidden bg-gradient-to-r from-slate-900 via-blue-900 to-indigo-900 dark:from-slate-950 dark:via-blue-950 dark:to-indigo-950 text-white rounded-3xl mx-4 mt-4">
<div class="absolute inset-0 bg-black/30 dark:bg-black/50"></div>
<div class="absolute inset-0 bg-gradient-to-r from-transparent via-white/5 dark:via-white/3 to-transparent"></div>
<!-- Live Status Indicator -->
<div class="absolute top-4 right-4 flex items-center space-x-2">
<div class="flex items-center space-x-2 bg-white/15 dark:bg-white/10 backdrop-blur-sm border border-white/30 dark:border-white/20 rounded-full px-3 py-1">
<div id="live-indicator" class="w-2 h-2 bg-green-400 dark:bg-green-300 rounded-full animate-pulse"></div>
<span class="text-sm font-medium text-white">Live</span>
</div>
<div class="bg-white/15 dark:bg-white/10 backdrop-blur-sm border border-white/30 dark:border-white/20 rounded-full px-3 py-1">
<span id="live-time" class="text-sm font-medium text-white"></span>
</div>
</div>
<!-- Animated Background Pattern -->
<div class="absolute inset-0 opacity-10 dark:opacity-5 rounded-3xl overflow-hidden">
<div class="absolute inset-0" style="background-image: radial-gradient(circle at 25% 25%, white 2px, transparent 2px), radial-gradient(circle at 75% 75%, white 2px, transparent 2px); background-size: 50px 50px;"></div>
</div>
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16">
<div class="flex justify-between items-center">
<div>
<!-- Mercedes-Benz Logo -->
<div class="inline-flex items-center justify-center w-20 h-20 bg-white/15 dark:bg-white/10 backdrop-blur-sm rounded-full mb-6 border border-white/30 dark:border-white/20">
<svg class="w-10 h-10 text-white" viewBox="0 0 80 80" fill="currentColor">
<path d="M58.6,4.5C53,1.6,46.7,0,40,0c-6.7,0-13,1.6-18.6,4.5v0C8.7,11.2,0,24.6,0,40c0,15.4,8.7,28.8,21.5,35.5
C27,78.3,33.3,80,40,80c6.7,0,12.9-1.7,18.5-4.6C71.3,68.8,80,55.4,80,40C80,24.6,71.3,11.2,58.6,4.5z M4,40
c0-13.1,7-24.5,17.5-30.9v0C26.6,6,32.5,4.2,39,4l-4.5,32.7L21.5,46.8v0L8.3,57.1C5.6,52,4,46.2,4,40z M58.6,70.8
C53.1,74.1,46.8,76,40,76c-6.8,0-13.2-1.9-18.6-5.2c-4.9-2.9-8.9-6.9-11.9-11.7l11.9-4.9v0L40,46.6l18.6,7.5v0l12,4.9
C67.6,63.9,63.4,67.9,58.6,70.8z M58.6,46.8L58.6,46.8l-12.9-10L41.1,4c6.3,0.2,12.3,2,17.4,5.1v0C69,15.4,76,26.9,76,40
c0,6.2-1.5,12-4.3,17.1L58.6,46.8z"/>
</svg>
</div>
<h1 class="text-4xl md:text-5xl font-bold mb-4 tracking-tight">
<span class="bg-gradient-to-r from-white via-blue-100 to-slate-100 dark:from-white dark:via-blue-200 dark:to-slate-200 bg-clip-text text-transparent">
Gastaufträge Verwaltung
</span>
</h1>
<p class="text-xl text-blue-100 dark:text-blue-200 max-w-2xl leading-relaxed">
Verwalten Sie Gastdruckaufträge mit modernster Technologie und Mercedes-Benz Qualität
</p>
</div>
<!-- Back to Admin Button -->
<div>
<a href="{{ url_for('admin_page') }}"
class="inline-flex items-center px-6 py-3 bg-white/15 dark:bg-white/10 backdrop-blur-sm border border-white/30 dark:border-white/20 rounded-xl text-white hover:bg-white/25 dark:hover:bg-white/15 transition-all duration-300 hover:scale-105">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/>
</svg>
Zurück zum Admin
</a>
</div>
</div>
</div>
</div>
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 -mt-8 relative z-10">
<!-- Quick Stats Dashboard -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8 mb-12">
<!-- Pending Requests -->
<div class="group relative bg-white/90 dark:bg-slate-900/90 backdrop-blur-xl rounded-3xl border border-gray-200/50 dark:border-slate-700/50 p-8 shadow-xl hover:shadow-2xl dark:shadow-2xl dark:hover:shadow-slate-900/50 transition-all duration-500 hover:-translate-y-2">
<div class="absolute inset-0 bg-gradient-to-br from-orange-500/10 dark:from-orange-400/20 to-red-500/10 dark:to-red-400/20 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div class="relative">
<div class="flex items-center justify-between mb-4">
<div class="p-3 bg-gradient-to-br from-orange-500 to-orange-600 dark:from-orange-400 dark:to-orange-500 rounded-xl shadow-lg">
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</div>
<div class="text-right">
<div id="pending-count" class="text-2xl font-bold text-slate-900 dark:text-slate-100">-</div>
<div class="text-sm text-slate-500 dark:text-slate-400">Wartend</div>
</div>
</div>
<div class="flex items-center space-x-2 mb-2">
<div class="w-2 h-2 bg-orange-400 dark:bg-orange-300 rounded-full animate-pulse"></div>
<span class="text-xs text-orange-600 dark:text-orange-400 font-medium">Benötigt Aufmerksamkeit</span>
</div>
</div>
</div>
<!-- Approved Requests -->
<div class="group relative bg-white/90 dark:bg-slate-900/90 backdrop-blur-xl rounded-3xl border border-gray-200/50 dark:border-slate-700/50 p-8 shadow-xl hover:shadow-2xl dark:shadow-2xl dark:hover:shadow-slate-900/50 transition-all duration-500 hover:-translate-y-2">
<div class="absolute inset-0 bg-gradient-to-br from-green-500/10 dark:from-green-400/20 to-emerald-500/10 dark:to-emerald-400/20 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div class="relative">
<div class="flex items-center justify-between mb-4">
<div class="p-3 bg-gradient-to-br from-green-500 to-green-600 dark:from-green-400 dark:to-green-500 rounded-xl shadow-lg">
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</div>
<div class="text-right">
<div id="approved-count" class="text-2xl font-bold text-slate-900 dark:text-slate-100">-</div>
<div class="text-sm text-slate-500 dark:text-slate-400">Genehmigt</div>
</div>
</div>
<div class="flex items-center space-x-2 mb-2">
<div class="w-2 h-2 bg-green-400 dark:bg-green-300 rounded-full animate-pulse"></div>
<span class="text-xs text-green-600 dark:text-green-400 font-medium">Aktiv</span>
</div>
</div>
</div>
<!-- Rejected Requests -->
<div class="group relative bg-white/90 dark:bg-slate-900/90 backdrop-blur-xl rounded-3xl border border-gray-200/50 dark:border-slate-700/50 p-8 shadow-xl hover:shadow-2xl dark:shadow-2xl dark:hover:shadow-slate-900/50 transition-all duration-500 hover:-translate-y-2">
<div class="absolute inset-0 bg-gradient-to-br from-red-500/10 dark:from-red-400/20 to-pink-500/10 dark:to-pink-400/20 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div class="relative">
<div class="flex items-center justify-between mb-4">
<div class="p-3 bg-gradient-to-br from-red-500 to-red-600 dark:from-red-400 dark:to-red-500 rounded-xl shadow-lg">
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"/>
</svg>
</div>
<div class="text-right">
<div id="rejected-count" class="text-2xl font-bold text-slate-900 dark:text-slate-100">-</div>
<div class="text-sm text-slate-500 dark:text-slate-400">Abgelehnt</div>
</div>
</div>
<div class="flex items-center space-x-2 mb-2">
<div class="w-2 h-2 bg-red-400 dark:bg-red-300 rounded-full"></div>
<span class="text-xs text-red-600 dark:text-red-400 font-medium">Archiviert</span>
</div>
</div>
</div>
<!-- Total Requests -->
<div class="group relative bg-white/90 dark:bg-slate-900/90 backdrop-blur-xl rounded-3xl border border-gray-200/50 dark:border-slate-700/50 p-8 shadow-xl hover:shadow-2xl dark:shadow-2xl dark:hover:shadow-slate-900/50 transition-all duration-500 hover:-translate-y-2">
<div class="absolute inset-0 bg-gradient-to-br from-blue-500/10 dark:from-blue-400/20 to-indigo-500/10 dark:to-indigo-400/20 rounded-2xl opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<div class="relative">
<div class="flex items-center justify-between mb-4">
<div class="p-3 bg-gradient-to-br from-blue-500 to-blue-600 dark:from-blue-400 dark:to-blue-500 rounded-xl shadow-lg">
<svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
</svg>
</div>
<div class="text-right">
<div id="total-count" class="text-2xl font-bold text-slate-900 dark:text-slate-100">-</div>
<div class="text-sm text-slate-500 dark:text-slate-400">Gesamt</div>
</div>
</div>
<div class="flex items-center space-x-2 mb-2">
<div class="w-2 h-2 bg-blue-400 dark:bg-blue-300 rounded-full animate-pulse"></div>
<span class="text-xs text-blue-600 dark:text-blue-400 font-medium">Alle Zeit</span>
</div>
</div>
</div>
</div>
<!-- Control Panel -->
<div class="bg-white/90 dark:bg-slate-900/90 backdrop-blur-xl rounded-3xl border border-gray-200/50 dark:border-slate-700/50 p-8 shadow-xl dark:shadow-2xl mb-8">
<div class="flex flex-col lg:flex-row justify-between items-start lg:items-center space-y-4 lg:space-y-0">
<!-- Search and Filters -->
<div class="flex flex-col sm:flex-row gap-4 flex-1">
<div class="relative flex-1 max-w-md">
<input type="text" id="search-requests" placeholder="Gastaufträge durchsuchen..."
class="w-full pl-10 pr-4 py-3 border border-slate-300 dark:border-slate-600 rounded-xl
bg-white/80 dark:bg-slate-800/80 text-slate-900 dark:text-slate-100
focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent
placeholder-slate-500 dark:placeholder-slate-400">
<svg class="w-5 h-5 text-slate-400 dark:text-slate-500 absolute left-3 top-1/2 transform -translate-y-1/2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
</svg>
</div>
<select id="status-filter"
class="px-4 py-3 border border-slate-300 dark:border-slate-600 rounded-xl
bg-white/80 dark:bg-slate-800/80 text-slate-900 dark:text-slate-100
focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent min-w-[150px]">
<option value="all">Alle Status</option>
<option value="pending">Wartend</option>
<option value="approved">Genehmigt</option>
<option value="rejected">Abgelehnt</option>
<option value="expired">Abgelaufen</option>
</select>
<select id="sort-order"
class="px-4 py-3 border border-slate-300 dark:border-slate-600 rounded-xl
bg-white/80 dark:bg-slate-800/80 text-slate-900 dark:text-slate-100
focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent min-w-[150px]">
<option value="newest">Neueste zuerst</option>
<option value="oldest">Älteste zuerst</option>
<option value="priority">Nach Priorität</option>
</select>
</div>
<!-- Action Buttons -->
<div class="flex space-x-3 ml-6">
<button id="refresh-btn"
class="inline-flex items-center px-4 py-3 bg-blue-500 dark:bg-blue-600 text-white rounded-xl hover:bg-blue-600 dark:hover:bg-blue-700 transition-all duration-300 shadow-lg hover:shadow-xl hover:scale-105">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/>
</svg>
Aktualisieren
</button>
<button id="export-btn"
class="inline-flex items-center px-4 py-3 bg-green-500 dark:bg-green-600 text-white rounded-xl hover:bg-green-600 dark:hover:bg-green-700 transition-all duration-300 shadow-lg hover:shadow-xl hover:scale-105">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
</svg>
Exportieren
</button>
<button id="bulk-actions-btn"
class="inline-flex items-center px-4 py-3 bg-purple-500 dark:bg-purple-600 text-white rounded-xl hover:bg-purple-600 dark:hover:bg-purple-700 transition-all duration-300 shadow-lg hover:shadow-xl hover:scale-105">
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 10h16M4 14h16M4 18h16"/>
</svg>
Massenaktionen
</button>
</div>
</div>
</div>
<!-- Guest Requests Table -->
<div class="bg-white/90 dark:bg-slate-900/90 backdrop-blur-xl rounded-3xl border border-gray-200/50 dark:border-slate-700/50 shadow-xl dark:shadow-2xl overflow-hidden">
<div class="p-8 border-b border-slate-200 dark:border-slate-700">
<div class="flex justify-between items-center">
<h2 class="text-2xl font-bold text-slate-900 dark:text-slate-100">Gastaufträge</h2>
<div class="flex items-center space-x-2 text-sm text-slate-500 dark:text-slate-400">
<span>Automatische Aktualisierung:</span>
<div class="w-2 h-2 bg-green-400 dark:bg-green-300 rounded-full animate-pulse"></div>
<span>Aktiv</span>
</div>
</div>
</div>
<div class="overflow-x-auto">
<table class="min-w-full">
<thead class="bg-slate-50 dark:bg-slate-900/80">
<tr>
<th class="px-6 py-4 text-left">
<input type="checkbox" id="select-all"
class="rounded border-slate-300 dark:border-slate-600 text-blue-600 dark:text-blue-500 focus:ring-blue-500 dark:focus:ring-blue-400 bg-white dark:bg-slate-800">
</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">
Antragsteller
</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">
Datei & Details
</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">
Status
</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">
Zeitstempel
</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">
Priorität
</th>
<th class="px-6 py-4 text-left text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider">
Aktionen
</th>
</tr>
</thead>
<tbody id="requests-table-body" class="bg-white dark:bg-slate-900/50 divide-y divide-slate-200 dark:divide-slate-700">
<!-- Dynamic content will be loaded here -->
</tbody>
</table>
</div>
<!-- Loading State -->
<div id="table-loading" class="flex items-center justify-center py-12 hidden">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 dark:border-blue-400 mr-4"></div>
<span class="text-slate-600 dark:text-slate-400">Lade Gastaufträge...</span>
</div>
<!-- Empty State -->
<div id="empty-state" class="text-center py-12 hidden">
<svg class="mx-auto h-12 w-12 text-slate-400 dark:text-slate-500 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"/>
</svg>
<h3 class="text-lg font-medium text-slate-900 dark:text-slate-100 mb-2">Keine Gastaufträge gefunden</h3>
<p class="text-slate-500 dark:text-slate-400">Es sind derzeit keine Gastaufträge vorhanden oder sie entsprechen nicht den Filterkriterien.</p>
</div>
</div>
<!-- Pagination -->
<div id="pagination" class="mt-8 flex justify-center">
<!-- Pagination controls will be dynamically generated -->
</div>
</div>
</div>
<!-- Guest Request Detail Modal -->
<div id="detail-modal" class="fixed inset-0 bg-black/60 dark:bg-black/80 backdrop-blur-sm z-50 hidden">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white dark:bg-slate-900 rounded-2xl shadow-2xl border border-gray-200 dark:border-slate-700 max-w-4xl w-full max-h-[90vh] overflow-y-auto">
<div id="modal-content">
<!-- Modal content will be dynamically loaded -->
</div>
</div>
</div>
</div>
<!-- Bulk Actions Modal -->
<div id="bulk-modal" class="fixed inset-0 bg-black/60 dark:bg-black/80 backdrop-blur-sm z-50 hidden">
<div class="flex items-center justify-center min-h-screen p-4">
<div class="bg-white dark:bg-slate-900 rounded-2xl shadow-2xl border border-gray-200 dark:border-slate-700 max-w-md w-full">
<div class="p-6 border-b border-gray-200 dark:border-slate-700">
<h3 class="text-xl font-bold text-gray-900 dark:text-slate-100">Massenaktionen</h3>
</div>
<div class="p-6">
<div class="space-y-4">
<button onclick="performBulkAction('approve')"
class="w-full px-4 py-3 bg-green-500 dark:bg-green-600 text-white rounded-lg hover:bg-green-600 dark:hover:bg-green-700 transition-colors">
Ausgewählte genehmigen
</button>
<button onclick="performBulkAction('reject')"
class="w-full px-4 py-3 bg-red-500 dark:bg-red-600 text-white rounded-lg hover:bg-red-600 dark:hover:bg-red-700 transition-colors">
Ausgewählte ablehnen
</button>
<button onclick="performBulkAction('delete')"
class="w-full px-4 py-3 bg-gray-500 dark:bg-gray-600 text-white rounded-lg hover:bg-gray-600 dark:hover:bg-gray-700 transition-colors">
Ausgewählte löschen
</button>
</div>
<div class="mt-6 text-center">
<button onclick="closeBulkModal()"
class="px-4 py-2 text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200">
Abbrechen
</button>
</div>
</div>
</div>
</div>
</div>
<script>
// Initialize live time display
function updateLiveTime() {
const timeElement = document.getElementById('live-time');
if (timeElement) {
timeElement.textContent = new Date().toLocaleTimeString('de-DE');
}
}
// Update time every second
setInterval(updateLiveTime, 1000);
updateLiveTime();
</script>
{% endblock %}