/** * Mercedes-Benz MYP Admin Guest Requests Management * Moderne Verwaltung von Gastaufträgen mit Live-Updates */ // Vereinfachte minimierte Version mit korrigierten API-URLs const API_BASE_URL = document.location.origin; let csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || ''; let currentRequests = []; let filteredRequests = []; document.addEventListener('DOMContentLoaded', function() { console.log('🎯 Admin Guest Requests Manager geladen'); initEventListeners(); loadGuestRequests(); startAutoRefresh(); }); function initEventListeners() { document.getElementById('search-requests')?.addEventListener('input', handleSearch); document.getElementById('status-filter')?.addEventListener('change', handleFilterChange); document.getElementById('sort-order')?.addEventListener('change', handleSortChange); document.getElementById('refresh-btn')?.addEventListener('click', loadGuestRequests); document.getElementById('export-btn')?.addEventListener('click', handleExport); document.getElementById('bulk-actions-btn')?.addEventListener('click', showBulkActionsModal); document.getElementById('select-all')?.addEventListener('change', handleSelectAll); } async function loadGuestRequests() { try { showLoading(true); const url = `${API_BASE_URL}/api/admin/requests`; const response = await fetch(url, { method: 'GET', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); if (data.success) { currentRequests = data.requests || []; updateStats(data.stats || {}); applyFiltersAndSort(); console.log(`✅ ${currentRequests.length} Gastaufträge geladen`); } else { throw new Error(data.message || 'Fehler beim Laden der Gastaufträge'); } } catch (error) { console.error('Fehler beim Laden der Gastaufträge:', error); showNotification('❌ Fehler beim Laden der Gastaufträge: ' + error.message, 'error'); showEmptyState(); } finally { showLoading(false); } } async function approveRequest(requestId) { const notes = prompt('Genehmigungsnotizen (optional):'); if (notes === null) return; try { showLoading(true); const url = `${API_BASE_URL}/api/requests/${requestId}/approve`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken }, body: JSON.stringify({ notes: notes || '' }) }); const data = await response.json(); if (data.success) { showNotification('✅ Gastauftrag erfolgreich genehmigt', 'success'); if (data.otp) { showNotification(`🔑 OTP-Code für Gast: ${data.otp}`, 'info'); } loadGuestRequests(); } else { throw new Error(data.message || 'Fehler beim Genehmigen'); } } catch (error) { console.error('Fehler beim Genehmigen:', error); showNotification('❌ Fehler beim Genehmigen: ' + error.message, 'error'); } finally { showLoading(false); } } async function rejectRequest(requestId) { const reason = prompt('Grund für die Ablehnung (erforderlich):'); if (!reason || reason.trim() === '') { showNotification('⚠️ Ablehnungsgrund ist erforderlich', 'warning'); return; } try { showLoading(true); const url = `${API_BASE_URL}/api/requests/${requestId}/deny`; const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken }, body: JSON.stringify({ reason: reason.trim() }) }); const data = await response.json(); if (data.success) { showNotification('✅ Gastauftrag erfolgreich abgelehnt', 'success'); loadGuestRequests(); } else { throw new Error(data.message || 'Fehler beim Ablehnen'); } } catch (error) { console.error('Fehler beim Ablehnen:', error); showNotification('❌ Fehler beim Ablehnen: ' + error.message, 'error'); } finally { showLoading(false); } } async function deleteRequest(requestId) { if (!confirm('Möchten Sie diesen Gastauftrag wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden.')) return; try { showLoading(true); const url = `${API_BASE_URL}/api/admin/requests/${requestId}`; const response = await fetch(url, { method: 'DELETE', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken } }); const data = await response.json(); if (data.success) { showNotification('✅ Gastauftrag erfolgreich gelöscht', 'success'); loadGuestRequests(); } else { throw new Error(data.message || 'Fehler beim Löschen'); } } catch (error) { console.error('Fehler beim Löschen:', error); showNotification('❌ Fehler beim Löschen: ' + error.message, 'error'); } finally { showLoading(false); } } // Utility Functions function updateStats(stats) { document.getElementById('pending-count').textContent = stats.pending || 0; document.getElementById('approved-count').textContent = stats.approved || 0; document.getElementById('rejected-count').textContent = stats.denied || 0; document.getElementById('total-count').textContent = stats.total || 0; } function applyFiltersAndSort() { const searchTerm = document.getElementById('search-requests')?.value.toLowerCase() || ''; const statusFilter = document.getElementById('status-filter')?.value || 'all'; const sortOrder = document.getElementById('sort-order')?.value || 'newest'; let requests = [...currentRequests]; if (searchTerm) { requests = requests.filter(req => (req.name || '').toLowerCase().includes(searchTerm) || (req.email || '').toLowerCase().includes(searchTerm) || (req.file_name || '').toLowerCase().includes(searchTerm) ); } if (statusFilter !== 'all') { requests = requests.filter(req => req.status === statusFilter); } requests.sort((a, b) => { if (sortOrder === 'oldest') { return new Date(a.created_at) - new Date(b.created_at); } return new Date(b.created_at) - new Date(a.created_at); }); filteredRequests = requests; renderRequestsTable(); } function renderRequestsTable() { const tableBody = document.getElementById('requests-table-body'); if (!tableBody) return; if (filteredRequests.length === 0) { tableBody.innerHTML = 'Keine Gastaufträge gefunden'; return; } const requestsHtml = filteredRequests.map(request => createRequestRow(request)).join(''); tableBody.innerHTML = requestsHtml; } function createRequestRow(request) { const statusColors = { 'pending': 'bg-yellow-100 text-yellow-800', 'approved': 'bg-green-100 text-green-800', 'rejected': 'bg-red-100 text-red-800' }; return `
${escapeHtml(request.name || 'Unbekannt')}
${escapeHtml(request.email || '')}
${escapeHtml(request.file_name || 'Keine Datei')}
${request.duration_minutes || 0} Min.
${getStatusText(request.status)} ${formatDateTime(request.created_at)} Normal
${request.status === 'pending' ? ` ` : ''}
`; } // Event Handlers function handleSearch() { applyFiltersAndSort(); } function handleFilterChange() { applyFiltersAndSort(); } function handleSortChange() { applyFiltersAndSort(); } function handleSelectAll(event) { document.querySelectorAll('.request-checkbox').forEach(cb => cb.checked = event.target.checked); } function handleExport() { showNotification('Export-Funktion wird implementiert', 'info'); } // UI Functions function showLoading(show) { const overlay = document.getElementById('loading-overlay'); if (overlay) overlay.classList.toggle('hidden', !show); } function showEmptyState() { document.getElementById('empty-state')?.classList.remove('hidden'); } function showNotification(message, type = 'info') { const colors = { 'success': 'bg-green-500', 'error': 'bg-red-500', 'warning': 'bg-yellow-500', 'info': 'bg-blue-500' }; const notification = document.createElement('div'); notification.className = `fixed top-4 right-4 ${colors[type]} text-white px-6 py-3 rounded-lg shadow-lg z-50`; notification.textContent = message; document.body.appendChild(notification); setTimeout(() => { notification.remove(); }, 5000); } function startAutoRefresh() { setInterval(loadGuestRequests, 30000); // Refresh every 30 seconds } function showBulkActionsModal() { const selectedIds = Array.from(document.querySelectorAll('.request-checkbox:checked')).map(cb => cb.value); if (selectedIds.length === 0) { showNotification('⚠️ Bitte wählen Sie mindestens einen Gastauftrag aus', 'warning'); return; } document.getElementById('bulk-modal')?.classList.remove('hidden'); } function closeBulkModal() { document.getElementById('bulk-modal')?.classList.add('hidden'); } // Utility Functions function escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } function formatDateTime(dateString) { return new Date(dateString).toLocaleString('de-DE'); } function getStatusText(status) { const texts = { 'pending': 'Wartend', 'approved': 'Genehmigt', 'rejected': 'Abgelehnt' }; return texts[status] || status; }