Bounty: Operate → Decide → Payout → Wrap → Disputes UI#639
Bounty: Operate → Decide → Payout → Wrap → Disputes UI#639darrenyoungblood12345-a11y wants to merge 2 commits into
Conversation
… Disputes) Implements the organizer completion UI for bounties (boundlessfi#638): - lib/api/bounties.ts — typed API stubs for all bounty lifecycle endpoints (getBounty, applications CRUD, submissions, select-winners, cancel, disputes, escrow, archive) - hooks/use-bounty.ts — data hooks (useBounty, useBountyApplications, useBountySubmissions, useBountyPayout) - components/organization/bounties/details/BountySidebar.tsx — per-bounty nav sidebar mirroring HackathonSidebar (desktop + mobile sheet) - app/…/bounties/[bountyId]/page.tsx — overview: stats + lifecycle timeline - app/…/bounties/[bountyId]/applications/page.tsx — Applications (Decide): review, shortlist, select, decline with tab-filtered counts - app/…/bounties/[bountyId]/submissions/page.tsx — Submissions: list with repo/demo links and rank badge - app/…/bounties/[bountyId]/payout/page.tsx — Payout: rank assignment grid + select-winners on-chain flow with confirmation dialog - app/…/bounties/[bountyId]/cancel/page.tsx — Cancel/Refund: guarded cancel with irreversibility warning - app/…/bounties/[bountyId]/wrap/page.tsx — Wrap: winners podium + share link + archive action - app/…/bounties/[bountyId]/disputes/page.tsx — Disputes: list with resolution dialog - app/…/bounties/[bountyId]/settings/page.tsx — Settings: read-only config view - app/…/organizations/layout.tsx — wire BountySidebar for /bounties/* paths Closes boundlessfi#630 boundlessfi#631 boundlessfi#632 boundlessfi#633 boundlessfi#634 boundlessfi#635 boundlessfi#636 boundlessfi#637 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Someone is attempting to deploy a commit to the Threadflow Team on Vercel. A member of the Team first needs to authorize it. |
|
Warning Review limit reached
More reviews will be available in 38 minutes and 57 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughAdds shared bounty API/types and reusable fetch hooks, then wires a bounty sidebar into the organizations layout. New bounty pages cover overview, settings, submissions, applications, payout, wrap, disputes, and cancel flows with loading, error, and mutation states. ChangesBounty management and completion
Sequence Diagram(s)Shared bounty load sequenceDiagram
participant Organizer
participant BountyOverviewPage
participant useBounty
participant getBounty
participant api
Organizer->>BountyOverviewPage: open a bounty route
BountyOverviewPage->>useBounty: request bounty data
useBounty->>getBounty: fetch organizationId and bountyId
getBounty->>api: GET bounty details
api-->>getBounty: ApiResponse<Bounty>
getBounty-->>useBounty: bounty
useBounty-->>BountyOverviewPage: loading false
Application status update sequenceDiagram
participant Organizer
participant ApplicationsPage
participant updateApplicationStatus
participant api
Organizer->>ApplicationsPage: choose SHORTLISTED, SELECTED, or DECLINED
ApplicationsPage->>updateApplicationStatus: submit status change
updateApplicationStatus->>api: PATCH application status
api-->>updateApplicationStatus: updated application
updateApplicationStatus-->>ApplicationsPage: updated data
ApplicationsPage->>ApplicationsPage: update local state and toast
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related issues
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (1)
app/(landing)/organizations/[id]/bounties/[bountyId]/wrap/page.tsx (1)
195-204: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winSame wrong-explorer issue as the payout page.
The winner
txHashis linked toetherscan.io, but settlement happens on Stellar/Soroban via the escrow runner, so the link won't resolve. Fix alongside the payout page (preferably via a shared explorer-URL helper).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/`(landing)/organizations/[id]/bounties/[bountyId]/wrap/page.tsx around lines 195 - 204, The winner transaction link in the wrap page is pointing to the wrong explorer, since settlement is on Stellar/Soroban rather than Ethereum. Update the link generation in the txHash rendering block to use the correct explorer URL for the network, and align this with the payout page by extracting or reusing a shared explorer-URL helper so both places resolve the same way.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/`(landing)/organizations/[id]/bounties/[bountyId]/page.tsx:
- Around line 72-101: AuthGuard is wrapping too late in the bounty page, so the
loading and error branches can render before auth protection runs. Move the
entire return flow in the bounty page component so AuthGuard wraps the loading,
error, and success states just like the sibling settings/page.tsx and
submissions/page.tsx patterns, using the AuthGuard and Loading symbols to locate
the component body.
In `@app/`(landing)/organizations/[id]/bounties/[bountyId]/payout/page.tsx:
- Around line 251-260: The transaction link in the payout row is hardcoded to
Ethereum and won’t work for Stellar/Soroban tx hashes. Update the link rendering
in the payout page’s transaction anchor to use getTransactionExplorerUrl(...)
from lib/wallet-utils.ts, passing w.txHash so the correct network-specific
explorer URL is generated. Keep the existing conditional rendering and anchor
styling, but replace the etherscan.io href with the shared helper.
In `@app/`(landing)/organizations/[id]/bounties/[bountyId]/submissions/page.tsx:
- Around line 32-36: Update the rank rendering logic in the submissions page so
it checks for `submission.rank !== null` instead of relying on a truthy guard,
because `submission.rank && (...)` will treat `0` as falsy and can render the
literal `0` or exclude rank-0 items from the ranked count. Apply the same
explicit null check wherever the rank badge and the “With Rank Assigned” count
are derived, using the existing `submission.rank` and the associated count logic
in the submissions page.
In `@app/`(landing)/organizations/[id]/bounties/[bountyId]/wrap/page.tsx:
- Around line 62-78: The archive flow in handleArchive updates the server but
never refreshes the bounty data, so the UI keeps using stale state and does not
show completion. Update the useBounty hook usage in wrap/page.tsx to expose a
refetch or otherwise invalidate the bounty query, then call that refresh right
after archiveBounty succeeds before closing the dialog; this will let
isCompleted and the completion banner update and hide the Archive button.
In `@hooks/use-bounty.ts`:
- Around line 143-175: The `useBountyPayout` fetch logic is swallowing failures
because `Promise.allSettled` won’t trigger the `catch` in `fetch`, so no
user-facing error is set when both `getBountyWinners` and `getBountyEscrow`
fail. Update `fetch` in `use-bounty.ts` to inspect the settled results from both
calls, and when neither returns a successful `data` payload, call `setError`
with a fallback message and `reportError` using the existing `useBountyPayout`
context. Keep the current success paths for `setWinners` and `setEscrow`, but
ensure the hook surfaces an error instead of silently completing when both
requests fail.
---
Duplicate comments:
In `@app/`(landing)/organizations/[id]/bounties/[bountyId]/wrap/page.tsx:
- Around line 195-204: The winner transaction link in the wrap page is pointing
to the wrong explorer, since settlement is on Stellar/Soroban rather than
Ethereum. Update the link generation in the txHash rendering block to use the
correct explorer URL for the network, and align this with the payout page by
extracting or reusing a shared explorer-URL helper so both places resolve the
same way.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c7496f1a-240d-4037-a019-039f1e5c1de3
📒 Files selected for processing (12)
app/(landing)/organizations/[id]/bounties/[bountyId]/applications/page.tsxapp/(landing)/organizations/[id]/bounties/[bountyId]/cancel/page.tsxapp/(landing)/organizations/[id]/bounties/[bountyId]/disputes/page.tsxapp/(landing)/organizations/[id]/bounties/[bountyId]/page.tsxapp/(landing)/organizations/[id]/bounties/[bountyId]/payout/page.tsxapp/(landing)/organizations/[id]/bounties/[bountyId]/settings/page.tsxapp/(landing)/organizations/[id]/bounties/[bountyId]/submissions/page.tsxapp/(landing)/organizations/[id]/bounties/[bountyId]/wrap/page.tsxapp/(landing)/organizations/layout.tsxcomponents/organization/bounties/details/BountySidebar.tsxhooks/use-bounty.tslib/api/bounties.ts
| const handleArchive = async () => { | ||
| setArchiving(true); | ||
| try { | ||
| const res = await archiveBounty(organizationId, bountyId); | ||
| if (res.success) { | ||
| toast.success('Bounty archived successfully'); | ||
| } else { | ||
| toast.error(res.message || 'Failed to archive bounty'); | ||
| } | ||
| } catch (err) { | ||
| reportError(err, { context: 'wrap-archive', bountyId }); | ||
| toast.error('Failed to archive bounty'); | ||
| } finally { | ||
| setArchiving(false); | ||
| setArchiveOpen(false); | ||
| } | ||
| }; |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Refresh bounty state after archiving so the UI reflects completion.
On success, bounty is never refetched, so isCompleted stays false: the completion banner won't appear and the Archive button remains visible/clickable even after a successful archive. useBountyPayout exposes a refetch, but useBounty here does not; pull a refetch from useBounty (or re-route/invalidate) and call it after a successful archive.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@app/`(landing)/organizations/[id]/bounties/[bountyId]/wrap/page.tsx around
lines 62 - 78, The archive flow in handleArchive updates the server but never
refreshes the bounty data, so the UI keeps using stale state and does not show
completion. Update the useBounty hook usage in wrap/page.tsx to expose a refetch
or otherwise invalidate the bounty query, then call that refresh right after
archiveBounty succeeds before closing the dialog; this will let isCompleted and
the completion banner update and hide the Archive button.
- Move AuthGuard to wrap loading/error states (page.tsx) - Replace etherscan.io with getTransactionExplorerUrl (payout, wrap) - Fix rank 0 rendering via explicit null check (submissions) - Surface errors when both allSettled calls fail (use-bounty)
Fixes #638. Implements bounty management UI covering the full lifecycle.
Summary by CodeRabbit
New Features
Bug Fixes