Files
cogmind/public/optionPage.js
T
2026-08-10 21:35:17 +09:00

145 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const DIFFICULTIES = [
{ id: 'easy', label: '쉬움' },
{ id: 'medium', label: '보통' },
{ id: 'hard', label: '어려움' },
];
const fillSelect = (select, values) => {
select.replaceChildren(
...values.map((value) => {
const option = document.createElement('option');
option.value = value;
option.textContent = value;
return option;
})
);
select.disabled = values.length === 0;
};
class OptionPage extends HTMLElement {
async connectedCallback() {
this.className = 'screen';
this.innerHTML = `
<div class="hero">
<picture>
<source srcset="/public/images/logo-dark.png"
media="(prefers-color-scheme: dark)">
<img src="/public/images/logo-light.png" alt="CogMind">
</picture>
<h1>공부의 시작은 나를 아는것</h1>
<p>문제를 풀면 AI가 여러분을 메타인지하고 피드백 해줘요.</p>
</div>
<div class="card">
<div class="field">
<label for="student">이름</label>
<input id="student" type="text" placeholder="예: 이승준" autocomplete="off"
maxlength="30">
</div>
<div class="field">
<label for="school">학교 종류</label>
<select id="school"></select>
</div>
<div class="row" style="margin-top:16px">
<div class="field" style="margin:0">
<label for="subject">과목</label>
<select id="subject"></select>
</div>
<div class="field" style="margin:0">
<label for="chapter">단원</label>
<select id="chapter"></select>
</div>
</div>
<div class="row" style="margin-top:16px">
<div class="field" style="margin:0">
<label>난이도</label>
<div id="difficulty"></div>
</div>
<div class="field" style="margin:0">
<label for="amount">문항 수 (120)</label>
<input id="amount" type="number" min="1" max="20" value="5">
</div>
</div>
<div id="error"></div>
<button class="primary block" id="start" style="margin-top:24px">
학습 진단 시작하기
</button>
<button class="block" id="history" style="margin-top:10px">
지난 기록 보기
</button>
</div>
`;
const errorBox = this.querySelector('#error');
const showMessage = (message) => {
errorBox.className = message ? 'error-box' : '';
errorBox.textContent = message ?? '';
};
if (this.dataset.error) showMessage(this.dataset.error);
this.querySelector('#history').onclick = () => showHistoryScreen();
let difficulty = 'medium';
this.querySelector('#difficulty').appendChild(
createChipGroup(DIFFICULTIES, {
selected: difficulty,
onSelect: (value) => {
difficulty = value;
},
})
);
const school = this.querySelector('#school');
const subject = this.querySelector('#subject');
const chapter = this.querySelector('#chapter');
const student = this.querySelector('#student');
const amount = this.querySelector('#amount');
const startButton = this.querySelector('#start');
let chapters = {};
const onSchoolChange = () => {
fillSelect(subject, Object.keys(chapters[school.value] ?? {}));
onSubjectChange();
};
const onSubjectChange = () => {
fillSelect(chapter, chapters[school.value]?.[subject.value] ?? []);
};
school.onchange = onSchoolChange;
subject.onchange = onSubjectChange;
startButton.disabled = true;
try {
chapters = await api.chapters();
fillSelect(school, Object.keys(chapters));
onSchoolChange();
startButton.disabled = false;
} catch (err) {
showMessage(`단원 목록을 불러오지 못했습니다. ${err.message}`);
return;
}
const submit = () => {
if (!chapter.value) {
showMessage('과목과 단원을 선택해 주세요.');
return;
}
startQuiz(
{
student: student.value.trim() || '학생',
school: school.value,
subject: subject.value,
chapter: chapter.value,
difficulty,
},
Math.min(Math.max(Number(amount.value) || 5, 1), 20)
);
};
startButton.onclick = submit;
student.addEventListener('keydown', (event) => {
if (event.key === 'Enter') submit();
});
}
}
customElements.define('option-page', OptionPage);