update
This commit is contained in:
@@ -4,6 +4,7 @@ import MovieCard from './components/MovieCard.vue'
|
||||
import FilterSidebar from './components/FilterSidebar.vue'
|
||||
import AehnlichTab from './components/AehnlichTab.vue'
|
||||
import KiTab from './components/KiTab.vue'
|
||||
import PersonenTab from './components/PersonenTab.vue'
|
||||
import MerklisteTab from './components/MerklisteTab.vue'
|
||||
import SammlungFilter from './components/SammlungFilter.vue'
|
||||
import MovieDetail from './components/MovieDetail.vue'
|
||||
@@ -24,11 +25,20 @@ import { useLangeListe } from './composables/useLangeListe'
|
||||
const { ansicht, ohneGesehene, activeTab, quelle, suchArt, host } = useEinstellungen()
|
||||
|
||||
const {
|
||||
runde, ich, michSetzen,
|
||||
gesehen, gesehenIds, gesehenZahl, ladeGesehen,
|
||||
meinVorschlag, aufDemRad, ladeVorschlag,
|
||||
merkliste, ladeMerkliste,
|
||||
wuensche, ladeWuensche,
|
||||
runde,
|
||||
ich,
|
||||
michSetzen,
|
||||
gesehen,
|
||||
gesehenIds,
|
||||
gesehenZahl,
|
||||
ladeGesehen,
|
||||
meinVorschlag,
|
||||
aufDemRad,
|
||||
ladeVorschlag,
|
||||
merkliste,
|
||||
ladeMerkliste,
|
||||
wuensche,
|
||||
ladeWuensche,
|
||||
} = useMeins({ host })
|
||||
|
||||
// Ohne gewählten Namen darf man alles lesen, aber nichts eintragen —
|
||||
@@ -37,44 +47,74 @@ const {
|
||||
const angemeldet = computed(() => !!ich.value)
|
||||
|
||||
const {
|
||||
movies, loading, error, load,
|
||||
netflixMovies, canonMovies, canonGroups, netflixEntries, SORTS,
|
||||
movies,
|
||||
loading,
|
||||
error,
|
||||
load,
|
||||
netflixMovies,
|
||||
canonMovies,
|
||||
canonGroups,
|
||||
netflixEntries,
|
||||
SORTS,
|
||||
} = useKatalog()
|
||||
|
||||
const {
|
||||
search, sort, suchSort, include, exclude, grenzen, ranges, genreOptions,
|
||||
toggleGenre, toggleAll, resetGenres, nichtGesehen, passt, suchFilter,
|
||||
} = useFilter({ activeTab, quelle, netflixMovies, canonMovies, gesehenIds, ohneGesehene })
|
||||
search,
|
||||
sort,
|
||||
suchSort,
|
||||
suchAnzahl,
|
||||
include,
|
||||
exclude,
|
||||
grenzen,
|
||||
ranges,
|
||||
genreOptions,
|
||||
toggleGenre,
|
||||
toggleAll,
|
||||
resetGenres,
|
||||
nichtGesehen,
|
||||
passt,
|
||||
suchFilter,
|
||||
} = useFilter({
|
||||
activeTab,
|
||||
quelle,
|
||||
suchArt,
|
||||
netflixMovies,
|
||||
canonMovies,
|
||||
gesehenIds,
|
||||
ohneGesehene,
|
||||
})
|
||||
|
||||
// Eine Reihe erscheint, sobald ein Teil passt — sortiert wird sie über
|
||||
// ihren stärksten Teil
|
||||
function filterGruppen(entries, term) {
|
||||
return entries
|
||||
.filter(
|
||||
(e) =>
|
||||
e.parts.some((m) => passt(m)) &&
|
||||
(!term || e.parts.some((m) => matches(m, term)))
|
||||
(e) => e.parts.some((m) => passt(m)) && (!term || e.parts.some((m) => matches(m, term))),
|
||||
)
|
||||
.sort((a, b) => SORTS[sort.value](a.parts[a.best], b.parts[b.best]))
|
||||
}
|
||||
|
||||
const visible = computed(() =>
|
||||
filterGruppen(netflixEntries.value, search.value.trim().toLowerCase())
|
||||
filterGruppen(netflixEntries.value, search.value.trim().toLowerCase()),
|
||||
)
|
||||
|
||||
// Im Kanon greift die Suche auf die ganze Reihe: wer "Saw" sucht, will den
|
||||
// Eintrag sehen, egal welcher Teil gerade vorne liegt.
|
||||
const visibleCanon = computed(() =>
|
||||
filterGruppen(canonGroups.value, search.value.trim().toLowerCase())
|
||||
filterGruppen(canonGroups.value, search.value.trim().toLowerCase()),
|
||||
)
|
||||
|
||||
const aktuelleListe = computed(() =>
|
||||
quelle.value === 'netflix' ? visible.value : visibleCanon.value
|
||||
quelle.value === 'netflix' ? visible.value : visibleCanon.value,
|
||||
)
|
||||
|
||||
// Die zwei Listen des Katalogs, umschaltbar in der Filterleiste
|
||||
const quellen = computed(() => [
|
||||
{ id: 'netflix', label: 'Netflix', count: netflixMovies.value.filter(nichtGesehen).length },
|
||||
{
|
||||
id: 'netflix',
|
||||
label: 'Netflix',
|
||||
count: netflixMovies.value.filter(nichtGesehen).length,
|
||||
},
|
||||
{
|
||||
id: 'canon',
|
||||
label: 'Horror-Kanon',
|
||||
@@ -98,7 +138,11 @@ const tabs = computed(() => [
|
||||
{ id: 'wheel', label: 'Rad', count: null },
|
||||
{ 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 },
|
||||
{
|
||||
id: 'wuensche',
|
||||
label: 'Wünsche',
|
||||
count: wuensche.value.filter((w) => !w.done_at).length,
|
||||
},
|
||||
...(host.value || angemeldet.value
|
||||
? [{ id: 'verwaltung', label: 'Verwaltung', count: null }]
|
||||
: []),
|
||||
@@ -107,9 +151,7 @@ const tabs = computed(() => [
|
||||
// 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(() =>
|
||||
['katalog', 'suche', 'merkliste'].includes(activeTab.value)
|
||||
)
|
||||
const mitFilter = computed(() => ['katalog', 'suche', 'merkliste'].includes(activeTab.value))
|
||||
|
||||
// Der Sammlungen-Reiter filtert nach Person und Genre, nicht nach Regler —
|
||||
// dafür hat er eine eigene Leiste
|
||||
@@ -124,9 +166,7 @@ const leuteMitSammlung = computed(() => {
|
||||
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')
|
||||
)
|
||||
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
|
||||
@@ -180,9 +220,7 @@ const series = computed(() => {
|
||||
: []
|
||||
|
||||
if (group.length < 2) return []
|
||||
return [...group].sort((a, b) =>
|
||||
(a.release_date || '').localeCompare(b.release_date || '')
|
||||
)
|
||||
return [...group].sort((a, b) => (a.release_date || '').localeCompare(b.release_date || ''))
|
||||
})
|
||||
|
||||
// Aus der Filmansicht heraus zur Ähnlichkeitsuche springen
|
||||
@@ -195,10 +233,21 @@ function zurAehnlichkeitsuche(movie) {
|
||||
suchArt.value = 'aehnlich'
|
||||
}
|
||||
|
||||
// Aus der Filmansicht zu einer Person: Regie oder Besetzung
|
||||
const personStart = ref(null)
|
||||
|
||||
function zurPersonensuche(person) {
|
||||
personStart.value = person
|
||||
selected.value = null
|
||||
activeTab.value = 'suche'
|
||||
suchArt.value = 'personen'
|
||||
}
|
||||
|
||||
// Die drei Suchen unter einem Reiter, umschaltbar über der Liste
|
||||
const SUCHARTEN = [
|
||||
{ id: 'search', label: 'Titel' },
|
||||
{ id: 'aehnlich', label: 'Ähnliche Filme' },
|
||||
{ id: 'personen', label: 'Personen' },
|
||||
{ id: 'ki', label: 'KI' },
|
||||
]
|
||||
|
||||
@@ -238,12 +287,7 @@ onMounted(load)
|
||||
Filter
|
||||
</button>
|
||||
<span v-if="host" class="host">Host</span>
|
||||
<NamensWahl
|
||||
:items="runde"
|
||||
:mine="ich"
|
||||
:host="host"
|
||||
:anmelden="michSetzen"
|
||||
/>
|
||||
<NamensWahl :items="runde" :mine="ich" :host="host" :anmelden="michSetzen" />
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -280,6 +324,17 @@ onMounted(load)
|
||||
@gestartet="aehnlichStart = null"
|
||||
/>
|
||||
|
||||
<PersonenTab
|
||||
v-else-if="suchArt === 'personen'"
|
||||
:gesehen-ids="gesehenIds"
|
||||
:ohne-gesehene="ohneGesehene"
|
||||
:filter="suchFilter"
|
||||
:ansicht="ansicht"
|
||||
:start="personStart"
|
||||
@open="selected = $event"
|
||||
@gestartet="personStart = null"
|
||||
/>
|
||||
|
||||
<KiTab
|
||||
v-else
|
||||
:angemeldet="angemeldet"
|
||||
@@ -294,6 +349,8 @@ onMounted(load)
|
||||
<!-- Die KI ordnet selbst nach Passung, da gibt es nichts zu sortieren -->
|
||||
<FilterSidebar
|
||||
v-model:sort="suchSort"
|
||||
v-model:anzahl="suchAnzahl"
|
||||
:mit-anzahl="suchArt !== 'personen'"
|
||||
v-model:ansicht="ansicht"
|
||||
v-model:ohne-gesehene="ohneGesehene"
|
||||
v-model:ranges="ranges"
|
||||
@@ -363,12 +420,7 @@ onMounted(load)
|
||||
@changed="ladeWuensche"
|
||||
/>
|
||||
|
||||
<VerwaltungTab
|
||||
v-else-if="activeTab === 'verwaltung'"
|
||||
:items="runde"
|
||||
:host="host"
|
||||
:ich="ich"
|
||||
/>
|
||||
<VerwaltungTab v-else-if="activeTab === 'verwaltung'" :items="runde" :host="host" :ich="ich" />
|
||||
|
||||
<StreamTab v-else-if="activeTab === 'stream'" />
|
||||
|
||||
@@ -459,6 +511,7 @@ onMounted(load)
|
||||
@suggested="nachVorschlag"
|
||||
@watched="ladeGesehen"
|
||||
@aehnlich="zurAehnlichkeitsuche"
|
||||
@person="zurPersonensuche"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -649,10 +702,7 @@ onMounted(load)
|
||||
/* Eine Detailkarte ist so breit wie vier kompakte Karten nebeneinander —
|
||||
oder die halbe Reihe, falls die schmaler ist. */
|
||||
.grid.details {
|
||||
grid-template-columns: repeat(
|
||||
auto-fill,
|
||||
min(calc(50% - 0.55rem), calc(4 * 190px + 3 * 1.1rem))
|
||||
);
|
||||
grid-template-columns: repeat(auto-fill, min(calc(50% - 0.55rem), calc(4 * 190px + 3 * 1.1rem)));
|
||||
}
|
||||
|
||||
.note {
|
||||
|
||||
Reference in New Issue
Block a user