diff --git a/src/components/bounty/ClaimButton.test.tsx b/src/components/bounty/ClaimButton.test.tsx index 9c49b61..835cb75 100644 --- a/src/components/bounty/ClaimButton.test.tsx +++ b/src/components/bounty/ClaimButton.test.tsx @@ -108,6 +108,51 @@ describe("ClaimButton", () => { expect(screen.queryByText(/Claimed by:/)).not.toBeInTheDocument(); }); + describe("the claimant's own view of their claim (#699)", () => { + it("shows 'You're working on this' with PR instructions instead of the loser's message", () => { + mockAuth({ id: "user-1", stellarAddress: "GSTELLAR" }); + mockHooks( + {}, + { + status: "claimed", + bounty: { id: "b1", status: "claimed", claimedById: "user-1", issueNumber: 42 }, + }, + ); + render(); + + expect(screen.getByText("You're working on this")).toBeInTheDocument(); + expect(screen.getByText("Fixes #42")).toBeInTheDocument(); + expect(screen.queryByText(/This bounty has already been/)).not.toBeInTheDocument(); + }); + + it("still shows the generic already-claimed view to a different signed-in user", () => { + mockAuth({ id: "user-2", stellarAddress: "GOTHER" }); + mockHooks( + {}, + { + status: "claimed", + bounty: { id: "b1", status: "claimed", claimedById: "user-1", claimedBy: "alice" }, + }, + ); + render(); + + expect(screen.getByText(/This bounty has already been/)).toBeInTheDocument(); + expect(screen.queryByText("You're working on this")).not.toBeInTheDocument(); + }); + + it("shows the generic already-claimed view when signed out", () => { + mockAuth(null); + mockHooks( + {}, + { status: "claimed", bounty: { id: "b1", status: "claimed", claimedById: "user-1" } }, + ); + render(); + + expect(screen.getByText(/This bounty has already been/)).toBeInTheDocument(); + expect(screen.queryByText("You're working on this")).not.toBeInTheDocument(); + }); + }); + it("shows the auto-refresh hint only while polling", () => { mockHooks({}, { isPolling: true }); render(); diff --git a/src/components/bounty/ClaimButton.tsx b/src/components/bounty/ClaimButton.tsx index 3e11d4c..f867801 100644 --- a/src/components/bounty/ClaimButton.tsx +++ b/src/components/bounty/ClaimButton.tsx @@ -186,6 +186,30 @@ export function ClaimButton({ const needsPayoutWallet = !!user && !user.stellarAddress; if (status === 'claimed') { + // The claimant sees this same view on every later visit too, not just + // right after the 5s success notice expires -- "already claimed" / + // "Claimed by: ..." reads like they lost a race they actually won, with + // no indication of what to do next (#699). + const isOwnClaim = !!user && !!bounty?.claimedById && bounty.claimedById === user.id; + + if (isOwnClaim) { + return ( +
+

You're working on this

+

+ Open a pull request that says{' '} + + Fixes #{bounty?.issueNumber} + {' '} + in its description. The reward releases automatically once it's merged. +

+
+ ); + } + return (