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

Skip to content

Conversation

@marcusljf
Copy link
Collaborator

@marcusljf marcusljf commented Oct 1, 2025

On smaller screens, the Help and Support links were below laptop heights, so reworked this section to tighten everything up and to make everything more consistent and consumable.

A new rewards section was created to not impact other places that file is being used.

CleanShot 2025-10-01 at 13 28 15@2x

Summary by CodeRabbit

  • New Features

    • Added a dedicated Rewards panel showing program rewards and discounts.
    • Improved referral link copying with an inline button, toast feedback, and subtle gradient overlay.
  • Style

    • Refreshed Program details layout: smaller avatar, vertical info stack, and updated referral link input/button design.
    • Renamed “Stats” to “Performance” with refined spacing and typography.
    • Standardized padding, borders, and rounded styles across sections.
    • Aligned Help & Support block spacing with the new layout.

On smaller screens, the Help and Support links were below screen heights, so it was a complete rework of this section was done to tighten everything up and to make everything a bit more consistent and readable.
@vercel
Copy link
Contributor

vercel bot commented Oct 1, 2025

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

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Oct 1, 2025 8:33pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 1, 2025

Walkthrough

Replaces the in-page rewards list with a new ProgramRewardsPanel component, updates UI layouts and classes in the messages page, adjusts help link styling, and publicly exports ProgramRewardModifiersTooltipContent. Introduces ProgramRewardsPanel to render rewards and optional discounts with tooltip support.

Changes

Cohort / File(s) Summary
Messages dashboard UI updates
apps/web/app/(ee)/partners.dub.co/(dashboard)/messages/[programSlug]/page-client.tsx
Swaps ProgramRewardList for ProgramRewardsPanel; restructures layout (avatar, referral link, performance block); tweaks paddings, sizes, icons; adds copy-to-clipboard behavior and gradient overlay; inserts dedicated Rewards panel.
Rewards panel (new component)
apps/web/ui/partners/program-rewards-panel.tsx
Adds memoized ProgramRewardsPanel to render rewards and optional discount; builds labels with duration logic; integrates modifiers tooltip; exports component and sets displayName.
Tooltip export change
apps/web/ui/partners/program-reward-modifiers-tooltip.tsx
Makes ProgramRewardModifiersTooltipContent a public export; no logic changes.
Help links styling
apps/web/ui/partners/program-help-links.tsx
Adjusts anchor classes: padding and transition tweaks; no behavioral changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Page as Messages Page
  participant Panel as ProgramRewardsPanel
  participant Tooltip as Reward Modifiers Tooltip

  User->>Page: Open program messages dashboard
  Page->>Panel: Render rewards (+optional discount)
  Panel->>Panel: Build items (amount + duration text)
  alt Reward has modifiers
    Panel-->>Tooltip: Attach tooltip content
  end
  User-->>Tooltip: Hover/Focus reward with modifiers
  Tooltip-->>User: Show modifiers details
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • steven-tey

Poem

A bunny stacks rewards in tidy rows,
With tooltips soft as clover glows.
A panel hops where lists once lay,
Discounts dance in bright array.
Click—copy!—toasts go “ding!” with cheer,
New burrows built; the path is clear. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The current title "Partner messages panel updates" is related to the changes in the partner messages panel but is overly generic and does not highlight the specific improvements such as responsive layout adjustments and the addition of the rewards section. Consider revising the title to clearly state the main changes, for example "Improve responsive layout and add rewards section to partner messages panel," to make the PR’s intent immediately clear.
✅ 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
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch program-message-panel

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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 13f520d and 8609fd4.

📒 Files selected for processing (4)
  • apps/web/app/(ee)/partners.dub.co/(dashboard)/messages/[programSlug]/page-client.tsx (6 hunks)
  • apps/web/ui/partners/program-help-links.tsx (1 hunks)
  • apps/web/ui/partners/program-reward-modifiers-tooltip.tsx (1 hunks)
  • apps/web/ui/partners/program-rewards-panel.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/ui/partners/program-rewards-panel.tsx (3)
