{{ texte[activeTab].md === null ? 'Generiere…' : 'Lade…' }}
diff --git a/frontend/src/components/TopicDetail.vue b/frontend/src/components/TopicDetail.vue index 4056d1c..45a1da9 100644 --- a/frontend/src/components/TopicDetail.vue +++ b/frontend/src/components/TopicDetail.vue @@ -4,6 +4,7 @@ import { fetchGuideContent, chatGuide, fetchBausteinLernstand } from '../api.js' import { renderMarkdown } from '../markdown.js' import { useChat } from '../composables/useChat.js' import BausteinPanel from './BausteinPanel.vue' +import BausteinFokus from './BausteinFokus.vue' const props = defineProps({ previewGuide: { type: Object, default: null }, @@ -57,6 +58,35 @@ function onBausteinStatus(baustein, status) { if (status.absolviert && !warAbsolviert) emit('progressChanged') // Locks/Stats neu laden } +// --- Vollbild-Fokus: ein Baustein groß, Guide links + Prüfung rechts --- +const fokusIndex = ref(null) // Index in der flachen Baustein-Liste; null = zu +const fokusTab = ref('pruefung') +const bausteine = computed(() => + isOnePager.value || !content.value ? [] : content.value.chapters.flatMap((ch) => ch.sections), +) +const fokusBaustein = computed(() => (fokusIndex.value === null ? null : bausteine.value[fokusIndex.value])) + +function openFokus(baustein, tab) { + const i = bausteine.value.findIndex((s) => s.title === baustein.title) + if (i === -1) return + fokusIndex.value = i + fokusTab.value = tab || 'pruefung' +} +function fokusPrev() { if (fokusIndex.value > 0) fokusIndex.value-- } +function fokusNext() { if (fokusIndex.value < bausteine.value.length - 1) fokusIndex.value++ } + +// Erfahrungsleiste: Lernstand über alle Bausteine des Guides (sticky, absolviert ⊇ verstanden ⊇ gemeistert). +const fortschritt = computed(() => { + let a = 0, v = 0, g = 0 + for (const s of bausteine.value) { + const l = lernstand.value[s.title] || {} + if (l.absolviert) a++ + if (l.verstanden) v++ + if (l.gemeistert) g++ + } + return { total: bausteine.value.length, absolviert: a, verstanden: v, gemeistert: g } +}) + // Cap pro Baustein folgt den erstellten Formaten: Guide vorhanden → bis 10, FullGuide → bis 25. const tier2 = computed(() => !!props.doneByFormat?.Guide) const tier3 = computed(() => !!props.doneByFormat?.FullGuide) @@ -163,7 +193,7 @@ function extractContext() { :class="['section-card', isOnePager && s.key ? 'op-card op-' + s.key : '', lernstand[s.title]?.gemeistert ? 'gemeistert' : (lernstand[s.title]?.verstanden ? 'verstanden' : (lernstand[s.title]?.absolviert ? 'absolviert' : ''))]" :style="isOnePager && s.key ? { gridArea: s.key } : null" > -Guide-Format anklicken um zu generieren oder Vorschau zu öffnen.