update
This commit is contained in:
@@ -14,6 +14,7 @@ const neuName = ref('')
|
||||
const neuArt = ref('thema')
|
||||
const fehler = ref('')
|
||||
const theme = ref(localStorage.getItem('theme') || 'auto')
|
||||
const guideRef = ref(null) // Header-Play-Button startet den Lernmodus im Guide
|
||||
// mobil (≤768px) startet die Navigation eingeklappt, sofern nie manuell gesetzt
|
||||
const navAuf = ref(localStorage.getItem('navAuf') !== null
|
||||
? localStorage.getItem('navAuf') !== '0'
|
||||
@@ -209,6 +210,8 @@ function runBadge(run) {
|
||||
<span v-if="state?.run?.grund" class="badge gelb">{{ state.run.grund }}</span>
|
||||
<span v-if="fehler" class="badge rot">{{ fehler }}</span>
|
||||
<span style="flex: 1"></span>
|
||||
<button v-if="tab === 'guide' && state" class="lm-start" title="Lernmodus (Vollbild)"
|
||||
@click="guideRef?.lesemodusStarten()">▶</button>
|
||||
<select v-model="theme" title="Farbschema">
|
||||
<option value="hell">hell</option>
|
||||
<option value="dunkel">dunkel</option>
|
||||
@@ -219,7 +222,7 @@ function runBadge(run) {
|
||||
<div class="inhalt">
|
||||
<Board v-if="tab === 'board'" :state="state" :topic="topic" @reload="stateLaden"
|
||||
@fehler="(e) => (fehler = e)" />
|
||||
<Guide v-else-if="tab === 'guide'" :topic="topic" :state="state" />
|
||||
<Guide v-else-if="tab === 'guide'" ref="guideRef" :topic="topic" :state="state" />
|
||||
<Ueben v-else-if="tab === 'üben'" :topic="topic" />
|
||||
<Kennzahlen v-else :run="state?.run" />
|
||||
</div>
|
||||
|
||||
@@ -55,6 +55,16 @@ const info = (key) => props.state?.ebenen?.find((e) => e.name === key) || {}
|
||||
const aktiveAtome = computed(() =>
|
||||
(props.state?.atome || []).filter((a) => !['gemerged', 'verworfen'].includes(a.status)))
|
||||
|
||||
// Spaltenkopf Artefakte: Gesamtfortschritt = Summe verifiziert / Summe Soll
|
||||
const artefakteSumme = computed(() => {
|
||||
let ok = 0, ziel = 0
|
||||
for (const a of aktiveAtome.value) {
|
||||
ok += a.artefakte?.verifiziert || 0
|
||||
ziel += a.artefakte?.gesamt || 0
|
||||
}
|
||||
return { ok, ziel }
|
||||
})
|
||||
|
||||
function karten(key) {
|
||||
const s = props.state
|
||||
if (!s) return []
|
||||
@@ -146,7 +156,11 @@ const k = (n) => (n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1000 ? `${Math.ro
|
||||
<div class="spaltekopf">
|
||||
<div class="zeile">
|
||||
<span class="titel">{{ e.titel }}
|
||||
<span class="badge">{{ karten(e.key).length }}</span></span>
|
||||
<span class="badge">{{ karten(e.key).length }}</span>
|
||||
<span v-if="e.key === 'artefakte' && artefakteSumme.ziel" class="badge"
|
||||
:class="artefakteSumme.ok >= artefakteSumme.ziel ? 'gruen' : ''">
|
||||
{{ artefakteSumme.ok }}/{{ artefakteSumme.ziel }} verifiziert
|
||||
</span></span>
|
||||
<span class="badge" :class="info(e.key).laeuft ? 'blau' : info(e.key).fertig ? 'gruen' : ''">
|
||||
{{ info(e.key).laeuft ? 'läuft' : info(e.key).fertig ? 'fertig' : 'offen' }}
|
||||
</span>
|
||||
|
||||
@@ -6,6 +6,8 @@ import Lesemodus from './Lesemodus.vue'
|
||||
|
||||
const props = defineProps({ topic: String, state: Object })
|
||||
const lesemodus = ref(false) // Vollbild-Lernmodus (Fundament + Abrufprüfung)
|
||||
// Header-Play-Button (App.vue) startet den Lernmodus von außen
|
||||
defineExpose({ lesemodusStarten: () => { lesemodus.value = true } })
|
||||
const daten = ref(null)
|
||||
const level = ref('E') // Durchgang-Wahl: jede Stufe ist ein eigener Lese-Durchgang
|
||||
const ansicht = ref('erklaerend') // erklaerend = Fließtext | kompakt = Stichpunkte
|
||||
@@ -158,8 +160,6 @@ function onScroll(e) {
|
||||
</button>
|
||||
<button class="schalter-solo" title="Fokus-Modus (ablenkungsfrei lesen)"
|
||||
@click="fokus = true">⛶</button>
|
||||
<button v-if="daten" class="schalter-solo lm-start" title="Lernmodus (Vollbild)"
|
||||
@click="lesemodus = true">▶</button>
|
||||
</div>
|
||||
<div class="fortschritt">
|
||||
<div>Kapitel {{ aktiv + 1 }} / {{ anzeige.length }}</div>
|
||||
|
||||
@@ -61,6 +61,24 @@ function taste(e) {
|
||||
else if (e.key === 'ArrowLeft') zurueck()
|
||||
}
|
||||
|
||||
// Wisch-Navigation (mobil): klar horizontal + kurz genug = blättern.
|
||||
// Vertikales Scrollen und Text-Markieren bleiben unberührt (dy-Vergleich).
|
||||
let wisch = null
|
||||
function wischStart(e) {
|
||||
const t = e.touches[0]
|
||||
wisch = { x: t.clientX, y: t.clientY }
|
||||
}
|
||||
function wischEnde(e) {
|
||||
if (!wisch) return
|
||||
const t = e.changedTouches[0]
|
||||
const dx = t.clientX - wisch.x
|
||||
const dy = t.clientY - wisch.y
|
||||
wisch = null
|
||||
if (Math.abs(dx) < 60 || Math.abs(dx) < 2 * Math.abs(dy)) return
|
||||
if (dx < 0) vor()
|
||||
else zurueck()
|
||||
}
|
||||
|
||||
// ── Abrufprüfung (Karteikarten) ────────────────────────────────────────────────
|
||||
const stapel = ref([])
|
||||
const zeigeAntwort = ref(false)
|
||||
@@ -155,7 +173,8 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="wurzel" class="lesemodus">
|
||||
<div ref="wurzel" class="lesemodus"
|
||||
@touchstart.passive="wischStart" @touchend.passive="wischEnde">
|
||||
<header class="lm-kopf">
|
||||
<span class="lm-fort">{{ fortschrittText }}</span>
|
||||
<button class="lm-x" title="Schließen" @click="schliessen">✕</button>
|
||||
@@ -205,7 +224,6 @@ onUnmounted(() => {
|
||||
'pf-wahr': urteil(x.id) === true,
|
||||
'pf-falsch2': urteil(x.id) === false }"
|
||||
@click.prevent="toggle(x.id)">
|
||||
<input type="checkbox" :checked="auswahl.has(x.id)" @click.stop="toggle(x.id)" />
|
||||
<span class="markdown" v-html="render(x.text)"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -332,8 +332,12 @@ table.kennzahlen th { color: var(--dim); }
|
||||
padding: 12px 14px; border: 1px solid var(--rand); border-radius: 10px;
|
||||
background: var(--karte);
|
||||
}
|
||||
.pf-aussage input { margin-top: 5px; flex: 0 0 auto; }
|
||||
.pf-aussage.gewaehlt { border-color: var(--akzent); }
|
||||
/* Auswahl ohne Checkbox: die ganze Karte ist der Klickbereich */
|
||||
.pf-aussage.gewaehlt {
|
||||
border-color: var(--akzent);
|
||||
background: color-mix(in srgb, var(--akzent) 10%, var(--karte));
|
||||
box-shadow: inset 3px 0 0 var(--akzent);
|
||||
}
|
||||
.pf-aussage.pf-wahr { border-color: #2f7d32; background: color-mix(in srgb, #2f7d32 14%, var(--karte)); }
|
||||
.pf-aussage.pf-falsch2 { border-color: #a23b3b; background: color-mix(in srgb, #a23b3b 12%, var(--karte)); }
|
||||
.pf-feedback { margin-top: 14px; padding: 10px 14px; border-radius: 8px; font-size: 15px; }
|
||||
|
||||
Reference in New Issue
Block a user