first commit
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
class HistoryPage extends HTMLElement {
|
||||
async connectedCallback() {
|
||||
this.className = 'screen';
|
||||
this.replaceChildren(createTopbar([createButton('새 시험 시작', () => showStartScreen())]));
|
||||
|
||||
const heading = document.createElement('h1');
|
||||
heading.className = 'page-title';
|
||||
heading.textContent = '지난 기록';
|
||||
this.appendChild(heading);
|
||||
|
||||
const body = document.createElement('div');
|
||||
body.innerHTML = `<div class="inline-loading"><span class="spinner small"></span>
|
||||
<span>기록을 불러오는 중이에요…</span></div>`;
|
||||
this.appendChild(body);
|
||||
|
||||
let tests;
|
||||
try {
|
||||
({ tests } = await api.tests());
|
||||
} catch (err) {
|
||||
body.replaceChildren();
|
||||
const error = document.createElement('p');
|
||||
error.className = 'error-box';
|
||||
error.textContent = err.message;
|
||||
body.appendChild(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tests.length) {
|
||||
body.replaceChildren();
|
||||
const empty = document.createElement('div');
|
||||
empty.className = 'card empty';
|
||||
empty.innerHTML = `<p>아직 저장된 기록이 없습니다.</p>`;
|
||||
empty.appendChild(
|
||||
createButton('첫 시험 시작하기', () => showStartScreen(), 'primary')
|
||||
);
|
||||
body.appendChild(empty);
|
||||
return;
|
||||
}
|
||||
|
||||
body.replaceChildren(this.renderStats(tests), this.renderList(tests));
|
||||
}
|
||||
|
||||
renderStats(tests) {
|
||||
const totals = tests.reduce(
|
||||
(acc, test) => ({
|
||||
questions: acc.questions + test.score.total,
|
||||
correct: acc.correct + test.score.correct,
|
||||
overconfident: acc.overconfident + test.score.overconfident,
|
||||
}),
|
||||
{ questions: 0, correct: 0, overconfident: 0 }
|
||||
);
|
||||
|
||||
const card = document.createElement('div');
|
||||
card.className = 'card';
|
||||
card.innerHTML = `
|
||||
<div class="insight">
|
||||
<div><strong></strong>본 시험</div>
|
||||
<div><strong></strong>푼 문제</div>
|
||||
<div><strong></strong>평균 정답률</div>
|
||||
<div class="${totals.overconfident ? 'danger' : ''}">
|
||||
<strong></strong>확신했지만 틀림
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
const tiles = card.querySelectorAll('.insight strong');
|
||||
tiles[0].textContent = tests.length;
|
||||
tiles[1].textContent = totals.questions;
|
||||
tiles[2].textContent = `${Math.round((totals.correct / totals.questions) * 100)}%`;
|
||||
tiles[3].textContent = totals.overconfident;
|
||||
card.querySelector('.insight').classList.toggle('risk', totals.overconfident > 0);
|
||||
return card;
|
||||
}
|
||||
|
||||
renderList(tests) {
|
||||
const list = document.createElement('div');
|
||||
list.className = 'result-list';
|
||||
|
||||
tests.forEach((test) => {
|
||||
const item = document.createElement('button');
|
||||
item.type = 'button';
|
||||
item.className = 'card history-item';
|
||||
item.onclick = () => showHistoryDetail(test.id);
|
||||
|
||||
const top = document.createElement('div');
|
||||
top.className = 'history-top';
|
||||
const range = document.createElement('span');
|
||||
range.className = 'history-range';
|
||||
range.textContent = `${test.school} ${test.subject} · ${test.chapter}`;
|
||||
const percent = document.createElement('span');
|
||||
percent.className = 'history-score';
|
||||
percent.textContent = `${test.score.percent}점`;
|
||||
top.append(range, percent);
|
||||
|
||||
const meta = document.createElement('p');
|
||||
meta.className = 'muted';
|
||||
meta.textContent =
|
||||
`${test.student} · ${formatDate(test.createdAt)} · ` +
|
||||
`난이도 ${DIFFICULTY_LABEL[test.difficulty] ?? test.difficulty} · ` +
|
||||
`${test.score.total}문제 중 ${test.score.correct}문제 정답`;
|
||||
|
||||
const tags = document.createElement('p');
|
||||
tags.className = 'history-tags';
|
||||
const badges = [];
|
||||
if (test.score.overconfident) {
|
||||
badges.push(['bad', `확신했지만 틀림 ${test.score.overconfident}`]);
|
||||
}
|
||||
if (test.explainedCount) badges.push(['', `해설 ${test.explainedCount}`]);
|
||||
if (test.twinCount) badges.push(['', `쌍둥이 문제 ${test.twinCount}`]);
|
||||
if (test.askedCount) badges.push(['', `후속 질문 ${test.askedCount}`]);
|
||||
badges.forEach(([tone, label]) => {
|
||||
const badge = document.createElement('span');
|
||||
badge.className = `badge ${tone}`.trim();
|
||||
badge.textContent = label;
|
||||
tags.appendChild(badge);
|
||||
});
|
||||
|
||||
item.append(top, meta, tags);
|
||||
list.appendChild(item);
|
||||
});
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('history-page', HistoryPage);
|
||||
Reference in New Issue
Block a user