fix(catalog): use the paginated courses API instead of the first page only - #80
Merged
udaycodespace merged 1 commit intoAug 18, 2026
Conversation
… only udaycodespace#43 made GET /api/user/getallcourses paginated, searchable and filterable. AllCourses.jsx never picked it up: it called the endpoint bare, got the default twelve rows, filtered those twelve in a useMemo and dropped the pagination block. Course thirteen was unreachable, the search box searched one page, and the "courses found" counter maxed out at twelve. The API already does all of this, so the change is on the client. - lib/catalogQuery.js is the pure half: the query builder, the pagination reader, page clamping, the page-number window, and the range label. Kept free of React so it can be tested without a DOM. - hooks/useCourseCatalog.js owns the request. It debounces typing at 350ms so the search box is one request rather than one per character, and gives every request a ticket so a slow response for "re" cannot land on top of a fast one for "react". - CatalogPager renders Previous/pages/Next, always keeping the first, last and current pages present so nothing is more than two clicks away. - The free/paid test moves off /\d/.test(C_price), which called a course priced "Free for the first 100" paid while the server called it free, onto the same pattern the server uses. - A page that no longer exists — a filter narrowed, a course deleted — clamps to one that does instead of rendering an empty grid. frontend gains npm test, running node --test over src/**/*.test.js. No new dependency; Node's runner reads the ESM modules directly. Closes udaycodespace#75
This was referenced Aug 16, 2026
udaycodespace
self-requested a review
August 17, 2026 09:48
Owner
|
@MOHITKOURAV01 Looks good to me. The pagination, search, sorting, and edge-case handling are well covered. Approved and ready to merge. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
#43 made
GET /api/user/getallcoursespaginated, searchable, filterable andsortable. The catalogue never picked any of it up:
normalizePaginationdefaults toDEFAULT_LIMIT = 12, so that response holdstwelve courses.
AllCourses.jsxthen filtered those twelve in auseMemoand dropped
res.data.paginationon the floor.Course thirteen could not be seen or enrolled in, there was no page control
anywhere in the UI, the search box searched one page, and the "courses found"
counter maxed out at twelve.
The API already does the work, so this is all on the client.
Related Issue
Closes #75
What changed
lib/catalogQuery.js— the pure half, no React, so it can be tested withouta DOM: the query builder, the pagination reader, page clamping, the
page-number window, and the range label.
hooks/useCourseCatalog.jsowns the request. Two things it has to get right:fires a request per character.
"re"landing after a fast one for"react"would put the wrong results on screen. Every request takes aticket and only the newest one may write state.
It also resets to page one whenever the query changes, since staying on page
four while switching to a filter with two pages shows an empty grid.
CatalogPagerrenders Previous / numbered pages / Next, always keeping thefirst, last and current pages present so nothing is more than two clicks
away, with
aria-current="page"and per-button labels./\d/.test(course.C_price)— which calls acourse priced
"Free for the first 100"paid while the server'sFREE_PRICE_PATTERNcalls it free — onto the server's rule. The two halvesof the same filter used to disagree.
one that does instead of rendering an empty grid.
sortand nothing exposed it.no courses yet", and only offers "Clear filters" in the first case.
Type
Areas touched
Testing
npm testinfrontend/: 22 passing.npm run buildpasses.Test steps
real total, not 12.
?page=1&limit=12&search=….page clamps to one that exists.
cd frontend && npm testScreenshots
Happy to add before/after shots of the grid and the new pager if that helps
review.
Edge cases checked
Other edge case details
readPaginationfills intotalPagesand the has-page flags when a responsedoes not carry them, and falls back to a single page if the whole block is
missing, so an older or proxied response cannot leave the grid without a pager.
An empty catalogue reports zero pages rather than one. The pager's buttons
shrink on small screens so "‹ Previous 1 … 9 Next ›" still fits.
Checklist
CONTRIBUTING.mdNotes
frontend/package.jsongains annpm testscript runningnode --testoversrc/**/*.test.js. No new dependency — Node's own runner reads the ESMmodules directly. That is why
buildPageWindowlives inlib/catalogQuery.jsrather than next to the component: Node cannot import
.jsx, and I wouldrather the arithmetic be testable than have it sit in a file the runner cannot
open. The React components still need a DOM and are not covered; the logic that
decides which courses are reachable is.
npm run lintis failing onmainalready (68 errors, mostly missingprop-typesacross existing components). I matched the surrounding stylerather than adding prop-types to the two new components only; happy to add them
if you would prefer to start narrowing that down.
docs/issue-75-catalog-pagination.mdhas the details.