| (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 = ` |
| <div class="admin-card-head"> |
| <div> |
| <p class="column-label">Category</p> |
| <h2>${category.name}</h2> |
| </div> |
| <span class="task-count">0 项任务</span> |
| </div> |
| <p class="admin-card-copy">删除分类会同时移除其下全部任务,请谨慎操作。</p> |
| <button class="danger-button" type="button" data-delete-category="${category.id}">删除此清单</button> |
| `; |
| 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"); |
| } |
| }); |
| })(); |
|
|