update
This commit is contained in:
@@ -35,8 +35,8 @@ export const api = {
|
||||
ueben: (topic) => req(`/api/topics/${e(topic)}/ueben`),
|
||||
antwort: (artefakt_id, richtig) =>
|
||||
req('/api/ueben/antwort', { method: 'POST', body: JSON.stringify({ artefakt_id, richtig }) }),
|
||||
bausteinKarten: (topic, bausteinId) =>
|
||||
req(`/api/topics/${e(topic)}/baustein/${e(bausteinId)}/karten`),
|
||||
bausteinKarten: (topic, bausteinId, alle = false) =>
|
||||
req(`/api/topics/${e(topic)}/baustein/${e(bausteinId)}/karten${alle ? '?alle=1' : ''}`),
|
||||
lernstand: (topic) => req(`/api/topics/${e(topic)}/lernstand`),
|
||||
bausteinFertig: (topic, bausteinId) =>
|
||||
req(`/api/topics/${e(topic)}/baustein/${e(bausteinId)}/fertig`, { method: 'POST', body: '{}' }),
|
||||
|
||||
@@ -66,6 +66,22 @@ function taste(e) {
|
||||
e.preventDefault()
|
||||
buehne.value?.scrollBy({ top: e.key === 'ArrowDown' ? 140 : -140, behavior: 'smooth' })
|
||||
}
|
||||
// Abruf: Leertaste deckt auf, 1 = falsch, 2 = richtig
|
||||
else if (screen.value.typ === 'abruf' && stapel.value.length) {
|
||||
if (e.key === ' ') { e.preventDefault(); zeigeAntwort.value = true }
|
||||
else if (zeigeAntwort.value && e.key === '1') antworten(false)
|
||||
else if (zeigeAntwort.value && e.key === '2') antworten(true)
|
||||
}
|
||||
// Prüfung: 1–4 toggeln die Aussagen, Leertaste prüft / blättert zum nächsten Panel
|
||||
else if (screen.value.typ === 'pruefung' && panel.value.length) {
|
||||
if (e.key === ' ') {
|
||||
e.preventDefault()
|
||||
aufloesung.value ? naechstesPanel() : pruefen()
|
||||
} else if (['1', '2', '3', '4'].includes(e.key)) {
|
||||
const x = panel.value[Number(e.key) - 1]
|
||||
if (x) toggle(x.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wisch-Navigation (mobil): klar horizontal + kurz genug = blättern.
|
||||
@@ -92,12 +108,23 @@ function wischEnde(e) {
|
||||
}
|
||||
|
||||
// ── Abrufprüfung (Karteikarten) ────────────────────────────────────────────────
|
||||
// Persistenz über Leitner (DB): richtig beantwortete Karten sind bis zur
|
||||
// Wiedervorlage nicht fällig und erscheinen beim nächsten Besuch nicht mehr.
|
||||
const stapel = ref([])
|
||||
const alleKarten = ref([]) // gefüllt, wenn alles absolviert → „Alle erneut üben"
|
||||
const zeigeAntwort = ref(false)
|
||||
const sende = ref(false)
|
||||
|
||||
async function abrufLaden(bausteinId) {
|
||||
zeigeAntwort.value = false
|
||||
alleKarten.value = []
|
||||
stapel.value = await api.bausteinKarten(props.topic, bausteinId)
|
||||
if (!stapel.value.length)
|
||||
alleKarten.value = await api.bausteinKarten(props.topic, bausteinId, true)
|
||||
}
|
||||
function nochmalAlle() {
|
||||
stapel.value = alleKarten.value
|
||||
alleKarten.value = []
|
||||
zeigeAntwort.value = false
|
||||
}
|
||||
async function antworten(richtig) {
|
||||
@@ -108,6 +135,7 @@ async function antworten(richtig) {
|
||||
await api.antwort(karte.id, richtig)
|
||||
stapel.value = richtig ? stapel.value.slice(1) : [...stapel.value.slice(1), karte]
|
||||
zeigeAntwort.value = false
|
||||
if (!stapel.value.length) await abrufLaden(screen.value.baustein)
|
||||
} finally { sende.value = false }
|
||||
}
|
||||
|
||||
@@ -215,14 +243,21 @@ onUnmounted(() => {
|
||||
<div class="lm-frage markdown" v-html="render(stapel[0].inhalt.frage)"></div>
|
||||
<div v-if="zeigeAntwort" class="lm-antwort markdown" v-html="render(stapel[0].inhalt.antwort)"></div>
|
||||
<div class="lm-karte-akt">
|
||||
<button v-if="!zeigeAntwort" @click="zeigeAntwort = true">Antwort zeigen</button>
|
||||
<button v-if="!zeigeAntwort" @click="zeigeAntwort = true">
|
||||
Antwort zeigen <kbd class="kurz">_</kbd></button>
|
||||
<template v-else>
|
||||
<button class="lm-falsch" @click="antworten(false)">Falsch</button>
|
||||
<button class="lm-richtig" @click="antworten(true)">Richtig</button>
|
||||
<button class="lm-falsch" @click="antworten(false)">
|
||||
Falsch <kbd class="kurz">1</kbd></button>
|
||||
<button class="lm-richtig" @click="antworten(true)">
|
||||
Richtig <kbd class="kurz">2</kbd></button>
|
||||
</template>
|
||||
</div>
|
||||
<div class="lm-rest">noch {{ stapel.length }} · Box {{ stapel[0].box }}</div>
|
||||
</div>
|
||||
<div v-else-if="alleKarten.length" class="lm-bestanden">
|
||||
✓ Alle Karten absolviert — Wiedervorlage folgt automatisch.<br />
|
||||
<button style="margin-top: 12px" @click="nochmalAlle">Alle erneut üben</button>
|
||||
</div>
|
||||
<div v-else class="lm-bestanden">✓ Abruf durch — weiter mit →</div>
|
||||
</section>
|
||||
|
||||
@@ -231,11 +266,12 @@ onUnmounted(() => {
|
||||
<template v-if="panel.length">
|
||||
<h3 class="pf-frage">Was gilt? <span class="pf-hinweis">(0–{{ panel.length }} Aussagen können wahr sein)</span></h3>
|
||||
<div class="pf-panel">
|
||||
<label v-for="x in panel" :key="x.id" class="pf-aussage"
|
||||
<label v-for="(x, i) in panel" :key="x.id" class="pf-aussage"
|
||||
:class="{ gewaehlt: auswahl.has(x.id),
|
||||
'pf-wahr': urteil(x.id) === true,
|
||||
'pf-falsch2': urteil(x.id) === false }"
|
||||
@click.prevent="toggle(x.id)">
|
||||
<kbd class="kurz">{{ i + 1 }}</kbd>
|
||||
<span class="markdown" v-html="render(x.text)"></span>
|
||||
</label>
|
||||
</div>
|
||||
@@ -243,8 +279,8 @@ onUnmounted(() => {
|
||||
{{ warRichtig ? '✓ Panel korrekt (+1)' : '✗ Nicht exakt (−1)' }}
|
||||
</div>
|
||||
<div class="pf-akt">
|
||||
<button v-if="!aufloesung" @click="pruefen">Prüfen</button>
|
||||
<button v-else @click="naechstesPanel">Nächstes Panel →</button>
|
||||
<button v-if="!aufloesung" @click="pruefen">Prüfen <kbd class="kurz">_</kbd></button>
|
||||
<button v-else @click="naechstesPanel">Nächstes Panel → <kbd class="kurz">_</kbd></button>
|
||||
<span v-if="fertig.has(screen.baustein)" class="lm-bestanden" style="margin: 0">✓ bestanden</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -340,6 +340,19 @@ table.kennzahlen th { color: var(--dim); }
|
||||
padding: 12px 14px; border: 1px solid var(--rand); border-radius: 10px;
|
||||
background: var(--karte);
|
||||
}
|
||||
/* Shortcut-Badge: echte Tastenkappe — Monospace-Ziffer, dickere Unterkante
|
||||
als 3D-Hinweis. „_" steht für die Leertaste. */
|
||||
kbd.kurz {
|
||||
display: inline-block; padding: 0 5px; margin-left: 8px;
|
||||
font: 600 10px/16px ui-monospace, 'SF Mono', Menlo, monospace;
|
||||
color: var(--dim); text-align: center;
|
||||
background: var(--bg); border: 1px solid var(--rand);
|
||||
border-bottom-width: 2px; border-radius: 5px;
|
||||
}
|
||||
/* Zahlen-Badge der Aussagen: absolut rechts oben, aus dem Textfluss raus */
|
||||
.pf-aussage { position: relative; }
|
||||
.pf-aussage kbd.kurz { position: absolute; top: 7px; right: 7px; margin: 0; }
|
||||
|
||||
/* Auswahl ohne Checkbox: die ganze Karte ist der Klickbereich */
|
||||
.pf-aussage.gewaehlt {
|
||||
border-color: var(--akzent);
|
||||
|
||||
Reference in New Issue
Block a user