Skip to content

[Enhancement] Add search, category/price filters, sorting, and pagination to the book library #88

Description

@zeemscript

What's Happening

The book library (app/dashboard/library/page.jsx) fetches every book in one shot (fetchBooks()GET /api/books in lib/actions/library/fetch-books.js) and renders the whole list in a grid. There is no way to search, filter, sort, or paginate within the library:

  • The only controls on the page are "Create Book" and a bookmarks toggle.
  • Books have a category field (creators type one free-form in book-create-form.jsx, and BookDetailPageClient.jsx renders it as a badge) — but the library offers no category filtering.
  • Prices exist (free vs paid USDC) — no "Free"/"Paid" filter, no sort by price/rating/date.
  • The global Searchbox in nav-header.jsx routes to /dashboard/search/[searchparam], a separate cross-entity results page — useful, but browsing within the library still means scrolling an unbounded grid, and the client-side render cost grows linearly with catalog size.

As the catalog grows this page becomes both slow (fetch-all + render-all) and unusable for discovery — a core flow for an Islamic book library.

Where to Find This

  • app/dashboard/library/page.jsx — page state (books, showBookmarks, loading, error)
  • lib/actions/library/fetch-books.js — the fetch-all action
  • components/molecules/dashboard/cards/libraryCard.jsx — the card grid item
  • components/atoms/skeletons/LibraryBookSkeleton.jsx — existing loading skeletons
  • Reference for UI primitives: components/ui/select.jsx, components/ui/pagination.jsx (already in the repo, unused here)

What We Want

  1. A toolbar on the library page with: a debounced text search (title/author), a category select (populated from the fetched data or a backend categories endpoint if available), a price filter (All / Free / Paid), and a sort control (Newest, Price, Rating).
  2. Pagination (or "Load more" infinite scroll — pick one) instead of rendering the full catalog; reuse components/ui/pagination.jsx.
  3. Prefer server-side querying: extend fetch-books.js to pass ?search=&category=&page=&limit=&sort= query params and use the backend's response shape if it supports them. If the backend doesn't yet, implement the filtering client-side behind the same UI and note the needed backend params in the PR (so the API work can be a follow-up) — the UI contract should not change either way.
  4. Reflect filters in the URL query string (useSearchParams/router.replace) so filtered views are shareable and survive refresh.
  5. Keep existing behavior: bookmarks toggle applies on top of filters, own-books exclusion (book?.author?._id !== user?._id) stays, skeletons during loading, NetworkErrorComp with retry on failure, and a filter-aware empty state ("No books match your filters" with a clear-filters button).

Technical Context

  • The page is a client component with plain useState — this can stay; just mind effect dependencies when filters change (debounce search ~300ms to avoid a request per keystroke).
  • Category is free-form text today, so normalize for the dropdown (trim/case-fold) and expect duplicates like "Aqeedah"/"aqeedah".
  • The same pattern applies to /dashboard/courses — keep components (toolbar, hooks) reusable, but courses are out of scope for this issue.

Acceptance Criteria

  • Library shows a search box, category filter, price filter, and sort control; each visibly narrows/orders the grid.
  • Search input is debounced (no request storm while typing).
  • Only one page of results renders at a time (or incremental batches for infinite scroll); paging controls work.
  • Filter state round-trips through the URL: refreshing or sharing the URL restores the same view.
  • Bookmarks toggle, loading skeletons, error+retry, and the empty state all still work with filters applied.
  • npm run lint and npm run build pass.

Metadata

Metadata

Assignees

No one assigned

    Labels

    complexity:highMaps to Drips Wave High tier (200 pts)enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions