-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Adding reward amount back #3178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Was and oversight to remove from the partner side since there are custom reward amounts that don't show in the title. Added back to the workspace view as well.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThis PR adds reward description display to four bounty-related UI components by introducing Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (5)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/bounty-card.tsx (1)
1-1: Avoid recomputinggetBountyRewardDescription(bounty)in the card bodyThe new reward row looks good and makes use of the shared helper, but you’re calling
getBountyRewardDescription(bounty)twice per render. It’s cheap, but a local constant improves clarity and keeps condition + content in sync.You could do:
export function BountyCard({ bounty }: { bounty: BountyListProps }) { - const { slug: workspaceSlug, isOwner } = useWorkspace(); + const { slug: workspaceSlug, isOwner } = useWorkspace(); + const rewardDescription = getBountyRewardDescription(bounty); @@ - {getBountyRewardDescription(bounty) && ( + {rewardDescription && ( <div className="text-content-subtle font-regular flex items-center gap-2 text-sm"> <Gift className="size-3.5" /> - <span>{getBountyRewardDescription(bounty)}</span> + <span>{rewardDescription}</span> </div> )}Also applies to: 9-9, 74-79
apps/web/ui/partners/bounties/claim-bounty-modal.tsx (1)
9-9: Reuse a localrewardDescriptionin the claim modal headerThe new Gift + reward row is a nice UX improvement, but
getBountyRewardDescription(bounty)is evaluated twice.Precompute once at the top of
ClaimBountyModalContentand reuse:function ClaimBountyModalContent({ bounty }: ClaimBountyModalProps) { const { submission } = bounty; + const rewardDescription = getBountyRewardDescription(bounty); @@ - {getBountyRewardDescription(bounty) && ( + {rewardDescription && ( <div className="text-content-subtle flex items-center gap-2 text-sm font-medium"> <Gift className="size-3.5" /> - <span>{getBountyRewardDescription(bounty)}</span> + <span>{rewardDescription}</span> </div> )}This keeps the condition and displayed text guaranteed in sync and mirrors the pattern used on the cards. Based on learnings, this also centralizes the flat-rate vs custom reward semantics via the helper.
Also applies to: 21-21, 303-308
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/[bountyId]/bounty-info.tsx (1)
89-96: PrecomputerewardDescriptiononce, guarding forbountybeing nullThe reward row correctly uses
getBountyRewardDescription, but it’s recomputed inside JSX. Givenbountycan be null while loading, a small helper variable keeps things both safe and clearer.For example:
export function BountyInfo() { const { bounty, loading } = useBounty(); const { isOwner } = useWorkspace(); + const rewardDescription = bounty + ? getBountyRewardDescription(bounty) + : ""; @@ - {getBountyRewardDescription(bounty) && ( + {rewardDescription && ( <div className="text-content-subtle font-regular flex items-center gap-2 text-sm"> <Gift className="size-4 shrink-0" /> - <span className="text-ellipsis"> - {getBountyRewardDescription(bounty)} - </span> + <span className="text-ellipsis">{rewardDescription}</span> </div> )}This avoids any chance of calling the helper with an undefined
bountywhile still using the same truthy check for rendering.apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/bounties/partner-bounty-card.tsx (2)
1-1: Use a localrewardDescriptionconstant inPartnerBountyCardThe reward row looks good and matches the other bounty surfaces, but again
getBountyRewardDescription(bounty)is called twice.You can mirror the other suggested pattern:
export function PartnerBountyCard({ bounty }: { bounty: PartnerBountyProps }) { const { programSlug } = useParams(); const { claimBountyModal, setShowClaimBountyModal } = useClaimBountyModal({ bounty, }); + const rewardDescription = getBountyRewardDescription(bounty); @@ - {getBountyRewardDescription(bounty) && ( + {rewardDescription && ( <div className="text-content-subtle flex items-center gap-2 text-sm font-medium"> <Gift className="size-3.5" /> - <span>{getBountyRewardDescription(bounty)}</span> + <span>{rewardDescription}</span> </div> )}Also applies to: 8-8, 96-101
96-101: Consider a sharedBountyRewardRowcomponent to avoid repetitionThe Gift + reward-description row is now effectively duplicated in:
BountyCard(workspace)PartnerBountyCard(partner app)BountyInfoClaimBountyModalTo keep iconography/typography from drifting over time, consider extracting a tiny shared component like:
// e.g. apps/web/ui/partners/bounties/bounty-reward-row.tsx export function BountyRewardRow({ description, className, }: { description?: string; className?: string }) { if (!description) return null; return ( <div className={cn( "text-content-subtle flex items-center gap-2 text-sm", className, )} > <Gift className="size-3.5" /> <span>{description}</span> </div> ); }Then each caller just passes in
getBountyRewardDescription(bounty). Not urgent, but it would simplify future tweaks.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/bounties/partner-bounty-card.tsx(2 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/[bountyId]/bounty-info.tsx(3 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/bounty-card.tsx(2 hunks)apps/web/ui/partners/bounties/claim-bounty-modal.tsx(3 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: devkiran
Repo: dubinc/dub PR: 2833
File: apps/web/lib/actions/partners/approve-bounty-submission.ts:53-61
Timestamp: 2025-09-12T17:31:10.548Z
Learning: In approve-bounty-submission.ts, the logic `bounty.rewardAmount ?? rewardAmount` is intentional. Bounties with preset reward amounts should use those fixed amounts, and the rewardAmount override parameter is only used when bounty.rewardAmount is null/undefined (for custom reward bounties). This follows the design pattern where bounties are either "flat rate" (fixed amount) or "custom" (variable amount set during approval).
📚 Learning: 2025-09-12T17:31:10.548Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2833
File: apps/web/lib/actions/partners/approve-bounty-submission.ts:53-61
Timestamp: 2025-09-12T17:31:10.548Z
Learning: In approve-bounty-submission.ts, the logic `bounty.rewardAmount ?? rewardAmount` is intentional. Bounties with preset reward amounts should use those fixed amounts, and the rewardAmount override parameter is only used when bounty.rewardAmount is null/undefined (for custom reward bounties). This follows the design pattern where bounties are either "flat rate" (fixed amount) or "custom" (variable amount set during approval).
Applied to files:
apps/web/ui/partners/bounties/claim-bounty-modal.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/bounty-card.tsxapps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/bounties/partner-bounty-card.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/[bountyId]/bounty-info.tsx
📚 Learning: 2025-08-26T14:32:33.851Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/lib/actions/partners/create-bounty-submission.ts:105-112
Timestamp: 2025-08-26T14:32:33.851Z
Learning: Non-performance bounties are required to have submissionRequirements. In create-bounty-submission.ts, it's appropriate to let the parsing fail if submissionRequirements is null for non-performance bounties, as this indicates a data integrity issue that should be caught.
Applied to files:
apps/web/ui/partners/bounties/claim-bounty-modal.tsx
📚 Learning: 2025-08-25T17:39:38.965Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2736
File: apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/[bountyId]/bounty-info.tsx:45-56
Timestamp: 2025-08-25T17:39:38.965Z
Learning: In the bounty system, each partner can only submit to the same bounty once. This means totalSubmissions (pending + approved + rejected) equals the number of unique partners who have submitted, making UI text like "X of Y partners completed" accurate when using totalSubmissions.
Applied to files:
apps/web/ui/partners/bounties/claim-bounty-modal.tsx
🧬 Code graph analysis (4)
apps/web/ui/partners/bounties/claim-bounty-modal.tsx (1)
apps/web/lib/partners/get-bounty-reward-description.ts (1)
getBountyRewardDescription(4-20)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/bounty-card.tsx (1)
apps/web/lib/partners/get-bounty-reward-description.ts (1)
getBountyRewardDescription(4-20)
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/bounties/partner-bounty-card.tsx (1)
apps/web/lib/partners/get-bounty-reward-description.ts (1)
getBountyRewardDescription(4-20)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/[bountyId]/bounty-info.tsx (1)
apps/web/lib/partners/get-bounty-reward-description.ts (1)
getBountyRewardDescription(4-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/[bountyId]/bounty-info.tsx (1)
66-66: Thumbnail + skeleton heights stay alignedThe
sm:h-[128px]updates on both the live thumbnail container andBountyInfoSkeletonkeep the loading state visually consistent with the final layout. No functional or layout issues from this change.Also applies to: 193-193
Was and oversight to remove from the partner side since there are custom reward amounts that don't show in the title.
Added back to the workspace view as well.
Summary by CodeRabbit
New Features
Improvements
✏️ Tip: You can customize this high-level summary in your review settings.