Kentlo's picture
πŸš€ Clean deployment - removed all binary files
8f0fa74
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>AZ-104 CBT β€’ μ˜€λ‹΅ & 볡슡 λ…ΈνŠΈ</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>
:root {
--brand: #0a6bdf;
--brand-dark: #0850a7;
--warn: #ffcc00;
--bg: #f5f7fa;
--ok: #178a00;
--bad: #d12929;
--card: #fff;
--muted: #6b7280;
}
body {
margin: 0;
background: var(--bg);
font-family: system-ui, -apple-system, Segoe UI, Roboto, Apple SD Gothic Neo, Noto Sans KR, Arial, sans-serif;
padding: 24px;
display: flex;
justify-content: center;
}
.wrap { width: 100%; max-width: 900px; }
.topbar {
display: flex; align-items: center; justify-content: space-between;
margin-bottom: 16px; gap: 12px; flex-wrap: wrap;
}
.progress { color: var(--muted); font-size: 14px; }
.pill {
font-size: 12px; padding: 6px 10px; border-radius: 999px;
background: #f3f4f6; color: #374151;
}
.card {
background: var(--card); border-radius: 14px; padding: 22px;
box-shadow: 0 8px 24px rgba(0,0,0,.08);
min-height: 260px;
}
.qid { font-size: 13px; color: var(--muted); margin-bottom: 6px; }
.qtext { font-size: 18px; line-height: 1.5; margin: 0 0 14px; }
.options { display: grid; gap: 10px; margin-top: 14px; }
.opt {
display: flex; align-items: center; gap: 10px; padding: 12px 14px;
border: 1px solid #e5e7eb; border-radius: 10px; background: #fff;
}
.opt.correct { border-color: #b8e3c1; background: #effaf2; }
.opt.wrong { border-color: #f1b7b7; background: #fff1f1; }
.opt.chosen { border: 2px solid var(--warn); }
.exp {
display: none; margin-top: 14px; padding: 12px 14px; border-left: 5px solid var(--brand);
background: #eef6ff; border-radius: 8px;
}
.exp.show { display: block; }
.nav {
margin-top: 18px; display: flex; align-items: center; gap: 14px;
background: #fff; border-radius: 14px; box-shadow: 0 8px 24px rgba(0,0,0,.08);
padding: 16px 18px;
}
.spacer { flex: 1; }
button.btn {
border: 0; padding: 10px 18px; border-radius: 10px; color: #fff; background: var(--brand);
cursor: pointer; font-weight: 600; transition: background .15s;
}
button.btn:hover { background: var(--brand-dark); }
button.outline { background: #fff; color: #111827; border: 1px solid #e5e7eb; }
button.delete { background: var(--bad); }
.loading { text-align: center; padding: 40px; color: var(--muted); }
</style>
</head>
<body>
<div class="wrap">
<div class="topbar">
<div class="pill">CBT β€’ μ˜€λ‹΅ & 볡슡 λ…ΈνŠΈ</div>
<div class="progress" id="progress">0 / 0</div>
</div>
<div class="card">
<div id="loading" class="loading">λΆˆλŸ¬μ˜€λŠ” 쀑...</div>
<div id="qContainer" style="display:none;">
<div class="qid" id="qid"></div>
<h2 class="qtext" id="qtext"></h2>
<div class="options" id="options"></div>
<div class="exp" id="exp"></div>
</div>
</div>
<div class="nav">
<button class="btn outline" id="homeBtn">🏠 ν™ˆ</button>
<button class="btn outline" id="prevBtn">← 이전</button>
<button class="btn outline" id="nextBtn">λ‹€μŒ β†’</button>
<div class="spacer"></div>
<button class="btn" id="showExpBtn">μ •λ‹΅ 보기</button>
<button class="btn delete" id="deleteBtn">πŸ—‘οΈ 제거</button>
</div>
</div>
<script>
let list = [];
let currentIndex = 0;
async function load() {
const res = await fetch("/api/wrong_review"); // βœ… 톡합 API μ‚¬μš©
const data = await res.json();
list = data.items || [];
if (list.length === 0) {
document.getElementById("loading").textContent = "βœ… μ˜€λ‹΅ / 볡슡 λͺ©λ‘μ΄ μ—†μŠ΅λ‹ˆλ‹€!";
return;
}
show();
}
function show() {
const q = list[currentIndex];
document.getElementById("progress").textContent = `${currentIndex+1} / ${list.length}`;
document.getElementById("qid").textContent = `문제 ID ${q.question_id}`;
document.getElementById("qtext").textContent = q.stem;
const optsEl = document.getElementById("options");
optsEl.innerHTML = "";
for (const [k, v] of Object.entries(q.options)) {
const d = document.createElement("div");
d.className = "opt";
if (k === q.answer) d.classList.add("correct");
if (q.chosen && k === q.chosen && k !== q.answer) d.classList.add("wrong");
if (q.chosen && k === q.chosen) d.classList.add("chosen");
d.innerHTML = `<b>${k}</b>. ${v}`;
optsEl.appendChild(d);
}
const expEl = document.getElementById("exp");
expEl.innerHTML = `<div class="title bad">μ •λ‹΅: ${q.answer}</div><div>${q.explanation || "ν•΄μ„€ μ—†μŒ"}</div>`;
expEl.classList.remove("show");
document.getElementById("loading").style.display = "none";
document.getElementById("qContainer").style.display = "block";
}
document.getElementById("showExpBtn").onclick = () => {
document.getElementById("exp").classList.add("show");
};
document.getElementById("prevBtn").onclick = () => {
if (currentIndex > 0) { currentIndex--; show(); }
};
document.getElementById("nextBtn").onclick = () => {
if (currentIndex < list.length - 1) { currentIndex++; show(); }
};
document.getElementById("homeBtn").onclick = () => {
window.location.href = "/";
};
document.getElementById("deleteBtn").onclick = async () => {
const q = list[currentIndex];
await fetch("/api/wrong_remove", {
method:"POST",
headers:{"Content-Type":"application/json"},
body:JSON.stringify({question_id:q.question_id})
});
await fetch("/api/review_remove", {
method:"POST",
headers:{"Content-Type":"application/json"},
body:JSON.stringify({question_id:q.question_id})
});
list.splice(currentIndex,1);
if (list.length === 0) location.reload();
if (currentIndex >= list.length) currentIndex = list.length - 1;
show();
};
load();
</script>
</body>
</html>