File size: 2,684 Bytes
b7fa969
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
(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");
    }
  });
})();