Spaces:
Sleeping
Sleeping
| <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> | |