import { ApiError, request, type Manga, type Page } from './client'; export type Collection = { id: string; user_id: string; name: string; description: string | null; created_at: string; updated_at: string; }; /** Returned by `GET /v1/me/collections` — enriched for card rendering. */ export type CollectionSummary = Collection & { manga_count: number; /** Up to 3 cover image keys, newest-added first. */ sample_covers: string[]; }; export type CollectionsPage = { items: CollectionSummary[]; page: Page; }; export type CollectionMangasPage = { items: Manga[]; page: Page; }; export type NewCollection = { name: string; description?: string | null; }; export type CollectionPatch = { name?: string; description?: string | null; }; export type ListMyOptions = { limit?: number; offset?: number }; export async function listMyCollections( opts: ListMyOptions = {} ): Promise { const params = new URLSearchParams(); if (opts.limit != null) params.set('limit', String(opts.limit)); if (opts.offset != null) params.set('offset', String(opts.offset)); const qs = params.toString(); return request(`/v1/me/collections${qs ? `?${qs}` : ''}`); } /** Empty page on 401 so guest-rendering pages don't have to special-case. */ export async function listMyCollectionsOrEmpty(): Promise { try { return await listMyCollections(); } catch (e) { if (e instanceof ApiError && e.status === 401) { return { items: [], page: { limit: 50, offset: 0, total: null } }; } throw e; } } export async function createCollection( input: NewCollection ): Promise { return request('/v1/collections', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(input) }); } export async function getCollection(id: string): Promise { return request(`/v1/collections/${encodeURIComponent(id)}`); } export async function updateCollection( id: string, patch: CollectionPatch ): Promise { return request(`/v1/collections/${encodeURIComponent(id)}`, { method: 'PATCH', headers: { 'content-type': 'application/json' }, body: JSON.stringify(patch) }); } export async function deleteCollection(id: string): Promise { await request(`/v1/collections/${encodeURIComponent(id)}`, { method: 'DELETE' }); } export async function listCollectionMangas( id: string, opts: ListMyOptions = {} ): Promise { const params = new URLSearchParams(); if (opts.limit != null) params.set('limit', String(opts.limit)); if (opts.offset != null) params.set('offset', String(opts.offset)); const qs = params.toString(); return request( `/v1/collections/${encodeURIComponent(id)}/mangas${qs ? `?${qs}` : ''}` ); } export async function addMangaToCollection( collectionId: string, mangaId: string ): Promise { await request( `/v1/collections/${encodeURIComponent(collectionId)}/mangas`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ manga_id: mangaId }) } ); } export async function removeMangaFromCollection( collectionId: string, mangaId: string ): Promise { await request( `/v1/collections/${encodeURIComponent(collectionId)}/mangas/${encodeURIComponent(mangaId)}`, { method: 'DELETE' } ); } /** Which of the user's collections currently contain this manga. */ export async function getMyCollectionsContaining( mangaId: string ): Promise { const r = await request<{ collection_ids: string[] }>( `/v1/mangas/${encodeURIComponent(mangaId)}/my-collections` ); return r.collection_ids; }