feat(frontend): add ShowSummary, SeasonSummary types + library shows/seasons API methods

This commit is contained in:
2026-03-20 01:14:43 +01:00
parent 23722a771b
commit dd69470ee4
3 changed files with 36 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ use sqlx::SqlitePool;
use domain::{ use domain::{
ContentType, DomainError, DomainResult, ILibraryRepository, ContentType, DomainError, DomainResult, ILibraryRepository,
LibraryCollection, LibraryItem, LibrarySearchFilter, LibrarySyncLogEntry, LibrarySyncResult, LibraryCollection, LibraryItem, LibrarySearchFilter, LibrarySyncLogEntry, LibrarySyncResult,
SeasonSummary, ShowSummary,
}; };
pub struct SqliteLibraryRepository { pub struct SqliteLibraryRepository {
@@ -72,6 +73,9 @@ impl ILibraryRepository for SqliteLibraryRepository {
.collect(); .collect();
conditions.push(format!("({})", genre_conditions.join(" OR "))); conditions.push(format!("({})", genre_conditions.join(" OR ")));
} }
if let Some(sn) = filter.season_number {
conditions.push(format!("season_number = {}", sn));
}
let where_clause = if conditions.is_empty() { let where_clause = if conditions.is_empty() {
String::new() String::new()

View File

@@ -22,6 +22,8 @@ import type {
LibrarySyncLogEntry, LibrarySyncLogEntry,
PagedLibraryResponse, PagedLibraryResponse,
AdminSettings, AdminSettings,
ShowSummary,
SeasonSummary,
} from "@/lib/types"; } from "@/lib/types";
const API_BASE = const API_BASE =
@@ -267,6 +269,22 @@ export const api = {
params.set('limit', String(filter.limit ?? 50)); params.set('limit', String(filter.limit ?? 50));
return request(`/library/items?${params}`, { token }); return request(`/library/items?${params}`, { token });
}, },
shows: (token: string, filter?: { q?: string; provider?: string; genres?: string[] }): Promise<ShowSummary[]> => {
const params = new URLSearchParams();
if (filter?.q) params.set('q', filter.q);
if (filter?.provider) params.set('provider', filter.provider);
filter?.genres?.forEach(g => params.append('genres[]', g));
const qs = params.toString();
return request(`/library/shows${qs ? `?${qs}` : ''}`, { token });
},
seasons: (token: string, seriesName: string, provider?: string): Promise<SeasonSummary[]> => {
const params = new URLSearchParams();
if (provider) params.set('provider', provider);
const qs = params.toString();
return request(`/library/shows/${encodeURIComponent(seriesName)}/seasons${qs ? `?${qs}` : ''}`, { token });
},
}, },
files: { files: {

View File

@@ -303,6 +303,20 @@ export interface LibraryItemFull extends LibraryItemResponse {
collection_name?: string | null; collection_name?: string | null;
} }
export interface ShowSummary {
series_name: string;
episode_count: number;
season_count: number;
thumbnail_url?: string | null;
genres: string[];
}
export interface SeasonSummary {
season_number: number;
episode_count: number;
thumbnail_url?: string | null;
}
export interface PagedLibraryResponse { export interface PagedLibraryResponse {
items: LibraryItemFull[]; items: LibraryItemFull[];
total: number; total: number;