feat(ui): add homepage with Continue Reading, Recently Updated, and stats
Replace the single-button placeholder with a full homepage: - Stats bar: total books, total chapters, books in progress - Continue Reading grid (up to 6): links directly to last chapter read - Recently Updated grid (up to 6): recent books not already in progress - Empty state with Discover Novels CTA when library is empty New pocketbase.ts helpers: recentlyAddedBooks(), getHomeStats(), listN(), countCollection().
This commit is contained in:
@@ -130,6 +130,25 @@ async function listAll<T>(collection: string, filter = '', sort = ''): Promise<T
|
||||
return data.items ?? [];
|
||||
}
|
||||
|
||||
async function listN<T>(collection: string, n: number, filter = '', sort = ''): Promise<T[]> {
|
||||
const params = new URLSearchParams({ perPage: String(n) });
|
||||
if (filter) params.set('filter', filter);
|
||||
if (sort) params.set('sort', sort);
|
||||
const data = await pbGet<PBList<T>>(
|
||||
`/api/collections/${collection}/records?${params.toString()}`
|
||||
);
|
||||
return data.items ?? [];
|
||||
}
|
||||
|
||||
async function countCollection(collection: string, filter = ''): Promise<number> {
|
||||
const params = new URLSearchParams({ perPage: '1' });
|
||||
if (filter) params.set('filter', filter);
|
||||
const data = await pbGet<PBList<unknown>>(
|
||||
`/api/collections/${collection}/records?${params.toString()}`
|
||||
);
|
||||
return (data as { totalItems: number }).totalItems ?? 0;
|
||||
}
|
||||
|
||||
async function listOne<T>(collection: string, filter: string): Promise<T | null> {
|
||||
const params = new URLSearchParams({ perPage: '1', filter });
|
||||
const data = await pbGet<PBList<T>>(
|
||||
@@ -154,6 +173,27 @@ export async function getBook(slug: string): Promise<Book | null> {
|
||||
return listOne<Book>('books', `slug="${slug}"`);
|
||||
}
|
||||
|
||||
export async function recentlyAddedBooks(limit = 6): Promise<Book[]> {
|
||||
return listN<Book>('books', limit, '', '-meta_updated');
|
||||
}
|
||||
|
||||
export async function recentlyUpdatedBooks(limit = 6): Promise<Book[]> {
|
||||
return listN<Book>('books', limit, '', '-meta_updated');
|
||||
}
|
||||
|
||||
export interface HomeStats {
|
||||
totalBooks: number;
|
||||
totalChapters: number;
|
||||
}
|
||||
|
||||
export async function getHomeStats(): Promise<HomeStats> {
|
||||
const [totalBooks, totalChapters] = await Promise.all([
|
||||
countCollection('books'),
|
||||
countCollection('chapters_idx')
|
||||
]);
|
||||
return { totalBooks, totalChapters };
|
||||
}
|
||||
|
||||
// ─── Chapter index ────────────────────────────────────────────────────────────
|
||||
|
||||
export async function listChapterIdx(slug: string): Promise<ChapterIdx[]> {
|
||||
|
||||
Reference in New Issue
Block a user