From 8ce68eddd2a98270b3f76f75191f623499275edd Mon Sep 17 00:00:00 2001 From: sascha Date: Wed, 28 Jan 2026 21:29:40 +0000 Subject: [PATCH] =?UTF-8?q?app/static/script.js=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/static/script.js | 180 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 app/static/script.js diff --git a/app/static/script.js b/app/static/script.js new file mode 100644 index 0000000..5e1178e --- /dev/null +++ b/app/static/script.js @@ -0,0 +1,180 @@ +let currentCard = null; +let attempts = 0; +let stats = { points: 0, total: 0 }; + +document.addEventListener('DOMContentLoaded', loadLessons); + +function loadLessons() { + fetch('/api/lessons') + .then(res => res.json()) + .then(lessons => { + const list = document.getElementById('lesson-list'); + list.innerHTML = ''; + lessons.forEach(l => { + const div = document.createElement('div'); + div.className = 'lesson-item'; + div.innerHTML = ` + + + `; + list.appendChild(div); + }); + }); +} + +function updateStartBtn() { + const checked = document.querySelectorAll('#lesson-list input:checked'); + document.getElementById('btn-start').disabled = (checked.length === 0); +} + +function startQuiz() { + stats = { points: 0, total: 0 }; + updateStats(); + document.getElementById('setup-screen').style.display = 'none'; + document.getElementById('quiz-screen').style.display = 'flex'; + nextQuestion(); +} + +function stopQuiz() { + document.getElementById('quiz-screen').style.display = 'none'; + document.getElementById('setup-screen').style.display = 'block'; +} + +function nextQuestion() { + const btn = document.getElementById('btn-action'); + btn.innerText = "Prüfen"; + btn.onclick = checkAnswer; + btn.className = "action-btn primary"; + + document.getElementById('feedback').innerText = ''; + + const lids = Array.from(document.querySelectorAll('#lesson-list input:checked')).map(cb => cb.value); + const mid = document.getElementById('opt-middle').checked; + + fetch('/api/question', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ lessons: lids, askMiddle: mid }) + }) + .then(res => res.json()) + .then(card => { + if(card.error) { alert(card.error); stopQuiz(); return; } + currentCard = card; + attempts = 0; + renderCard(card); + }); +} + +function renderCard(card) { + document.getElementById('latin-text').innerText = card.latin; + document.getElementById('hint-text').innerText = card.hint; + + const container = document.getElementById('inputs-container'); + container.innerHTML = ''; + + if (card.middle_req) { + const row = document.createElement('div'); + row.className = 'input-row'; + row.innerHTML = ` + Form: + + `; + container.appendChild(row); + } + + card.german_correct.forEach(ans => { + const row = document.createElement('div'); + row.className = 'input-row'; + row.innerHTML = ` + Dt: + + `; + container.appendChild(row); + }); + + const first = container.querySelector('input'); + if(first) first.focus(); +} + +function checkAnswer() { + const inputs = document.querySelectorAll('.quiz-input'); + const payload = []; + inputs.forEach(i => { + payload.push({ + value: i.value, + correct: i.dataset.correct, + type: i.dataset.type || 'german' + }); + }); + + attempts++; + + fetch('/api/check', { + method: 'POST', + headers: {'Content-Type': 'application/json'}, + body: JSON.stringify({ inputs: payload, attempt: attempts }) + }) + .then(res => res.json()) + .then(res => { + const fb = document.getElementById('feedback'); + let globalMsg = ""; + + res.results.forEach((r, idx) => { + const el = inputs[idx]; + el.classList.remove('wrong', 'correct', 'typo', 'incomplete'); + + if (r.status === 'correct') { + el.classList.add('correct'); + } else if (r.status === 'typo') { + el.classList.add('typo'); + } else if (r.status === 'incomplete') { + el.classList.add('incomplete'); + globalMsg = r.msg; + } else { + el.classList.add('wrong'); + } + }); + + if (res.all_correct) { + fb.innerText = "Alles richtig!"; + fb.style.color = "green"; + stats.points += res.score; + finishTurn(); + } else { + if (res.has_incomplete) { + fb.innerText = globalMsg || "Unvollständig."; + fb.style.color = "#d39e00"; + } else { + if (attempts >= 3) { + fb.innerText = "Leider nicht geschafft. Lösungen eingesetzt."; + fb.style.color = "red"; + inputs.forEach(i => i.value = i.dataset.correct); + finishTurn(); + } else { + fb.innerText = `Fehler. Versuch ${attempts}/3`; + fb.style.color = "orange"; + } + } + } + }); +} + +function finishTurn() { + stats.total++; + updateStats(); + const btn = document.getElementById('btn-action'); + btn.innerText = "Weiter"; + btn.onclick = nextQuestion; + btn.focus(); +} + +function updateStats() { + let p = 0; + if (stats.total > 0) p = Math.round((stats.points / stats.total) * 100); + document.getElementById('progress-bar').style.width = `${p}%`; + document.getElementById('stats-text').innerText = `${p}% (${stats.points.toFixed(1)}/${stats.total})`; +} + +document.addEventListener('keypress', (e) => { + if (e.key === 'Enter') document.getElementById('btn-action').click(); +}); \ No newline at end of file