Add bounty board filtering/sorting/pagination and validate avatar image URLs - #574
Merged
chonilius merged 1 commit intoSep 28, 2026
Conversation
Fixes MergeFi#28: /issues now reads status, difficulty, asset, reward-range, sort, and page from searchParams (shareable/bookmarkable URLs), filters and paginates in a way that works identically against live and mock data, and clamps an invalid page/filter combo instead of erroring or blanking the page. fetchBounties forwards the same params to the backend so nothing needs to change here once /bounties supports them server-side. Fixes MergeFi#20: Avatar now rejects any src that isn't an https(s) URL on the GitHub-avatar/dicebear allowlist (blocking javascript:/data: schemes and unexpected hosts) before it ever reaches next/image, and falls back to the dicebear identicon on a real load failure too, without an infinite retry loop.
|
@Godbrand0 is attempting to deploy a commit to the chonilius' projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@Godbrand0 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
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
closes #28 and
closes #20 .
#28 — bounty board pagination/filtering/sorting
src/lib/bounty-query.ts: parsesstatus/difficulty/asset/minReward/maxReward/sort/pagefromsearchParams, with every value degrading to a sane default instead of erroring (unrecognized enum, non-numeric or out-of-range page, inverted reward range, out-of-range page number all clamp/degrade gracefully)./issuesreads and renders these from the URL (Server ComponentsearchParams, no client state), so every filter/sort/page combination is a shareable, bookmarkable link. Difficulty/asset/reward-range/sort are a plain<form method="get">so the page works with JS disabled; the status pills stay<Link>s.filterBounties/applyBountyQueryrun against whateverfetchBountiesreturns — live or mock fallback — so the mock-data path has full filter/sort/pagination parity with live data by construction, with no separate mock-only logic to keep in sync.fetchBountiesnow forwards the query as backend query params viabuildBountyQueryString. The backend doesn't currently honor them (confirmed:/bountiesreturns the full unfiltered collection regardless), so the client-side pass above is still the source of truth — this is forward-compatible with server-side filtering landing later without needing another frontend change.status; now covers all facets).#20 — avatar URL validation
Avatar.tsxnow rejects anysrcthat isn't anhttps:URL on the same host allowlist asnext.config.ts'simages.remotePatterns(avatars.githubusercontent.com,api.dicebear.com) before it reachesnext/image— blocksjavascript:/data:schemes and any unexpected third-party host, falling back to the dicebear identicon.onError, tracking the specific failedsrcso it doesn't retry the same failing URL in a loop but does retry if the prop later changes to a different URL.Test plan
npx jest— all suites pass except 3 pre-existing failures unrelated to this change (timezone-dependentlocale.test.ts, andCallbackClient.test.tsxfailures present onmainbefore this branch)src/lib/bounty-query.test.ts(parsing, filtering, sorting, pagination, href-building) and expandedsrc/components/ui/Avatar.test.tsx(allowlisted host, non-allowlisted host,javascript:/data:schemes, load-failure fallback)npx eslintclean on all changed filesnpx tsc --noEmit— no new errors (pre-existing unrelated errors confirmed present onmain)