apps/web/lib/types.ts (2)
  • RewardProps (509-509)
  • DiscountProps (445-445)
apps/web/ui/partners/program-reward-modifiers-tooltip.tsx (1)
  • ProgramRewardModifiersTooltipContent (48-99)
apps/web/lib/api/sales/construct-reward-amount.ts (1)
  • constructRewardAmount (5-61)
apps/web/app/(ee)/partners.dub.co/(dashboard)/messages/[programSlug]/page-client.tsx (2)
packages/utils/src/functions/urls.ts (1)
  • getPrettyUrl (130-138)
apps/web/ui/partners/program-rewards-panel.tsx (1)
  • ProgramRewardsPanel (29-109)
⏰ 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 (10)
apps/web/ui/partners/program-help-links.tsx (1)

54-54: LGTM! Hover animation refinement improves UX.

The transition from static horizontal padding to dynamic hover-based padding creates a subtle "grow on hover" effect that's more space-efficient on smaller screens while maintaining visual feedback.

apps/web/ui/partners/program-reward-modifiers-tooltip.tsx (1)

48-48: LGTM! Proper component modularization.

Exporting ProgramRewardModifiersTooltipContent enables reuse in the new ProgramRewardsPanel component, promoting DRY principles.

apps/web/app/(ee)/partners.dub.co/(dashboard)/messages/[programSlug]/page-client.tsx (6)

17-17: LGTM! Import updated for new component.

The import correctly references the new ProgramRewardsPanel component.


322-336: LGTM! Avatar and layout optimizations for smaller screens.

Reducing avatar size and switching to vertical stack improves space efficiency on mobile devices, consistent with PR objectives.


341-392: LGTM! Improved referral link UI with copy functionality.

The redesigned input with gradient fade overlay and integrated copy button provides better UX. The gradient overlay correctly uses pointer-events-none to avoid interfering with input interaction, and the toast notification on copy enhances user feedback.


396-437: LGTM! Performance section renamed and spacing optimized.

The rename from "Stats" to "Performance" is more descriptive, and the padding adjustments improve space efficiency while maintaining all data rendering logic and loading states.


451-458: LGTM! Consistent spacing applied to Help & support section.

Padding adjustments align with the overall spacing optimization strategy across all panel sections.


439-448: Remove redundant null-safety suggestion. A fallback (programEnrollment.rewards ?? []) is already applied, so ProgramRewardsPanel always receives an array.

Likely an incorrect or invalid review comment.

apps/web/ui/partners/program-rewards-panel.tsx (2)

16-27: LGTM! Compact tooltip implementation.

The custom tooltip with reduced icon size (h-3.5 w-3.5) maintains functionality while supporting the space optimization goals.


111-111: LGTM! Proper displayName for debugging.

Setting displayName on the memoized component aids in React DevTools debugging.

