ZXDB: Releases browser filters, schema lists, and fixes
- UI: Add /zxdb hub cards for Entries and Releases; implement Releases browser
with URL‑synced filters (q, year, sort, DL language/machine, file/scheme/source/case, demo)
and a paginated table (Entry ID, Title, Release #, Year).
- API: Add GET /api/zxdb/releases/search (Zod‑validated, Node runtime) supporting
title, year, sort, and downloads‑based filters; return paged JSON.
- Repo: Rewrite searchReleases to Drizzle QB; correct ORDER BY on releases.release_year;
implement EXISTS on downloads using explicit "from downloads as d"; return JSON‑safe rows.
- Schema: Align Drizzle models with ZXDB for releases/downloads; add lookups
availabletypes, currencies, roletypes, and roles relation.
- API (lookups): Add GET /api/zxdb/{availabletypes,currencies,roletypes} for dropdowns.
- Stability: JSON‑clone SSR payloads before passing to Client Components to avoid
RowDataPacket serialization errors.
Signed-off-by: Junie@lucy.xalior.com
This commit is contained in:
43
src/app/zxdb/entries/page.tsx
Normal file
43
src/app/zxdb/entries/page.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import EntriesExplorer from "./EntriesExplorer";
|
||||
import { listGenres, listLanguages, listMachinetypes, searchEntries } from "@/server/repo/zxdb";
|
||||
|
||||
export const metadata = {
|
||||
title: "ZXDB Entries",
|
||||
};
|
||||
|
||||
export const dynamic = "force-dynamic";
|
||||
|
||||
export default async function Page({ searchParams }: { searchParams: Promise<{ [key: string]: string | string[] | undefined }> }) {
|
||||
const sp = await searchParams;
|
||||
const page = Math.max(1, Number(Array.isArray(sp.page) ? sp.page[0] : sp.page) || 1);
|
||||
const genreId = (Array.isArray(sp.genreId) ? sp.genreId[0] : sp.genreId) ?? "";
|
||||
const languageId = (Array.isArray(sp.languageId) ? sp.languageId[0] : sp.languageId) ?? "";
|
||||
const machinetypeId = (Array.isArray(sp.machinetypeId) ? sp.machinetypeId[0] : sp.machinetypeId) ?? "";
|
||||
const sort = ((Array.isArray(sp.sort) ? sp.sort[0] : sp.sort) as any) ?? "id_desc";
|
||||
const q = (Array.isArray(sp.q) ? sp.q[0] : sp.q) ?? "";
|
||||
|
||||
const [initial, genres, langs, machines] = await Promise.all([
|
||||
searchEntries({
|
||||
page,
|
||||
pageSize: 20,
|
||||
sort,
|
||||
q,
|
||||
genreId: genreId ? Number(genreId) : undefined,
|
||||
languageId: languageId || undefined,
|
||||
machinetypeId: machinetypeId ? Number(machinetypeId) : undefined,
|
||||
}),
|
||||
listGenres(),
|
||||
listLanguages(),
|
||||
listMachinetypes(),
|
||||
]);
|
||||
|
||||
return (
|
||||
<EntriesExplorer
|
||||
initial={initial as any}
|
||||
initialGenres={genres as any}
|
||||
initialLanguages={langs as any}
|
||||
initialMachines={machines as any}
|
||||
initialUrlState={{ q, page, genreId, languageId, machinetypeId, sort }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user