/* ===================================================================== postfach.js — Logik für postfach.html ===================================================================== */ const API_BASE_URL = "https://dogfather-universe-postfach.dogfather1608.workers.dev"; const { getSession, sessionHasPermission, apiCall, doLogin, doLogout } = window.AdminAuth; const STATUS_OPTIONS = ["neu", "in_bearbeitung", "beantwortet"]; function $(id) { return document.getElementById(id); } function showApp(session) { $("gate-container").style.display = "none"; $("session-bar").style.display = "block"; $("inbox-section").style.display = "block"; $("role-badge").textContent = session.isOwner ? "Eingeloggt als: Dogi (Owner)" : `Eingeloggt als: ${session.name} (${session.roleName})`; const canSeeTeam = session.isOwner || sessionHasPermission(session, "TEAM_VIEW"); $("team-link").style.display = canSeeTeam ? "inline-flex" : "none"; if (session.isOwner) { $("live-toggle-section").style.display = "block"; loadLiveStatus(); } loadInbox(); } function showGate() { $("gate-container").style.display = "block"; $("session-bar").style.display = "none"; $("live-toggle-section").style.display = "none"; $("inbox-section").style.display = "none"; } /* ---------------- Bewerbungen ---------------- */ async function loadInbox() { const session = getSession(); const includeArchived = $("show-archived").checked; const res = await apiCall(API_BASE_URL, "/admin/applications/list", { includeArchived }); if (!res.ok) { if (!getSession()) showGate(); return; } renderInbox(res.applications, session); } function renderInbox(applications, session) { const list = $("inbox-list"); if (!applications.length) { list.innerHTML = `

Keine Bewerbungen in dieser Ansicht.

`; return; } list.innerHTML = applications .map((a) => { const fields = a.data ? Object.entries(a.data).map(([k, v]) => `

${k}: ${v}

`).join("") : `

Keine Berechtigung, den vollen Inhalt zu öffnen.

`; const date = new Date(a.createdAt).toLocaleString("de-DE"); const actions = []; if (sessionHasPermission(session, "APPLICATIONS_TAKE_OVER")) { actions.push(``); } if (sessionHasPermission(session, "APPLICATIONS_MARK_ANSWERED")) { actions.push(``); } if (sessionHasPermission(session, "APPLICATIONS_ARCHIVE") && !a.archived) { actions.push(``); } if (sessionHasPermission(session, "APPLICATIONS_RESTORE") && a.archived) { actions.push(``); } if (sessionHasPermission(session, "APPLICATIONS_DELETE")) { actions.push(``); } if (sessionHasPermission(session, "NOTES_READ")) { actions.push(``); } const statusSelect = sessionHasPermission(session, "APPLICATIONS_CHANGE_STATUS") ? `` : `${a.status}`; return `
${a.type}${a.archived ? " · archiviert" : ""} ${statusSelect}

${date}

${fields}
${actions.join("")}

Lädt…

${ sessionHasPermission(session, "NOTES_WRITE") ? `
` : "" }
`; }) .join(""); list.querySelectorAll(".take-btn").forEach((b) => b.addEventListener("click", () => appAction("/admin/applications/take-over", b.dataset.id))); list.querySelectorAll(".answered-btn").forEach((b) => b.addEventListener("click", () => appAction("/admin/applications/mark-answered", b.dataset.id))); list.querySelectorAll(".archive-btn").forEach((b) => b.addEventListener("click", () => appAction("/admin/applications/archive", b.dataset.id))); list.querySelectorAll(".restore-btn").forEach((b) => b.addEventListener("click", () => appAction("/admin/applications/restore", b.dataset.id))); list.querySelectorAll(".delete-btn").forEach((b) => b.addEventListener("click", () => { if (confirm("Diese Bewerbung wirklich endgültig löschen?")) appAction("/admin/applications/delete", b.dataset.id); }) ); list.querySelectorAll(".status-select").forEach((sel) => sel.addEventListener("change", () => appAction("/admin/applications/status", sel.dataset.id, { status: sel.value }, false)) ); list.querySelectorAll(".notes-toggle-btn").forEach((b) => b.addEventListener("click", () => { const box = $(`notes-${b.dataset.id}`); box.classList.toggle("open"); if (box.classList.contains("open")) loadNotes(b.dataset.id); }) ); list.querySelectorAll(".add-note-btn").forEach((b) => b.addEventListener("click", async () => { const textarea = document.querySelector(`.note-input[data-id="${b.dataset.id}"]`); const text = textarea.value.trim(); if (!text) return; const res = await apiCall(API_BASE_URL, "/admin/notes/add", { applicationId: b.dataset.id, text }); if (res.ok) { textarea.value = ""; loadNotes(b.dataset.id); } }) ); } async function appAction(path, id, extra, reload = true) { const res = await apiCall(API_BASE_URL, path, { id, ...(extra || {}) }); if (res.ok && reload) loadInbox(); else if (!res.ok) alert(res.error || "Fehler."); } async function loadNotes(applicationId) { const box = $(`notes-list-${applicationId}`); const res = await apiCall(API_BASE_URL, "/admin/notes/list", { applicationId }); if (!res.ok) { box.innerHTML = `

Konnte Notizen nicht laden.

`; return; } box.innerHTML = res.notes .map((n) => `
${n.author}: ${n.text}
${new Date(n.created_at).toLocaleString("de-DE")}
`) .join("") || `

Noch keine Notizen.

`; } /* ---------------- Live-Status ---------------- */ function renderLiveStatus(live) { $("admin-live-dot").classList.toggle("is-live", !!live); $("admin-live-text").textContent = live ? "Live jetzt!" : "Aktuell offline"; } async function loadLiveStatus() { try { const res = await fetch(`${API_BASE_URL}/live-status`); const data = await res.json(); if (res.ok && data.ok) renderLiveStatus(data.live); } catch { /* keine Blockade */ } } async function setLiveStatus(live) { const res = await apiCall(API_BASE_URL, "/live-status/set", { live }); if (res.ok) renderLiveStatus(res.live); } /* ---------------- Login / Logout ---------------- */ document.addEventListener("DOMContentLoaded", () => { const existing = getSession(); if (existing) showApp(existing); else showGate(); $("code-gate").addEventListener("submit", async (e) => { e.preventDefault(); const status = $("gate-status"); status.className = "form-status show"; status.textContent = "Prüfe Code …"; const res = await doLogin(API_BASE_URL, $("code-input").value); if (res.ok) { status.className = "form-status"; showApp(getSession()); } else { status.textContent = res.error || "Falscher Code."; status.className = "form-status show error"; } }); $("logout-btn").addEventListener("click", async () => { await doLogout(API_BASE_URL); showGate(); }); $("refresh-btn").addEventListener("click", loadInbox); $("show-archived").addEventListener("change", loadInbox); $("go-live-btn").addEventListener("click", () => setLiveStatus(true)); $("go-offline-btn").addEventListener("click", () => setLiveStatus(false)); });