This commit is contained in:
team3
2026-09-17 15:40:28 +02:00
parent a1684cf54f
commit ea54a86db4
30 changed files with 3680 additions and 989 deletions

View File

@@ -4,6 +4,7 @@ import MovieCard from './components/MovieCard.vue'
import FilterSidebar from './components/FilterSidebar.vue'
import AehnlichTab from './components/AehnlichTab.vue'
import MerklisteTab from './components/MerklisteTab.vue'
import SammlungFilter from './components/SammlungFilter.vue'
import MovieDetail from './components/MovieDetail.vue'
import NamensWahl from './components/NamensWahl.vue'
import VerwaltungTab from './components/VerwaltungTab.vue'
@@ -29,6 +30,11 @@ const {
wuensche, ladeWuensche,
} = useMeins({ host })
// Ohne gewählten Namen darf man alles lesen, aber nichts eintragen —
// für Zuschauer, die noch nicht in der Runde stehen. Steht vor tabs: die
// Reiterliste fragt danach.
const angemeldet = computed(() => !!ich.value)
const {
movies, loading, error, load,
netflixMovies, canonMovies, canonGroups, netflixEntries, SORTS,
@@ -84,16 +90,42 @@ const tabs = computed(() => [
{ id: 'stream', label: 'Stream', count: null },
{ id: 'watched', label: 'Gesehen', count: gesehenZahl.value },
{ id: 'wuensche', label: 'Wünsche', count: wuensche.value.filter((w) => !w.done_at).length },
...(host.value ? [{ id: 'verwaltung', label: 'Verwaltung', count: null }] : []),
...(host.value || angemeldet.value
? [{ id: 'verwaltung', label: 'Verwaltung', count: null }]
: []),
])
// Auf dem Handy passt die Filterleiste nicht neben die Karten — dort
// legt sie sich über einen Knopf über die Seite
const filterOffen = ref(false)
const mitFilter = computed(() =>
['netflix', 'canon', 'search', 'aehnlich'].includes(activeTab.value)
['netflix', 'canon', 'search', 'aehnlich', 'merkliste'].includes(activeTab.value)
)
// Der Sammlungen-Reiter filtert nach Person und Genre, nicht nach Regler —
// dafür hat er eine eigene Leiste
const sammlungLeute = ref([])
const sammlungHorror = ref(null)
// Wer überhaupt etwas gesammelt hat, mit Anzahl. Die eigene zuerst.
const leuteMitSammlung = computed(() => {
const nach = new Map()
for (const eintrag of merkliste.value) {
const name = eintrag.name || 'Anonym'
if (!nach.has(name)) nach.set(name, { name, anzahl: 0, mine: eintrag.mine })
nach.get(name).anzahl += 1
}
return [...nach.values()].sort(
(a, b) => b.mine - a.mine || a.name.localeCompare(b.name, 'de')
)
})
// Fällt der offene Reiter weg — Hostmodus aus, Name abgewählt —, wäre
// sonst keiner markiert und die Seite bliebe leer
watch(tabs, (liste) => {
if (!liste.some((t) => t.id === activeTab.value)) activeTab.value = 'netflix'
})
// Passen die Reiter nicht in eine Zeile, soll der offene sichtbar sein
const reiter = ref(null)
@@ -105,10 +137,6 @@ watch(activeTab, async () => {
leiste.querySelector('.active')?.scrollIntoView({ inline: 'center', block: 'nearest' })
})
// Ohne gewählten Namen darf man alles lesen, aber nichts eintragen —
// für Zuschauer, die noch nicht in der Runde stehen
const angemeldet = computed(() => !!ich.value)
const selected = ref(null)
// Der Katalog liefert nur sechs Bildpfade je Film. Beim Öffnen holen wir
@@ -193,7 +221,12 @@ onMounted(load)
Filter
</button>
<span v-if="host" class="host">Host</span>
<NamensWahl :items="runde" :mine="ich" @waehlen="michSetzen" />
<NamensWahl
:items="runde"
:mine="ich"
:host="host"
:anmelden="michSetzen"
/>
</div>
</header>
@@ -256,15 +289,27 @@ onMounted(load)
@changed="ladeGesehen"
/>
<MerklisteTab
v-else-if="activeTab === 'merkliste'"
:angemeldet="angemeldet"
:gesehen-ids="gesehenIds"
:items="merkliste"
:ich="ich"
@open="selected = $event"
@changed="ladeMerkliste"
/>
<div v-else-if="activeTab === 'merkliste'" class="layout">
<MerklisteTab
:angemeldet="angemeldet"
:gesehen-ids="gesehenIds"
:items="merkliste"
:ich="ich"
:ansicht="ansicht"
:leute="sammlungLeute"
:horror="sammlungHorror"
@open="filmOeffnen"
@changed="ladeMerkliste"
/>
<SammlungFilter
v-model:gewaehlt="sammlungLeute"
v-model:horror="sammlungHorror"
v-model:ansicht="ansicht"
:class="{ offen: filterOffen }"
:leute="leuteMitSammlung"
/>
</div>
<WuenscheTab
v-else-if="activeTab === 'wuensche'"
@@ -275,7 +320,12 @@ onMounted(load)
@changed="ladeWuensche"
/>
<VerwaltungTab v-else-if="activeTab === 'verwaltung'" :items="runde" />
<VerwaltungTab
v-else-if="activeTab === 'verwaltung'"
:items="runde"
:host="host"
:ich="ich"
/>
<StreamTab v-else-if="activeTab === 'stream'" />