File size: 5,119 Bytes
8f0fa74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>문제 μ—…λ‘œλ“œ</title>
  <script src="https://cdn.tailwindcss.com"></script>
</head>

<body class="min-h-screen bg-gradient-to-b from-emerald-50 to-slate-100">
  <!-- 헀더 -->
  <header class="bg-white shadow sticky top-0 z-10">
    <div class="max-w-4xl mx-auto px-4 py-3 flex items-center">
      <h1 class="text-lg font-semibold">문제 μ—…λ‘œλ“œ</h1>
      <nav class="ml-auto flex gap-3 text-sm">
        <a href="/" class="px-3 py-1.5 rounded-lg border">ν™ˆ</a>
        <a href="/quiz" class="px-3 py-1.5 rounded-lg border">문제 풀이</a>
        <a href="/wrong" class="px-3 py-1.5 rounded-lg border">μ˜€λ‹΅ λ…ΈνŠΈ</a>
      </nav>
    </div>
  </header>

  <!-- 메인 -->
  <main class="max-w-xl mx-auto px-4 py-10">
    <div class="bg-white rounded-2xl shadow p-6">
      <h2 class="text-xl font-bold text-slate-900 mb-4">PDF μ—…λ‘œλ“œ</h2>
      <p class="text-sm text-slate-600 mb-6">
        μ‹œν—˜ 덀프 PDFλ₯Ό μ—…λ‘œλ“œν•˜λ©΄ μžλ™μœΌλ‘œ <span class="text-emerald-600 font-semibold">Adaptive νŒŒμ„œ</span>κ°€
        문제 μœ ν˜•λ³„λ‘œ λΆ„μ„ν•˜κ³  DB에 μ €μž₯ν•©λ‹ˆλ‹€.
      </p>

      <form id="uploadForm" enctype="multipart/form-data" class="space-y-4">
        <input type="file" name="file" accept=".pdf"
               class="w-full text-sm text-slate-700 file:mr-4 file:py-2 file:px-4 
                      file:rounded-lg file:border-0 file:text-sm 
                      file:font-semibold file:bg-emerald-50 file:text-emerald-700 
                      hover:file:bg-emerald-100" required>
        <button type="submit"
                class="w-full py-2 px-4 rounded-lg bg-emerald-600 text-white font-semibold hover:bg-emerald-700 transition">
          μ—…λ‘œλ“œ 및 νŒŒμ‹± μ‹œμž‘
        </button>
      </form>

      <!-- μ§„ν–‰ μƒνƒœ -->
      <div id="statusBox" class="mt-6 hidden">
        <div class="text-sm text-slate-600 mb-2 font-medium">μ§„ν–‰ 상황</div>
        <div class="w-full bg-slate-200 rounded-full h-2.5">
          <div id="progressBar" class="bg-emerald-500 h-2.5 rounded-full transition-all duration-500 ease-in-out" style="width: 0%"></div>
        </div>
        <div id="statusText" class="mt-2 text-sm text-slate-600"></div>
      </div>

      <!-- κ²°κ³Ό λ©”μ‹œμ§€ -->
      <div id="message" class="mt-6 text-sm"></div>

      <!-- μœ ν˜•λ³„ 톡계 -->
      <div id="summary" class="mt-4 hidden bg-emerald-50 border border-emerald-200 rounded-lg p-4 text-sm text-emerald-800">
        <p class="font-semibold mb-2">πŸ“Š μœ ν˜•λ³„ νŒŒμ‹± κ²°κ³Ό</p>
        <ul id="summaryList" class="space-y-1 text-sm"></ul>
      </div>
    </div>
  </main>

  <script>
    const form = document.getElementById("uploadForm");
    const msgBox = document.getElementById("message");
    const statusBox = document.getElementById("statusBox");
    const progressBar = document.getElementById("progressBar");
    const statusText = document.getElementById("statusText");
    const summaryBox = document.getElementById("summary");
    const summaryList = document.getElementById("summaryList");

    function updateProgress(percent, text) {
      progressBar.style.width = percent + "%";
      statusText.textContent = text;
    }

    form.addEventListener("submit", async (e) => {
      e.preventDefault();
      msgBox.textContent = "";
      statusBox.classList.remove("hidden");
      summaryBox.classList.add("hidden");
      updateProgress(10, "πŸ“‘ 파일 μ—…λ‘œλ“œ 쀑...");

      const formData = new FormData(form);
      try {
        const res = await fetch("/admin/upload", { method: "POST", body: formData });
        updateProgress(50, "🧠 Adaptive νŒŒμ„œλ‘œ 문제 뢄석 쀑...");
        const data = await res.json();

        if (res.ok) {
          updateProgress(100, "βœ… DB μ €μž₯ μ™„λ£Œ!");
          msgBox.textContent = `βœ… ${data.message}`;
          msgBox.className = "mt-6 text-sm text-emerald-700 font-medium";

          // μœ ν˜•λ³„ 톡계 ν‘œμ‹œ (Adaptive νŒŒμ„œκ°€ 각 문항에 question_type 포함)
          if (data.details && data.details.by_type) {
            summaryBox.classList.remove("hidden");
            summaryList.innerHTML = "";
            for (const [type, count] of Object.entries(data.details.by_type)) {
              summaryList.innerHTML += `<li>β€’ ${type}: ${count}λ¬Έν•­</li>`;
            }
          } else {
            summaryBox.classList.remove("hidden");
            summaryList.innerHTML = `<li>총 ${data.count}λ¬Έν•­ μ €μž₯ μ™„λ£Œ</li>`;
          }

        } else {
          msgBox.textContent = `❌ 였λ₯˜: ${data.error || "μ—…λ‘œλ“œ μ‹€νŒ¨"}`;
          msgBox.className = "mt-6 text-sm text-rose-600 font-medium";
          updateProgress(0, "❌ μ‹€νŒ¨");
        }
      } catch (err) {
        msgBox.textContent = "⚠️ μ„œλ²„ 였λ₯˜λ‘œ μ—…λ‘œλ“œ μ‹€νŒ¨";
        msgBox.className = "mt-6 text-sm text-rose-600 font-medium";
        updateProgress(0, "⚠️ 였λ₯˜ λ°œμƒ");
      }
    });
  </script>
</body>
</html>