This commit is contained in:
team3
2026-06-17 22:56:24 +02:00
parent 0ff33271a0
commit dce9156ac8
17 changed files with 743 additions and 42 deletions

View File

@@ -1,5 +1,6 @@
<script setup>
import BausteinPanel from './BausteinPanel.vue'
import SubbausteinView from './SubbausteinView.vue'
import { renderMarkdown } from '../markdown.js'
const props = defineProps({
@@ -52,7 +53,8 @@ const standFarbe = computed(() => {
</div>
<div class="fokus-body">
<div class="fokus-col left">
<div class="markdown" v-html="renderMarkdown(baustein.md)"></div>
<div v-if="!baustein.subbausteine?.length" class="markdown" v-html="renderMarkdown(baustein.md)"></div>
<SubbausteinView v-else :subbausteine="baustein.subbausteine" :md="baustein.md" />
</div>
<div class="fokus-col right">
<BausteinPanel

View File

@@ -0,0 +1,105 @@
<script setup>
import { ref, computed } from 'vue'
import { renderMarkdown } from '../markdown.js'
const props = defineProps({
subbausteine: { type: Array, default: null },
md: { type: String, default: '' },
})
const STUFEN = ['einfach', 'mittel', 'schwer']
const rang = (s) => {
const i = STUFEN.indexOf(s)
return i < 0 ? 0 : i
}
// 0 = nur einfach (Default), 1 = + mittel, 2 = alle
const stufe = ref(0)
const labels = ['Einfach', '+ Mittel', 'Alle']
const hatSubs = computed(() => Array.isArray(props.subbausteine) && props.subbausteine.length > 0)
const sichtbar = computed(() => {
if (!hatSubs.value) return []
const gefiltert = props.subbausteine.filter((s) => rang(s.stufe) <= stufe.value)
return gefiltert.length ? gefiltert : props.subbausteine // nie ganz leer anzeigen
})
const verborgen = computed(() => (hatSubs.value ? props.subbausteine.length - sichtbar.value.length : 0))
</script>
<template>
<div v-if="hatSubs">
<div class="subs-filter">
<button v-for="(lab, i) in labels" :key="i" :class="{ active: stufe === i }" @click="stufe = i">{{ lab }}</button>
<span v-if="verborgen > 0" class="subs-hidden">{{ verborgen }} ausgeblendet</span>
</div>
<div v-for="(s, i) in sichtbar" :key="i" :class="['sub', 'stufe-' + s.stufe]">
<div class="sub-head">
<span class="sub-pill">{{ s.stufe }}</span>
<span class="sub-titel">{{ s.titel }}</span>
</div>
<div class="markdown" v-html="renderMarkdown(s.md)"></div>
</div>
</div>
<div v-else class="markdown" v-html="renderMarkdown(md)"></div>
</template>
<style scoped>
.subs-filter {
display: flex;
gap: 0.4rem;
align-items: center;
flex-wrap: wrap;
margin-bottom: 0.9rem;
}
.subs-filter button {
padding: 0.2rem 0.7rem;
font-size: 0.8rem;
cursor: pointer;
border: 1px solid var(--border-strong);
border-radius: 999px;
background: var(--panel);
color: var(--text-muted);
}
.subs-filter button.active {
background: var(--accent);
border-color: var(--accent);
color: var(--on-accent);
}
.subs-hidden {
font-size: 0.75rem;
color: var(--text-faint);
}
/* Ampel je Stufe: farbiger linker Rand + zarter Hintergrund. */
.sub {
border-left: 3px solid var(--sub-c);
background: color-mix(in srgb, var(--sub-c) 7%, var(--panel));
border-radius: 0 8px 8px 0;
padding: 0.6rem 0.9rem;
margin-bottom: 0.7rem;
}
.sub.stufe-einfach { --sub-c: var(--stufe-einfach); }
.sub.stufe-mittel { --sub-c: var(--stufe-mittel); }
.sub.stufe-schwer { --sub-c: var(--stufe-schwer); }
.sub-head {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.35rem;
}
.sub-pill {
font-size: 0.65rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.04em;
padding: 0.08rem 0.45rem;
border-radius: 999px;
color: #fff;
background: var(--sub-c);
}
.sub-titel {
font-weight: 600;
font-size: 0.9rem;
color: var(--text);
}
.sub .markdown :deep(p:last-child) { margin-bottom: 0; }
</style>

View File

@@ -5,6 +5,7 @@ import { renderMarkdown } from '../markdown.js'
import { useChat } from '../composables/useChat.js'
import BausteinPanel from './BausteinPanel.vue'
import BausteinFokus from './BausteinFokus.vue'
import SubbausteinView from './SubbausteinView.vue'
const props = defineProps({
previewGuide: { type: Object, default: null },
@@ -199,7 +200,8 @@ function extractContext() {
<span v-else-if="lernstand[s.title]?.verstanden" class="baustein-done verstanden" title="Vollständig verstanden (10/10)"> Verstanden</span>
<span v-else-if="lernstand[s.title]?.absolviert" class="baustein-done" title="Prüfung bestanden"> Absolviert</span>
</h3>
<div class="section-body markdown" v-html="renderMarkdown(s.md)"></div>
<div v-if="isOnePager || !s.subbausteine?.length" class="section-body markdown" v-html="renderMarkdown(s.md)"></div>
<SubbausteinView v-else class="section-body" :subbausteine="s.subbausteine" :md="s.md" />
<BausteinPanel
v-if="!isOnePager"
mode="trigger"