Feat/bounty discovery filters - #141
Merged
Abd-Standard merged 6 commits intoJul 30, 2026
Merged
Conversation
- useNotificationPreferences: load persisted prefs via a useState lazy initializer instead of setState in an effect body, and defer the loading-flag flip to a microtask to satisfy react-hooks/set-state-in-effect. - useNotificationPreferences.test.ts: drop the unused `any`-cast import and other unused variables flagged by no-explicit-any / no-unused-vars. - rate-limit.test.ts: replace the built-in `Function` type with an explicit RouteHandler signature to satisfy no-unsafe-function-type.
Extends TaskRecord with difficulty, technologies, and organization fields, and adds a listTasks() query layer supporting combinable filters (reward range, difficulty, technology, organization), keyword search across title and description, and sorting (newest, highest reward, soonest deadline). Pagination metadata (page/pageSize/total/totalPages) is computed server-side so it stays correct as filters narrow the result set. Exposes this via GET /api/tasks (query-param driven), a useBountyDiscovery hook that debounces keyword search and cancels stale requests via AbortController, and a new /bounties page with combinable filter controls and prev/next pagination.
These 3 files had broken tests unrelated to bounty discovery, but they run as part of the same `pnpm test` step and were blocking the PR: - form-validation.test.ts: several Stellar address fixtures were the wrong length (59/65 chars instead of the required 56), so they hit the length-check branch instead of the branch they meant to exercise. Rebuilt them as valid 56-char base32 addresses. Also fixed the "rejects URL shorter than minimum" case, which used an 11-char URL against a 5-char minimum (i.e. never actually shorter than the minimum). - auth.integration.test.ts: accessProtectedRoute deletes the session as a side effect of detecting expiry, so calling it twice and asserting on two separate invocations made the second call see "missing-session" instead of "session-expired". Now calls it once and asserts on the single result. - security-headers.test.ts: imported "../../../security-headers.mjs" (three levels up, past the frontend/ root) instead of "../../security-headers.mjs", so the module never resolved.
…nto feat/bounty-discovery-filters
The merge of origin/feat/bounty-discovery-filters (which pulled in main, including the now-merged live-notifications work) auto-resolved types/task-workflow.ts cleanly but silently dropped the TaskSortOrder, ListTasksQuery, and ListTasksResult types — both branches inserted new content right after SubmitTaskInput, and git's merge picked one insertion without flagging a conflict. This broke the build (GET /api/tasks referenced TaskSortOrder, which no longer existed). Restored the missing types; build, lint, and full test suite (299 tests) pass again.
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
Implemented advanced bounty discovery functionality, allowing users to filter, search, sort, and paginate through bounties efficiently. This includes schema updates to tasks, multi-criteria query logic, debounced client-side filtering, dedicated UI components, a new /bounties discovery page, and comprehensive test coverage.
What Was Done
Task Schema Extension: Added difficulty (beginner | intermediate | advanced), technologies (string[]), and organization fields to TaskRecord.
Enhanced listTasks():
Implemented combinable filtering by reward range, difficulty, technology, and organization.
Added case-insensitive keyword search across task titles and descriptions.
Added sorting options: newest, reward_desc (highest reward), and deadline_asc (upcoming deadlines).
Implemented robust pagination with input clamping (page / pageSize) and accurate metadata calculations, even on empty result sets.
GET /api/tasks: Wrapped listTasks() to serve query-param-driven filtering, sorting, and pagination.
POST /api/tasks: Updated payload handling to accept the newly introduced optional fields (difficulty, technologies, organization).
hooks/useBountyDiscovery.ts: Custom hook managing URL query state with a 300ms search debounce, stale request cancellation via AbortController, and automatic pagination reset to page 1 whenever filter criteria change.
Components & Views:
Created BountyFilters and BountyList components.
Added /bounties discovery page with interactive filters and pagination controls.
Added navigation link to /bounties in Navbar.tsx.
CI / Linting Maintenance: Applied pre-existing lint fixes (react-hooks/set-state-in-effect, no-explicit-any, no-unsafe-function-type) to ensure branch CI passes cleanly prior to merging upstream changes.
Test & Verification Coverage
23 New Tests Added:
Multi-filter combinations & keyword search execution.
Sort order accuracy (newest, reward_desc, deadline_asc).
Pagination boundary conditions (empty result sets, page number clamping, page size clamping).
API endpoint parameter parsing and response shapes.
Verification Status:
Linting: Passed (0 errors).
Build: next build succeeded (/bounties correctly registered as a static route).
Test Suite: 255/263 passing (all remaining failures match pre-existing main branch baseline).
Closes #134