Comment on lines +29 to +109
export const ProgramRewardsPanel = memo(
({ rewards, discount }: ProgramRewardsPanelProps) => {
const sortedFilteredRewards = rewards.filter((r) => r.amount >= 0);

const rewardItems = [
...sortedFilteredRewards.map((reward) => ({
icon: REWARD_EVENTS[reward.event].icon,
label: reward.description || (
<>
{constructRewardAmount(reward)}{" "}
{reward.event === "sale" && reward.maxDuration === 0 ? (
<>for the first sale</>
) : (
<>per {reward.event}</>
)}
{reward.maxDuration === null ? (
<>
{" "}
for the{" "}
<strong className="font-semibold">customer's lifetime</strong>
</>
) : reward.maxDuration && reward.maxDuration > 1 ? (
<>
{" "}
for{" "}
<strong className="font-semibold">
{reward.maxDuration % 12 === 0
? `${reward.maxDuration / 12} year${reward.maxDuration / 12 > 1 ? "s" : ""}`
: `${reward.maxDuration} months`}
</strong>
</>
) : null}
{!!reward.modifiers?.length && (
<>
{" "}
<CustomRewardModifiersTooltip reward={reward} />
</>
)}
</>
),
})),
...(discount
? [
{
icon: Gift,
label: discount.description || (
<>
New users get {constructRewardAmount(discount)} off{" "}
{discount.maxDuration === null
? "for their lifetime"
: discount.maxDuration === 0
? "for their first purchase"
: discount.maxDuration === 1
? "for their first month"
: discount.maxDuration && discount.maxDuration > 1
? `for ${discount.maxDuration} months`
: null}
</>
),
},
]
: []),
];

if (rewardItems.length === 0) return null;

return (
<div className="grid grid-cols-1">
{rewardItems.map(({ icon: Icon, label }, index) => (
<div
key={index}
className="text-content-default flex items-start gap-2 rounded-md py-1.5 text-sm"
>
<Icon className="size-4 shrink-0 translate-y-px" />
<div>{label}</div>
</div>
))}
</div>
);
},
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Review duration logic and key usage.

A few observations:

  1. Index as key (line 99): Using index as the key can cause React rendering issues if the rewards array order changes. Consider using a stable identifier like reward.id or a combination of properties.

  2. Duration edge case (lines 44-60): The logic doesn't explicitly handle maxDuration === 1 for rewards (though it's handled for discounts at line 81-82). For consistency, consider:

-           ) : reward.maxDuration && reward.maxDuration > 1 ? (
+           ) : reward.maxDuration === 1 ? (
+             <>
+               {" "}
+               for <strong className="font-semibold">1 month</strong>
+             </>
+           ) : reward.maxDuration && reward.maxDuration > 1 ? (
  1. Amount filter (line 31): The filter r.amount >= 0 excludes negative rewards. Verify this is intentional behavior, as negative amounts might represent clawbacks or penalties.

🏁 Script executed:

#!/bin/bash
# Verify if negative reward amounts are valid in the schema and how they should be displayed

rg -nP --type=ts -C5 'amount.*number|RewardSchema' apps/web/lib/zod/schemas/rewards.ts

Length of output: 1543


Replace index‐based key, add missing 1-month case, and reconsider amount filter.

  • Replace key={index} with a stable identifier (e.g. key={reward.id} and key={discount.id}) to avoid React reconciliation issues.

  • (Optional) Add an explicit maxDuration === 1 branch for rewards so that “for 1 month” is rendered:

    -           ) : reward.maxDuration && reward.maxDuration > 1 ? (
    +           ) : reward.maxDuration === 1 ? (
    +             <>
    +               {" "}
    +               for <strong className="font-semibold">1 month</strong>
    +             </>
    +           ) : reward.maxDuration && reward.maxDuration > 1 ? (
  • (Optional) Since the Zod createOrUpdateRewardSchema enforces amount ≥ 0, rewards.filter(r => r.amount >= 0) will never drop valid items—consider removing this filter if negative values aren’t meaningful in the UI.

🤖 Prompt for AI Agents
In apps/web/ui/partners/program-rewards-panel.tsx around lines 29 to 109, the PR
review asks to stop using an index-based React key, add an explicit 1-month
wording branch, and reconsider the amount filter: replace key={index} with
stable keys (use reward.id for each mapped reward item and discount.id for the
discount item), add an explicit maxDuration === 1 case in the reward label
rendering so it displays “for 1 month” (mirror the discount logic), and remove
or justify the rewards.filter(r => r.amount >= 0) line since the schema already
enforces amount >= 0 (delete the filter if negatives are impossible, or add a
comment explaining why it’s kept).

@steven-tey steven-tey merged commit a3df0db into main Oct 1, 2025
8 of 9 checks passed
@steven-tey steven-tey deleted the program-message-panel branch October 1, 2025 21:51
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