Add hideAvailable filter and unified pagination

Add support for hiding audiobooks that are already available by introducing a hideAvailable query flag and excluding matching ASINs at the DB level. Implemented getAvailableAsins() in audiobook-matcher to gather ASINs from the library and completed requests, and wired it into the popular and new-releases API routes to apply a notIn filter. Propagated the hideAvailable flag through useAudiobooks so client requests include the parameter, and adjusted the homepage to reset pagination when the flag changes. Replaced two StickyPagination instances with a new UnifiedPagination component (new file) that provides a single context-aware floating paginator which tracks the dominant section and allows switching between Popular and New Releases. Also removed client-side filtering in favor of server-side exclusion and made small imports/cleanup in page.tsx.
This commit is contained in:
kikootwo
2026-03-03 12:36:03 -05:00
parent bfd624e120
commit ff80d995c5
10 changed files with 653 additions and 361 deletions
+38
View File
@@ -272,6 +272,44 @@ export async function enrichAudiobooksWithMatches(
return results;
}
/**
* Get all ASINs that are considered "available" — present in library or have completed requests.
* Used by paginated API routes to exclude available items at the DB level.
*/
export async function getAvailableAsins(): Promise<Set<string>> {
const [libraryItems, completedRequests] = await Promise.all([
// ASINs present in the library (Plex or Audiobookshelf)
prisma.plexLibrary.findMany({
where: { asin: { not: null } },
select: { asin: true },
distinct: ['asin'],
}),
// ASINs with completed audiobook requests
prisma.audiobook.findMany({
where: {
audibleAsin: { not: null },
requests: {
some: {
status: 'completed',
type: 'audiobook',
deletedAt: null,
},
},
},
select: { audibleAsin: true },
}),
]);
const asins = new Set<string>();
for (const item of libraryItems) {
if (item.asin) asins.add(item.asin);
}
for (const item of completedRequests) {
if (item.audibleAsin) asins.add(item.audibleAsin);
}
return asins;
}
/**
* Normalize ISBN for comparison (remove dashes and spaces)
*/