(function () { 'use strict'; var root = document.querySelector('.task-cert-admin-monitoring'); if (!root) { return; } var csrfToken = root.getAttribute('data-csrf-token') || ''; var resetAssignmentUrl = root.getAttribute('data-reset-assignment-url') || ''; var resetCycleUrl = root.getAttribute('data-reset-cycle-url') || ''; var approvalUrl = root.getAttribute('data-approval-url') || ''; var taskId = parseInt(root.getAttribute('data-task-id') || '0', 10); // ── Toast ───────────────────────────────────────────────────── var toastContainer = document.getElementById('task-cert-toast-container'); function showToast(message, type) { if (!toastContainer) { return; } var cls = type === 'error' ? 'task-cert-error' : 'task-cert-success'; var toast = document.createElement('div'); toast.className = 'task-cert-toast ' + cls; toast.textContent = String(message || ''); toast.addEventListener('click', function () { removeToast(toast); }); toastContainer.appendChild(toast); // Trigger fade-in on next frame requestAnimationFrame(function () { toast.classList.add('is-visible'); }); var autoHideMs = type === 'error' ? 7000 : 4000; setTimeout(function () { removeToast(toast); }, autoHideMs); } function removeToast(toast) { if (!toast || !toast.parentNode) { return; } toast.classList.remove('is-visible'); setTimeout(function () { if (toast.parentNode) { toast.parentNode.removeChild(toast); } }, 250); } // Expose globally so other admin scripts (mark_completed) can reuse window.TaskCertAdminActions = window.TaskCertAdminActions || {}; window.TaskCertAdminActions.showToast = showToast; // ── Fetch-Helper ────────────────────────────────────────────── function postJson(url, body) { return fetch(url, { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }).then(function (res) { return res.json().then(function (data) { return { ok: res.ok, status: res.status, data: data }; }).catch(function () { return { ok: false, status: res.status, data: { success: false, error: 'Ungültige Server-Antwort' } }; }); }); } function reloadWithDelay() { setTimeout(function () { location.reload(); }, 800); } function setButtonBusy(btn, busy, busyLabel) { if (!btn) { return; } if (busy) { btn._originalLabel = btn.textContent; btn.textContent = busyLabel || 'Wird verarbeitet...'; btn.disabled = true; } else { if (btn._originalLabel) { btn.textContent = btn._originalLabel; } btn.disabled = false; } } // ── Action: Reset Assignment ────────────────────────────────── function handleResetAssignment(btn) { var assignmentId = parseInt(btn.getAttribute('data-assignment-id') || '0', 10); if (!assignmentId || !taskId || !resetAssignmentUrl) { return; } if (!window.confirm('Einreichungen und Zertifikat für diesen Zeitraum wirklich zurücksetzen?')) { return; } setButtonBusy(btn, true, 'Wird zurückgesetzt...'); postJson(resetAssignmentUrl, { csrf_token: csrfToken, task_id: taskId, assignment_id: assignmentId }).then(function (result) { if (result.data && result.data.success) { showToast('Zeitraum wurde zurückgesetzt.', 'success'); reloadWithDelay(); } else { setButtonBusy(btn, false); showToast((result.data && result.data.error) || 'Fehler beim Zurücksetzen.', 'error'); } }).catch(function (err) { setButtonBusy(btn, false); showToast('Netzwerkfehler: ' + (err && err.message ? err.message : 'Unbekannt'), 'error'); }); } // ── Action: Reset Cycle ─────────────────────────────────────── function handleResetCycle(btn) { var btnTaskId = parseInt(btn.getAttribute('data-task-id') || '0', 10) || taskId; if (!btnTaskId || !resetCycleUrl) { return; } if (!window.confirm('Wirklich ALLE Einreichungen und Zertifikate im aktuellen Zyklus zurücksetzen? Diese Aktion betrifft alle Mitarbeiter in diesem Zeitraum.')) { return; } setButtonBusy(btn, true, 'Wird zurückgesetzt...'); postJson(resetCycleUrl, { csrf_token: csrfToken, task_id: btnTaskId }).then(function (result) { if (result.data && result.data.success) { var stats = (result.data && result.data.stats) || {}; var n = parseInt(stats.assignment_count || 0, 10); showToast('Zyklus wurde zurückgesetzt (' + n + ' Zuweisungen).', 'success'); reloadWithDelay(); } else { setButtonBusy(btn, false); showToast((result.data && result.data.error) || 'Fehler beim Zurücksetzen.', 'error'); } }).catch(function (err) { setButtonBusy(btn, false); showToast('Netzwerkfehler: ' + (err && err.message ? err.message : 'Unbekannt'), 'error'); }); } // ── Action: Approval ────────────────────────────────────────── function handleApproval(btn) { var wrapper = btn.closest('.task-cert-inline-approval-form'); if (!wrapper) { return; } var submissionId = parseInt(wrapper.getAttribute('data-submission-id') || '0', 10); var decision = btn.getAttribute('data-decision') || ''; if (!submissionId || !decision || !approvalUrl) { return; } var noteEl = wrapper.querySelector('.task-cert-approval-note'); var note = noteEl ? noteEl.value.trim() : ''; if (decision === 'reject' && !window.confirm('Einreichung wirklich ablehnen?')) { return; } // Disable both buttons in this row var siblings = wrapper.querySelectorAll('.task-cert-btn-approval'); for (var i = 0; i < siblings.length; i++) { siblings[i].disabled = true; } setButtonBusy(btn, true, decision === 'approve' ? 'Freigabe...' : 'Ablehnen...'); postJson(approvalUrl, { csrf_token: csrfToken, submission_id: submissionId, decision: decision, note: note }).then(function (result) { if (result.data && result.data.success) { var msg = decision === 'approve' ? 'Einreichung freigegeben.' : 'Einreichung abgelehnt.'; showToast(msg, 'success'); reloadWithDelay(); } else { for (var j = 0; j < siblings.length; j++) { siblings[j].disabled = false; } setButtonBusy(btn, false); showToast((result.data && result.data.error) || 'Fehler bei der Bearbeitung.', 'error'); } }).catch(function (err) { for (var k = 0; k < siblings.length; k++) { siblings[k].disabled = false; } setButtonBusy(btn, false); showToast('Netzwerkfehler: ' + (err && err.message ? err.message : 'Unbekannt'), 'error'); }); } // ── Event-Delegation ────────────────────────────────────────── document.addEventListener('click', function (e) { var resetAssignBtn = e.target.closest('.task-cert-btn-reset-assignment'); if (resetAssignBtn) { e.preventDefault(); handleResetAssignment(resetAssignBtn); return; } var resetCycleBtn = e.target.closest('.task-cert-btn-reset-cycle'); if (resetCycleBtn) { e.preventDefault(); handleResetCycle(resetCycleBtn); return; } var approvalBtn = e.target.closest('.task-cert-btn-approval'); if (approvalBtn) { e.preventDefault(); handleApproval(approvalBtn); return; } }); })();