Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@marcusljf
Copy link
Collaborator

@marcusljf marcusljf commented Dec 1, 2025

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

    • Bounty reward descriptions now display across all bounty views (cards, info page, and claim modal)
    • Gift icon indicator added to highlight reward information
  • Improvements

    • Reward descriptions visibility improved—now display when available rather than by user role
    • Enhanced thumbnail sizing on bounty detail pages for better clarity

✏️ Tip: You can customize this high-level summary in your review settings.

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.
@vercel
Copy link
Contributor

vercel bot commented Dec 1, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
dub Error Error Dec 1, 2025 7:00pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

Walkthrough

This PR adds reward description display to four bounty-related UI components by introducing getBountyRewardDescription function calls and Gift icons. It also increases the thumbnail height from 100px to 128px in the bounty-info component and changes visibility logic from owner-based to description-existence checks.

Changes

Cohort / File(s) Summary
Bounty card components
apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/bounties/partner-bounty-card.tsx, apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/bounty-card.tsx
Added conditional rendering blocks displaying bounty reward descriptions with Gift icon using getBountyRewardDescription(). Both components follow identical UI pattern.
Bounty info component
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/[bountyId]/bounty-info.tsx
Updated thumbnail height from sm:h-[100px] to sm:h-[128px], changed reward description visibility logic from !isOwner to description-existence check, and aligned skeleton placeholder height.
Claim bounty modal
apps/web/ui/partners/bounties/claim-bounty-modal.tsx
Added dual conditional rendering of reward description (with Gift icon) in header and content areas, both using getBountyRewardDescription() for display logic.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

  • Areas requiring attention:
    • Verify getBountyRewardDescription import path and function behavior across all four files
    • Confirm the visibility logic change from !isOwner to description-existence check in bounty-info.tsx is intentional and doesn't affect permission models
    • Ensure responsive styling consistency for the new 128px thumbnail height across breakpoints

Possibly related PRs

Suggested reviewers

  • steven-tey

Poem

🎁 A gift of descriptions now shines so bright,
Four bounty cards glow with reward delight,
Gift icons dance beside the text,
While thumbnails stretch—what's next?
Hop along, the bounties are blessed! 🐰✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Adding reward amount back' is vague and does not clearly convey what was changed. While it references 'reward amount', it doesn't specify which bounty-related components are affected or the full scope of the changes. Consider a more specific title like 'Display bounty reward descriptions in partner and workspace views' to better reflect the actual changes across multiple components.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bounty-fix

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 recomputing getBountyRewardDescription(bounty) in the card body

The 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 local rewardDescription in the claim modal header

The new Gift + reward row is a nice UX improvement, but getBountyRewardDescription(bounty) is evaluated twice.

Precompute once at the top of ClaimBountyModalContent and 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: Precompute rewardDescription once, guarding for bounty being null

The reward row correctly uses getBountyRewardDescription, but it’s recomputed inside JSX. Given bounty can 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 bounty while 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 local rewardDescription constant in PartnerBountyCard

The 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 shared BountyRewardRow component to avoid repetition

The Gift + reward-description row is now effectively duplicated in:

  • BountyCard (workspace)
  • PartnerBountyCard (partner app)
  • BountyInfo
  • ClaimBountyModal

To 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

📥 Commits

Reviewing files that changed from the base of the PR and between 9cde7ea and 68a5c9a.

📒 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.tsx
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/bounty-card.tsx
  • apps/web/app/(ee)/partners.dub.co/(dashboard)/programs/[programSlug]/(enrolled)/bounties/partner-bounty-card.tsx
  • apps/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 aligned

The sm:h-[128px] updates on both the live thumbnail container and BountyInfoSkeleton keep the loading state visually consistent with the final layout. No functional or layout issues from this change.

Also applies to: 193-193

@steven-tey steven-tey merged commit 8ade5cb into main Dec 1, 2025
7 of 9 checks passed
@steven-tey steven-tey deleted the bounty-fix branch December 1, 2025 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants