feat: eigene Sammlung — „hab ich" mit Quelle
Streaming-Verfügbarkeit beantwortet nur die halbe Frage: manche Filme laufen nirgends mehr, die hat man gekauft und liegen zu Hause — in Jellyfin, Plex, Emby, auf dem NAS oder als Scheibe. Bewusst getrennt vom Feld „wo schaue ich das": das eine sagt, wo ein Titel gerade läuft, und das ändert sich ständig; das andere sagt, was einem gehört, und das bleibt. Auf der Detailseite steht die Sammlung deshalb vor der Verfügbarkeit — was man hat, ist die verlässlichere Antwort. Durchgezogen bis in Filter, Export, CSV-Import und REST-API.
This commit is contained in:
+12
-1
@@ -19,6 +19,8 @@ export type LibraryFilters = {
|
||||
genre?: string;
|
||||
tag?: string;
|
||||
provider?: string;
|
||||
/** Nur Titel, die in der eigenen Sammlung liegen. */
|
||||
owned?: boolean;
|
||||
sort?: LibrarySort;
|
||||
};
|
||||
|
||||
@@ -42,6 +44,8 @@ export type LibraryItem = {
|
||||
favorite: boolean;
|
||||
currentRun: number;
|
||||
whereToWatch: string | null;
|
||||
owned: boolean;
|
||||
ownedSource: string | null;
|
||||
tags: string[];
|
||||
watched: number;
|
||||
total: number;
|
||||
@@ -56,6 +60,7 @@ export async function getLibrary(
|
||||
userId,
|
||||
deletedAt: null,
|
||||
...(filters.status ? { status: filters.status } : {}),
|
||||
...(filters.owned ? { owned: true } : {}),
|
||||
...(filters.tag ? { tags: { some: { tag: { name: filters.tag } } } } : {}),
|
||||
title: {
|
||||
...(filters.type ? { type: filters.type } : {}),
|
||||
@@ -116,6 +121,8 @@ export async function getLibrary(
|
||||
favorite: entry.favorite,
|
||||
currentRun: entry.currentRun,
|
||||
whereToWatch: entry.whereToWatch,
|
||||
owned: entry.owned,
|
||||
ownedSource: entry.ownedSource,
|
||||
tags: entry.tags.map((link) => link.tag.name),
|
||||
watched,
|
||||
total,
|
||||
@@ -162,11 +169,13 @@ export type LibraryFacets = {
|
||||
tags: string[];
|
||||
providers: string[];
|
||||
counts: Record<EntryStatus | "ALLE", number>;
|
||||
/** Wie viele Titel in der eigenen Sammlung liegen. */
|
||||
owned: number;
|
||||
};
|
||||
|
||||
/** Werte für die Filterleiste — nur das, was in der Bibliothek wirklich vorkommt. */
|
||||
export async function getLibraryFacets(userId: string): Promise<LibraryFacets> {
|
||||
const [genreRows, tagRows, providerRows, statusRows, total] = await Promise.all([
|
||||
const [genreRows, tagRows, providerRows, statusRows, total, owned] = await Promise.all([
|
||||
prisma.$queryRaw<{ genre: string }[]>`
|
||||
SELECT DISTINCT unnest(t."genres") AS genre
|
||||
FROM "LibraryEntry" e
|
||||
@@ -193,6 +202,7 @@ export async function getLibraryFacets(userId: string): Promise<LibraryFacets> {
|
||||
_count: { _all: true },
|
||||
}),
|
||||
prisma.libraryEntry.count({ where: { userId, deletedAt: null } }),
|
||||
prisma.libraryEntry.count({ where: { userId, deletedAt: null, owned: true } }),
|
||||
]);
|
||||
|
||||
const counts = {
|
||||
@@ -211,6 +221,7 @@ export async function getLibraryFacets(userId: string): Promise<LibraryFacets> {
|
||||
tags: tagRows.map((row) => row.name),
|
||||
providers: providerRows.map((row) => row.name),
|
||||
counts,
|
||||
owned,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user