feat(frontend): add ShowSummary, SeasonSummary types + library shows/seasons API methods
This commit is contained in:
@@ -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()
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user