Fix ZXDB pagination counters and navigation
Implement URL-driven pagination and correct total counts across ZXDB: - Root /zxdb: SSR reads ?page; client syncs to SSR; Prev/Next as Links. - Sub-index pages (genres, languages, machinetypes): parse ?page on server; use SSR props in clients; Prev/Next via Links. - Labels browse (/zxdb/labels): dynamic SSR, reads ?q & ?page; typed count(*); client syncs to SSR; Prev/Next preserve q. - Label detail (/zxdb/labels/[id]): tab-aware Prev/Next Links; counters from server. - Repo: replace raw counts with typed Drizzle count(*) for reliable totals. Signed-off-by: Junie <Junie@lucy.xalior.com>
This commit is contained in:
@@ -68,7 +68,7 @@ export async function searchEntries(params: SearchParams): Promise<PagedResult<S
|
||||
|
||||
const whereExpr = whereClauses.length ? and(...whereClauses) : undefined;
|
||||
|
||||
const [items, [{ total }]] = await Promise.all([
|
||||
const [items, countRows] = await Promise.all([
|
||||
db
|
||||
.select()
|
||||
.from(entries)
|
||||
@@ -76,16 +76,13 @@ export async function searchEntries(params: SearchParams): Promise<PagedResult<S
|
||||
.orderBy(sort === "id_desc" ? desc(entries.id) : entries.title)
|
||||
.limit(pageSize)
|
||||
.offset(offset),
|
||||
db.execute(
|
||||
sql`select count(*) as total from ${entries} ${whereExpr ? sql`where ${whereExpr}` : sql``}`
|
||||
) as Promise<any>,
|
||||
db
|
||||
.select({ total: sql<number>`count(*)` })
|
||||
.from(entries)
|
||||
.where(whereExpr as any) as unknown as Promise<{ total: number }[]>,
|
||||
]);
|
||||
return {
|
||||
items: items as any,
|
||||
page,
|
||||
pageSize,
|
||||
total: Number((total as any) ?? 0),
|
||||
};
|
||||
const total = Number(countRows?.[0]?.total ?? 0);
|
||||
return { items: items as any, page, pageSize, total };
|
||||
}
|
||||
|
||||
const pattern = `%${q.toLowerCase().replace(/[^a-z0-9]+/g, "")}%`;
|
||||
@@ -201,11 +198,14 @@ export async function searchLabels(params: LabelSearchParams): Promise<PagedResu
|
||||
const offset = (page - 1) * pageSize;
|
||||
|
||||
if (!q) {
|
||||
const [items, [{ total }]] = await Promise.all([
|
||||
const [items, countRows] = await Promise.all([
|
||||
db.select().from(labels).orderBy(labels.name).limit(pageSize).offset(offset),
|
||||
db.execute(sql`select count(*) as total from ${labels}`) as Promise<any>,
|
||||
db
|
||||
.select({ total: sql<number>`count(*)` })
|
||||
.from(labels) as unknown as Promise<{ total: number }[]>,
|
||||
]);
|
||||
return { items: items as any, page, pageSize, total: Number(total ?? 0) };
|
||||
const total = Number(countRows?.[0]?.total ?? 0);
|
||||
return { items: items as any, page, pageSize, total };
|
||||
}
|
||||
|
||||
// Using helper search_by_names for efficiency
|
||||
@@ -313,7 +313,10 @@ export async function listMachinetypes() {
|
||||
|
||||
export async function entriesByGenre(genreId: number, page: number, pageSize: number): Promise<PagedResult<SearchResultItem>> {
|
||||
const offset = (page - 1) * pageSize;
|
||||
const [{ total }]: any = await db.execute(sql`select count(*) as total from ${entries} where ${entries.genretypeId} = ${genreId}`);
|
||||
const countRows = (await db
|
||||
.select({ total: sql<number>`count(*)` })
|
||||
.from(entries)
|
||||
.where(eq(entries.genretypeId, genreId as any))) as unknown as { total: number }[];
|
||||
const items = await db
|
||||
.select({ id: entries.id, title: entries.title, isXrated: entries.isXrated, machinetypeId: entries.machinetypeId, languageId: entries.languageId })
|
||||
.from(entries)
|
||||
@@ -321,12 +324,15 @@ export async function entriesByGenre(genreId: number, page: number, pageSize: nu
|
||||
.orderBy(entries.title)
|
||||
.limit(pageSize)
|
||||
.offset(offset);
|
||||
return { items: items as any, page, pageSize, total: Number(total ?? 0) };
|
||||
return { items: items as any, page, pageSize, total: Number(countRows?.[0]?.total ?? 0) };
|
||||
}
|
||||
|
||||
export async function entriesByLanguage(langId: string, page: number, pageSize: number): Promise<PagedResult<SearchResultItem>> {
|
||||
const offset = (page - 1) * pageSize;
|
||||
const [{ total }]: any = await db.execute(sql`select count(*) as total from ${entries} where ${entries.languageId} = ${langId}`);
|
||||
const countRows = (await db
|
||||
.select({ total: sql<number>`count(*)` })
|
||||
.from(entries)
|
||||
.where(eq(entries.languageId, langId as any))) as unknown as { total: number }[];
|
||||
const items = await db
|
||||
.select({ id: entries.id, title: entries.title, isXrated: entries.isXrated, machinetypeId: entries.machinetypeId, languageId: entries.languageId })
|
||||
.from(entries)
|
||||
@@ -334,12 +340,15 @@ export async function entriesByLanguage(langId: string, page: number, pageSize:
|
||||
.orderBy(entries.title)
|
||||
.limit(pageSize)
|
||||
.offset(offset);
|
||||
return { items: items as any, page, pageSize, total: Number(total ?? 0) };
|
||||
return { items: items as any, page, pageSize, total: Number(countRows?.[0]?.total ?? 0) };
|
||||
}
|
||||
|
||||
export async function entriesByMachinetype(mtId: number, page: number, pageSize: number): Promise<PagedResult<SearchResultItem>> {
|
||||
const offset = (page - 1) * pageSize;
|
||||
const [{ total }]: any = await db.execute(sql`select count(*) as total from ${entries} where ${entries.machinetypeId} = ${mtId}`);
|
||||
const countRows = (await db
|
||||
.select({ total: sql<number>`count(*)` })
|
||||
.from(entries)
|
||||
.where(eq(entries.machinetypeId, mtId as any))) as unknown as { total: number }[];
|
||||
const items = await db
|
||||
.select({ id: entries.id, title: entries.title, isXrated: entries.isXrated, machinetypeId: entries.machinetypeId, languageId: entries.languageId })
|
||||
.from(entries)
|
||||
@@ -347,7 +356,7 @@ export async function entriesByMachinetype(mtId: number, page: number, pageSize:
|
||||
.orderBy(entries.title)
|
||||
.limit(pageSize)
|
||||
.offset(offset);
|
||||
return { items: items as any, page, pageSize, total: Number(total ?? 0) };
|
||||
return { items: items as any, page, pageSize, total: Number(countRows?.[0]?.total ?? 0) };
|
||||
}
|
||||
|
||||
// ----- Facets for search -----
|
||||
|
||||
Reference in New Issue
Block a user