(function () { const form = document.getElementById("createCategoryForm"); const toastStack = document.getElementById("toastStack"); const adminGrid = document.getElementById("adminGrid"); function showToast(message, kind = "success") { const toast = document.createElement("div"); toast.className = `toast ${kind}`; toast.textContent = message; toastStack.appendChild(toast); window.setTimeout(() => toast.remove(), 2600); } async function requestJSON(url, options = {}) { const response = await fetch(url, { headers: { "Content-Type": "application/json", }, ...options, }); const payload = await response.json().catch(() => ({ ok: false, error: "请求失败" })); if (!response.ok || !payload.ok) { throw new Error(payload.error || "请求失败"); } return payload; } function categoryCard(category) { const card = document.createElement("article"); card.className = "admin-card"; card.dataset.categoryId = category.id; card.innerHTML = `

Category

${category.name}

0 项任务

删除分类会同时移除其下全部任务,请谨慎操作。

`; return card; } form.addEventListener("submit", async (event) => { event.preventDefault(); const nameInput = document.getElementById("newCategoryName"); const name = nameInput.value.trim(); try { const payload = await requestJSON("/api/categories", { method: "POST", body: JSON.stringify({ name }), }); const createCard = adminGrid.querySelector(".create-card"); adminGrid.insertBefore(categoryCard(payload.category), createCard.nextSibling); nameInput.value = ""; showToast("新分类已创建"); } catch (error) { showToast(error.message, "error"); } }); adminGrid.addEventListener("click", async (event) => { const button = event.target.closest("[data-delete-category]"); if (!button) { return; } try { await requestJSON(`/api/categories/${button.dataset.deleteCategory}`, { method: "DELETE", body: JSON.stringify({}), }); const card = button.closest(".admin-card"); if (card) { card.remove(); } showToast("分类已删除"); } catch (error) { showToast(error.message, "error"); } }); })();