145 lines
5.3 KiB
JavaScript
145 lines
5.3 KiB
JavaScript
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">문항 수 (1–20)</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);
|