This commit is contained in:
team3
2026-09-30 14:53:23 +02:00
parent fd7893b5d2
commit 817f39a42c
6 changed files with 187 additions and 0 deletions

View File

@@ -13,6 +13,7 @@ import NamensWahl from './components/NamensWahl.vue'
import FilmLogin from './components/FilmLogin.vue'
import VerwaltungTab from './components/VerwaltungTab.vue'
import WuenscheTab from './components/WuenscheTab.vue'
import InfoTab from './components/InfoTab.vue'
import SearchTab from './components/SearchTab.vue'
import StreamTab from './components/StreamTab.vue'
import WatchedTab from './components/WatchedTab.vue'
@@ -150,6 +151,7 @@ const tabs = computed(() => [
label: 'Wünsche',
count: wuensche.value.filter((w) => !w.done_at).length,
},
{ id: 'info', label: 'Info', count: null },
...(host.value || angemeldet.value
? [{ id: 'verwaltung', label: 'Verwaltung', count: null }]
: []),
@@ -430,6 +432,8 @@ onMounted(load)
@changed="ladeWuensche"
/>
<InfoTab v-else-if="activeTab === 'info'" :host="host" />
<VerwaltungTab v-else-if="activeTab === 'verwaltung'" :items="runde" :host="host" :ich="ich" />
<StreamTab v-else-if="activeTab === 'stream'" :angemeldet="angemeldet" />

View File

@@ -0,0 +1,114 @@
<script setup>
// Ein Markdown-Text, mehr nicht: PayPal, IBAN, Regeln, was man wissen
// muss. Der Host schreibt ihn hier direkt; bis dahin steht die Vorlage
// mit den Punkteregeln.
import { onMounted, onUnmounted, ref } from 'vue'
import { abonnieren } from '../live'
import { rendern } from '../markdown'
import MarkdownFeld from './MarkdownFeld.vue'
defineProps({ host: Boolean })
const text = ref('')
const laden = ref(true)
const bearbeitet = ref(false)
const entwurf = ref('')
const fehler = ref('')
async function laden_() {
try {
const resp = await fetch('/api/info')
if (!resp.ok) throw new Error('Infos konnten nicht geladen werden')
text.value = (await resp.json()).text
fehler.value = ''
} catch (err) {
fehler.value = err.message
} finally {
laden.value = false
}
}
function bearbeiten() {
entwurf.value = text.value
bearbeitet.value = true
}
async function speichern() {
const resp = await fetch('/api/info', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ text: entwurf.value }),
})
if (!resp.ok) {
fehler.value = 'Speichern hat nicht geklappt.'
return
}
bearbeitet.value = false
laden_()
}
let abbestellen = null
onMounted(() => {
laden_()
abbestellen = abonnieren((nachricht) => {
if (nachricht.type === 'info') laden_()
})
})
onUnmounted(() => abbestellen?.())
</script>
<template>
<div class="info-tab">
<p v-if="laden" class="note">Lade …</p>
<p v-else-if="fehler" class="note error">{{ fehler }}</p>
<MarkdownFeld
v-else-if="bearbeitet"
v-model="entwurf"
platzhalter="PayPal, IBAN, Regeln, was man wissen muss …"
knopf="Speichern"
:maxlaenge="8000"
@senden="speichern"
@abbrechen="bearbeitet = false"
/>
<template v-else>
<div class="oben">
<button v-if="host" type="button" class="klein" @click="bearbeiten">Bearbeiten</button>
</div>
<div class="markdown" v-html="rendern(text)"></div>
</template>
</div>
</template>
<style scoped>
.info-tab {
max-width: 640px;
}
.oben {
margin-bottom: 0.6rem;
}
.klein {
padding: 0.2rem 0.55rem;
color: var(--muted);
font-size: 0.72rem;
border: 1px solid var(--line);
border-radius: 6px;
}
.klein:hover {
color: var(--text);
}
.note {
padding: 2.5rem 0;
color: var(--muted);
text-align: center;
}
.note.error {
color: var(--accent);
}
</style>

View File

@@ -35,6 +35,7 @@ const TAB_IDS = [
'merkliste',
'watched',
'wuensche',
'info',
'verwaltung',
'stream',
'clips',