Skip to content

Split the CTA branch logic in bounty-detail-sidebar-cta.tsx into per-bounty-type components #297

Description

@Benjtalkshow

components/bounty-detail/bounty-detail-sidebar-cta.tsx is 399 lines and the bulk of it (lines ~152-233) is one giant cascading ternary that picks a CTA button based on bounty.type:

{isFcfs ? (
  <FcfsClaimButton bounty={bounty} />
) : isCompetition ? (
  hasJoined ? (...) : (...)
) : bounty.type === "MULTI_WINNER_MILESTONE" && canAct && !isCreator ? (
  ...
) : bounty.type === "MILESTONE_BASED" && canAct && !isCreator ? (
  ...
) : (
  ...
)}

The shape is hard to scan, hard to test, and every time a new bounty type lands it widens. Most of these branches also live alongside their own helper text, loading states, and disabled rules.

What to do

Extract each branch into its own component under components/bounty-detail/cta/:

  • fcfs-cta.tsx — wraps FcfsClaimButton
  • competition-cta.tsx — the join button, the joined state, the past-deadline messaging
  • multi-winner-cta.tsx — the apply-for-slot button and slot-full handling
  • milestone-based-cta.tsx — the apply dialog trigger
  • default-cta.tsx — the fallback "View on GitHub" / closed-bounty state

Then bounty-detail-sidebar-cta.tsx selects one component:

function BountyCta({ bounty, state }: ...) {
  if (state.isFcfs) return <FcfsCta bounty={bounty} />;
  if (state.isCompetition) return <CompetitionCta bounty={bounty} state={state} />;
  if (bounty.type === "MULTI_WINNER_MILESTONE") return <MultiWinnerCta ... />;
  if (bounty.type === "MILESTONE_BASED") return <MilestoneBasedCta ... />;
  return <DefaultCta bounty={bounty} state={state} />;
}

Hoist the state from useBountyCTAState to the parent and pass the relevant slice down to each component.

Acceptance criteria

  • No single CTA component over 120 lines
  • bounty-detail-sidebar-cta.tsx body shrinks substantially and the CTA selection is a simple dispatch
  • No visual or behavioral change in any bounty type's CTA
  • pnpm tsc --noEmit and pnpm lint pass

Files

  • components/bounty-detail/bounty-detail-sidebar-cta.tsx
  • components/bounty-detail/cta/ (new directory)
  • components/bounty-detail/use-bounty-cta-state.ts (reference)

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions