refactor: split bounty CTA branch logic into per-bounty-type components#313
Conversation
|
@jotel-dev is attempting to deploy a commit to the Threadflow Team on Vercel. A member of the Team first needs to authorize it. |
|
@Benedict315 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! 🚀 |
📝 WalkthroughWalkthroughExtracts the inline CTA ternary in ChangesCTA Component Extraction
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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: 1
🤖 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 `@components/bounty-detail/cta/competition-cta.tsx`:
- Around line 45-63: The CTA in competition-cta.tsx is falling back to
ctaLabel() after the deadline, which uses bounty status only and can show the
wrong action text for a past-deadline OPEN competition. Update the Button label
logic in the competition CTA so it uses a competition-specific closed/ended
label when isPastDeadline is true, while keeping the existing “Join Competition”
text only for the active canAct case. Reference the Button rendering in
competition-cta.tsx and the ctaLabel() usage to keep the change localized.
🪄 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: 903b5f6e-fb97-4885-b0e5-b68e79dbca9b
📒 Files selected for processing (6)
components/bounty-detail/bounty-detail-sidebar-cta.tsxcomponents/bounty-detail/cta/competition-cta.tsxcomponents/bounty-detail/cta/default-cta.tsxcomponents/bounty-detail/cta/fcfs-cta.tsxcomponents/bounty-detail/cta/milestone-based-cta.tsxcomponents/bounty-detail/cta/multi-winner-cta.tsx
| <Button | ||
| data-testid="apply-to-bounty-btn" | ||
| className="w-full h-11 font-bold tracking-wide" | ||
| disabled={ | ||
| !canAct || | ||
| isPastDeadline || | ||
| joinMutation.isPending || | ||
| !walletAddress | ||
| } | ||
| size="lg" | ||
| onClick={() => void handleJoin()} | ||
| > | ||
| {joinMutation.isPending ? ( | ||
| <Loader2 className="mr-2 size-4 animate-spin" /> | ||
| ) : ( | ||
| <Users className="mr-2 size-4" /> | ||
| )} | ||
| {canAct && !isPastDeadline ? "Join Competition" : ctaLabel()} | ||
| </Button> |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use a competition-specific closed label after the deadline.
Line 62 falls back to ctaLabel() when isPastDeadline is true, but ctaLabel() only looks at bounty status. For an OPEN competition past its deadline, the disabled button will read "Submit to Bounty", which is the wrong action here.
Suggested fix
- {canAct && !isPastDeadline ? "Join Competition" : ctaLabel()}
+ {!canAct
+ ? ctaLabel()
+ : isPastDeadline
+ ? "Deadline Passed"
+ : "Join Competition"}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <Button | |
| data-testid="apply-to-bounty-btn" | |
| className="w-full h-11 font-bold tracking-wide" | |
| disabled={ | |
| !canAct || | |
| isPastDeadline || | |
| joinMutation.isPending || | |
| !walletAddress | |
| } | |
| size="lg" | |
| onClick={() => void handleJoin()} | |
| > | |
| {joinMutation.isPending ? ( | |
| <Loader2 className="mr-2 size-4 animate-spin" /> | |
| ) : ( | |
| <Users className="mr-2 size-4" /> | |
| )} | |
| {canAct && !isPastDeadline ? "Join Competition" : ctaLabel()} | |
| </Button> | |
| <Button | |
| data-testid="apply-to-bounty-btn" | |
| className="w-full h-11 font-bold tracking-wide" | |
| disabled={ | |
| !canAct || | |
| isPastDeadline || | |
| joinMutation.isPending || | |
| !walletAddress | |
| } | |
| size="lg" | |
| onClick={() => void handleJoin()} | |
| > | |
| {joinMutation.isPending ? ( | |
| <Loader2 className="mr-2 size-4 animate-spin" /> | |
| ) : ( | |
| <Users className="mr-2 size-4" /> | |
| )} | |
| {!canAct | |
| ? ctaLabel() | |
| : isPastDeadline | |
| ? "Deadline Passed" | |
| : "Join Competition"} | |
| </Button> |
🤖 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 `@components/bounty-detail/cta/competition-cta.tsx` around lines 45 - 63, The
CTA in competition-cta.tsx is falling back to ctaLabel() after the deadline,
which uses bounty status only and can show the wrong action text for a
past-deadline OPEN competition. Update the Button label logic in the competition
CTA so it uses a competition-specific closed/ended label when isPastDeadline is
true, while keeping the existing “Join Competition” text only for the active
canAct case. Reference the Button rendering in competition-cta.tsx and the
ctaLabel() usage to keep the change localized.
Reset branch onto current main so this PR no longer deletes the work from PRs boundlessfi#298, boundlessfi#311, and boundlessfi#313. Only changes left: - New hooks/__tests__/use-bounty-application.test.tsx with 12 cases covering happy and rollback paths for useApplyToBounty, useSelectApplicant, useApproveApplicationSubmission, useRequestRevisions, useApplyForSlot, useReleasePayment, useRemoveContributor, useDeclineApplicant, and useRaiseDispute. - Validation in useApplyToBounty that throws ApplicationError when applicantAddress is missing. Production guard, not test-only. Verified pnpm lint, pnpm tsc --noEmit, pnpm build, and the new test suite (12/12 passing) all clean.
Description
Resolves #297.
This PR refactors the call-to-action (CTA) rendering logic inside
components/bounty-detail/bounty-detail-sidebar-cta.tsx. The previously giant cascading conditional ternary that selected the appropriate CTA button based on the bounty type has been split into dedicated, modular sub-components.Changes Made
Created a new directory
components/bounty-detail/cta/and extracted the branch rendering logic into five separate components:fcfs-cta.tsx: Wraps theFcfsClaimButtonand handles showing the fallback alert text if the FCFS bounty is no longer active (!canAct).competition-cta.tsx: Renders competition CTA buttons (e.g. "Joined ✓" state, "Join Competition" with load spinners and deadlines), and the past-deadline lockout warning.multi-winner-cta.tsx: Renders the apply-for-slot button for multi-winner milestone bounties, with slot fullness and already-joined validations.milestone-based-cta.tsx: Wraps the<ApplicationDialog>trigger and button component for milestone-based bounties.default-cta.tsx: Renders the fallback "View on GitHub" link or the closed-bounty message for when no other actions are applicable.Main Component Simplified
bounty-detail-sidebar-cta.tsx: Replaced the 100+ line cascading ternary block with a single<BountyCta bounty={bounty} state={state} />dispatch component.AlertCircle,Clock,ApplicationDialog,FcfsClaimButton).SidebarCTAcomponent and passed the required state properties down to the sub-components using strong TypeScript typing.Verification
pnpm tsc --noEmitcompiled successfully with 0 errors.pnpm lintandeslintchecked and verified with 0 errors/warnings.16 passed, 16 total/94 tests passed) successfully ran and passed:closes #297
Summary by CodeRabbit