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

Skip to content

Conversation

@TWilson023
Copy link
Collaborator

@TWilson023 TWilson023 commented Nov 21, 2025

Screenshot 2025-11-21 at 5 29 03 PM Screenshot 2025-11-21 at 5 29 21 PM Screenshot 2025-11-21 at 5 29 37 PM Screenshot 2025-11-21 at 5 29 45 PM

Summary by CodeRabbit

  • New Features

    • Added tooltip description to rewards with rich-text support and max-length validation.
    • Rewards form now supports editing and previewing tooltip content; reward preview card shows updated details and partner info.
    • Inline badge popover gains a rich-text editor and styling options for tooltip content.
    • Tooltips now display tooltip text when present (even without modifiers) and use improved condensed prose styling.
  • Chores

    • Added a helper to normalize reward form data for creation/edit flows.

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

@vercel
Copy link
Contributor

vercel bot commented Nov 21, 2025

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

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Nov 22, 2025 1:54am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 2025

Warning

Rate limit exceeded

@steven-tey has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 5 minutes and 39 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 4bd67ed and 82fe4b0.

📒 Files selected for processing (3)
  • apps/web/ui/partners/program-reward-list.tsx (1 hunks)
  • apps/web/ui/partners/rewards/reward-preview-card.tsx (1 hunks)
  • apps/web/ui/shared/inline-badge-popover.tsx (4 hunks)

Walkthrough

Adds a new tooltipDescription field end-to-end: schema, DB field, server actions, form bindings, UI rendering, a getRewardPayload helper, and a reward preview card; tooltipDescription is validated, persisted, and prioritized for tooltip content when present.

Changes

Cohort / File(s) Summary
Schemas & DB
apps/web/lib/zod/schemas/rewards.ts, packages/prisma/schema/reward.prisma
Introduced REWARD_DESCRIPTION_MAX_LENGTH (100) and REWARD_TOOLTIP_DESCRIPTION_MAX_LENGTH (2000). Added tooltipDescription to reward Zod schemas (nullish allowed). Added tooltipDescription String? @db.Text`` to Prisma Reward model.
Server actions
apps/web/lib/actions/partners/create-reward.ts, apps/web/lib/actions/partners/update-reward.ts
Parse tooltipDescription from input and persist as `tooltipDescription: tooltipDescription
Form & Helpers
apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx
Added exported getRewardPayload({ data: FormData }) to normalize form data (modifiers, currency → cents, amounts, maxDuration) and wired tooltipDescription into form defaults and inputs; replaced inline parsing with helper usage and updated UI to include rich-text tooltip input.
Preview & Partners UI
apps/web/ui/partners/rewards/reward-preview-card.tsx
New RewardPreviewCard (uses getRewardPayload), plus PartnersCompactTable and PartnerPreviewOrCount components to render partner previews/counts.
Program reward display
apps/web/ui/partners/program-reward-description.tsx, apps/web/ui/partners/program-reward-list.tsx, apps/web/ui/partners/program-reward-modifiers-tooltip.tsx
Narrowed ProgramRewardDescription props to a Pick, widened tooltip/modifiers rendering conditions to show when tooltipDescription exists, and made tooltip content use tooltipDescription when present; added minor layout adjustments and contentClassName usage.
Inline badge / rich text
apps/web/ui/shared/inline-badge-popover.tsx
Added showOptional?: boolean and contentClassName?: string props; exported InlineBadgePopoverRichTextArea rich-text editor (character count, markdown icon, keyboard handling). Note: duplicate export block appears present in file.
Tooltip styling
packages/ui/src/tooltip.tsx
Applied PROSE_STYLES.condensed to tooltip markdown className for condensed prose styling.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Form as Add/Edit Reward Form
    participant Helper as getRewardPayload
    participant Action as Create/Update Action
    participant DB as Prisma DB
    participant UI as Display Components

    User->>Form: Fill reward + tooltipDescription
    Form->>Helper: Submit FormData
    Helper->>Helper: Normalize modifiers, convert currency→cents, compute amounts
    Helper-->>Form: Payload (includes tooltipDescription)
    Form->>Action: Call create/update with payload
    Action->>DB: Persist reward (tooltipDescription stored)
    DB-->>Action: Confirm
    Action-->>UI: Return reward object

    alt tooltipDescription present
        UI->>UI: Render tooltip using tooltipDescription
    else modifiers present
        UI->>UI: Render modifiers tooltip
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay attention to getRewardPayload correctness (currency → cents, flat vs percentage, Infinity → null).
  • Verify tooltipDescription validation lengths in Zod vs DB type.
  • Confirm UI conditional rendering shows tooltip when modifiers are empty.
  • Check duplicate export of InlineBadgePopoverRichTextArea and any prop-type regressions from narrowing ProgramRewardDescription.

Possibly related PRs

Suggested reviewers

  • marcusljf
  • devkiran

Poem

🐰 A little tooltip hopped in today,
tucked rich text where modifiers play.
Previews gleam and payloads compute,
cents and lengths all neatly put.
Hooray — rewards now speak a bit more gay! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
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.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary change: adding custom reward tooltip descriptions. It directly matches the main feature introduced across the changeset.

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

🧹 Nitpick comments (3)
apps/web/ui/partners/rewards/reward-preview-card.tsx (1)

134-181: Align avatar “+X” label with actual previewed partners

PartnerPreviewOrCount always maps over all previewPartners, but the “+X” label is based on partnersCount > 3 and assumes only 3 are shown in the avatar row. If previewPartners ever contains more than 3 items, the UI could show more avatars than implied by +{partnersCount - 3}.

If upstream doesn’t already cap previewPartners to 3, consider either slicing locally:

const visiblePartners = previewPartners.slice(0, 3);
const extraCount = Math.max(0, partnersCount - visiblePartners.length);

or documenting the expectation that previewPartners.length <= 3.

apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx (2)

18-23: Shared getRewardPayload helper is solid; consider reusing safeParse in preview if perf becomes a concern

The new getRewardPayload centralizes:

  • Currency normalization for both main amount and per‑modifier conditions.
  • Infinitynull conversion for maxDuration (global and per‑modifier).
  • Type/shape validation of modifiers via rewardConditionsArraySchema.parse.

Using this helper in onSubmit keeps create/update payload construction consistent and keeps the error handling for invalid conditions (setError("root.logic", ...) + toast) in one place.

Given it’s also used in the live preview, you’re now running a full zod parse on every form change. That’s probably fine at current scale, but if the form grows or you see perf issues, you could switch the preview path to safeParse and only show the preview when it succeeds, avoiding try/catch exceptions in the hot render path.

Structurally, the helper and its use in onSubmit look correct.

Also applies to: 87-142, 300-317


182-183: Clarify lifecycle between description and tooltipDescription when removing the custom description

The tooltip wiring is clean:

  • tooltipDescription is in form defaults and watch.
  • UI uses InlineBadgePopoverRichTextArea with REWARD_TOOLTIP_DESCRIPTION_MAX_LENGTH.
  • Backend will receive tooltipDescription via getRewardPayload’s spread of data.

One behavioral nuance: the “Remove reward” button in this block only sets description to null:

onClick={() =>
  setValue("description", null, { shouldDirty: true })
}

tooltipDescription is left untouched, so you can end up with:

  • No custom description (sheet section closed because description === null).
  • A still‑persisted tooltipDescription that surfaces in ProgramRewardModifiersTooltip, but has no visible editing UI until the pencil button is toggled again.

If the intent is “disable the whole custom description + tooltip block,” consider also clearing tooltipDescription here:

onClick={() => {
  setValue("description", null, { shouldDirty: true });
  setValue("tooltipDescription", "", { shouldDirty: true });
}}

(or whatever “empty” value your schema expects).

If you do want to support “tooltip only” rewards, it might be worth making that explicit in the copy and keeping an explicit control to clear just the tooltip.

Also applies to: 221-231, 485-525, 531-533

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd3e8e2 and 60a44ae.

📒 Files selected for processing (11)
  • apps/web/lib/actions/partners/create-reward.ts (2 hunks)
  • apps/web/lib/actions/partners/update-reward.ts (2 hunks)
  • apps/web/lib/zod/schemas/rewards.ts (2 hunks)
  • apps/web/ui/partners/program-reward-description.tsx (2 hunks)
  • apps/web/ui/partners/program-reward-list.tsx (1 hunks)
  • apps/web/ui/partners/program-reward-modifiers-tooltip.tsx (1 hunks)
  • apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx (10 hunks)
  • apps/web/ui/partners/rewards/reward-preview-card.tsx (1 hunks)
  • apps/web/ui/shared/inline-badge-popover.tsx (4 hunks)
  • packages/prisma/schema/reward.prisma (1 hunks)
  • packages/ui/src/tooltip.tsx (2 hunks)
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: TWilson023
Repo: dubinc/dub PR: 2673
File: apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx:56-66
Timestamp: 2025-07-30T15:25:13.936Z
Learning: In apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx, the form schema uses partial condition objects to allow users to add empty/unconfigured condition fields without type errors, while submission validation uses strict schemas to ensure data integrity. This two-stage validation pattern improves UX by allowing progressive completion of complex forms.
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/profile-details-form.tsx:180-189
Timestamp: 2025-09-24T15:50:16.414Z
Learning: TWilson023 prefers to keep security vulnerability fixes separate from refactoring PRs when the vulnerable code is existing and was only moved/relocated rather than newly introduced.
📚 Learning: 2025-07-30T15:29:54.131Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2673
File: apps/web/ui/partners/rewards/rewards-logic.tsx:268-275
Timestamp: 2025-07-30T15:29:54.131Z
Learning: In apps/web/ui/partners/rewards/rewards-logic.tsx, when setting the entity field in a reward condition, dependent fields (attribute, operator, value) should be reset rather than preserved because different entities (customer vs sale) have different available attributes. Maintaining existing fields when the entity changes would create invalid state combinations and confusing UX.

Applied to files:

  • apps/web/lib/actions/partners/update-reward.ts
  • apps/web/lib/actions/partners/create-reward.ts
  • apps/web/ui/partners/program-reward-list.tsx
  • apps/web/ui/partners/program-reward-description.tsx
  • apps/web/ui/partners/rewards/reward-preview-card.tsx
  • apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx
📚 Learning: 2025-08-14T05:17:51.825Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2735
File: apps/web/lib/actions/partners/delete-reward.ts:33-41
Timestamp: 2025-08-14T05:17:51.825Z
Learning: In the partner groups system, a rewardId can only belong to one group, establishing a one-to-one relationship between rewards and groups. This means using Prisma's `update` method (rather than `updateMany`) is appropriate when updating groups by rewardId.

Applied to files:

  • apps/web/lib/actions/partners/update-reward.ts
📚 Learning: 2025-08-26T14:20:23.943Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2736
File: apps/web/app/api/workspaces/[idOrSlug]/notification-preferences/route.ts:13-14
Timestamp: 2025-08-26T14:20:23.943Z
Learning: The updateNotificationPreference action in apps/web/lib/actions/update-notification-preference.ts already handles all notification preference types dynamically, including newBountySubmitted, through its schema validation using the notificationTypes enum and Prisma's dynamic field update pattern.

Applied to files:

  • apps/web/lib/actions/partners/update-reward.ts
📚 Learning: 2025-07-30T15:25:13.936Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2673
File: apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx:56-66
Timestamp: 2025-07-30T15:25:13.936Z
Learning: In apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx, the form schema uses partial condition objects to allow users to add empty/unconfigured condition fields without type errors, while submission validation uses strict schemas to ensure data integrity. This two-stage validation pattern improves UX by allowing progressive completion of complex forms.

Applied to files:

  • apps/web/lib/actions/partners/update-reward.ts
  • apps/web/lib/actions/partners/create-reward.ts
  • apps/web/ui/partners/program-reward-list.tsx
  • apps/web/lib/zod/schemas/rewards.ts
  • apps/web/ui/partners/program-reward-description.tsx
  • apps/web/ui/partners/rewards/reward-preview-card.tsx
  • apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx
📚 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/lib/actions/partners/create-reward.ts
  • apps/web/ui/partners/program-reward-description.tsx
  • apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx
📚 Learning: 2025-09-24T16:09:52.724Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/ui/partners/online-presence-form.tsx:181-186
Timestamp: 2025-09-24T16:09:52.724Z
Learning: The cn utility function in this codebase uses tailwind-merge, which automatically resolves conflicting Tailwind classes by giving precedence to later classes in the className string. Therefore, patterns like `cn("gap-6", variant === "settings" && "gap-4")` are valid and will correctly apply gap-4 when the condition is true.

Applied to files:

  • packages/ui/src/tooltip.tsx
📚 Learning: 2025-10-15T01:05:43.266Z
Learnt from: steven-tey
Repo: dubinc/dub PR: 2958
File: apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx:432-457
Timestamp: 2025-10-15T01:05:43.266Z
Learning: In apps/web/app/app.dub.co/(dashboard)/[slug]/settings/members/page-client.tsx, defer refactoring the custom MenuItem component (lines 432-457) to use the shared dub/ui MenuItem component to a future PR, as requested by steven-tey.

Applied to files:

  • apps/web/ui/shared/inline-badge-popover.tsx
📚 Learning: 2025-09-24T16:10:37.349Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/ui/partners/partner-about.tsx:11-11
Timestamp: 2025-09-24T16:10:37.349Z
Learning: In the Dub codebase, the team prefers to import Icon as a runtime value from "dub/ui" and uses Icon as both a type and variable name in component props, even when this creates shadowing. This is their established pattern and should not be suggested for refactoring.

Applied to files:

  • apps/web/ui/shared/inline-badge-popover.tsx
📚 Learning: 2025-09-24T15:47:40.293Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx:152-157
Timestamp: 2025-09-24T15:47:40.293Z
Learning: The Button component from dub/ui automatically adds type="button" when an onClick prop is passed, preventing accidental form submissions without requiring explicit type specification.

Applied to files:

  • apps/web/ui/shared/inline-badge-popover.tsx
📚 Learning: 2025-09-24T15:47:40.293Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2872
File: apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/about-you-form.tsx:152-157
Timestamp: 2025-09-24T15:47:40.293Z
Learning: The Button component from dub/ui automatically adds type="button" when an onClick prop is passed, preventing accidental form submissions without requiring explicit type specification. The implementation uses: type={onClick ? "button" : type}

Applied to files:

  • apps/web/ui/shared/inline-badge-popover.tsx
🧬 Code graph analysis (7)
apps/web/ui/partners/program-reward-list.tsx (1)
apps/web/ui/partners/program-reward-modifiers-tooltip.tsx (1)
  • ProgramRewardModifiersTooltip (32-49)
apps/web/ui/partners/program-reward-modifiers-tooltip.tsx (1)
packages/ui/src/tooltip.tsx (1)
  • InfoTooltip (159-165)
packages/ui/src/tooltip.tsx (1)
packages/ui/src/rich-text-area/rich-text-provider.tsx (1)
  • PROSE_STYLES (20-24)
apps/web/ui/partners/program-reward-description.tsx (2)
apps/web/lib/types.ts (2)
  • RewardProps (536-536)
  • DiscountProps (463-463)
apps/web/ui/partners/program-reward-modifiers-tooltip.tsx (1)
  • ProgramRewardModifiersTooltip (32-49)
apps/web/ui/shared/inline-badge-popover.tsx (3)
packages/ui/src/rich-text-area/rich-text-provider.tsx (1)
  • RichTextProvider (69-242)
packages/ui/src/rich-text-area/index.tsx (1)
  • RichTextArea (9-32)
packages/ui/src/rich-text-area/rich-text-toolbar.tsx (1)
  • RichTextToolbar (16-129)
apps/web/ui/partners/rewards/reward-preview-card.tsx (6)
apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx (2)
  • useAddEditRewardForm (85-85)
  • getRewardPayload (87-142)
apps/web/ui/partners/constants.ts (1)
  • REWARD_EVENTS (3-25)
apps/web/ui/partners/program-reward-description.tsx (1)
  • ProgramRewardDescription (7-110)
apps/web/lib/types.ts (1)
  • EnrolledPartnerProps (451-451)
packages/ui/src/table/table.tsx (2)
  • useTable (51-243)
  • Table (341-675)
packages/utils/src/constants/misc.ts (1)
  • OG_AVATAR_URL (29-29)
apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx (4)
apps/web/lib/types.ts (1)
  • RewardConditionsArray (559-559)
apps/web/lib/zod/schemas/rewards.ts (4)
  • rewardConditionsArraySchema (156-158)
  • ENTITY_ATTRIBUTE_TYPES (39-64)
  • REWARD_DESCRIPTION_MAX_LENGTH (178-178)
  • REWARD_TOOLTIP_DESCRIPTION_MAX_LENGTH (179-179)
apps/web/ui/shared/inline-badge-popover.tsx (2)
  • InlineBadgePopover (38-90)
  • InlineBadgePopoverRichTextArea (316-381)
apps/web/ui/partners/rewards/reward-preview-card.tsx (1)
  • RewardPreviewCard (14-46)
⏰ 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 (11)
packages/ui/src/tooltip.tsx (1)

11-11: LGTM: Condensed prose styling for tooltips

The addition of condensed prose styling reduces vertical spacing in tooltip content, which is appropriate for compact tooltip displays.

Also applies to: 33-33

apps/web/ui/shared/inline-badge-popover.tsx (2)

38-90: LGTM: Extended InlineBadgePopover with optional styling variants

The addition of showOptional and contentClassName props provides flexible styling options while maintaining backward compatibility. The neutral color variant for optional fields is a good UX pattern.


316-381: LGTM: Well-structured rich text area component

The InlineBadgePopoverRichTextArea component properly integrates rich text editing with:

  • Markdown support with bold, italic, and links
  • Keyboard shortcut (Cmd/Ctrl+Enter) to close popover
  • Character count display
  • Markdown mode indicator

The implementation follows the established RichTextProvider pattern used elsewhere in the codebase.

apps/web/lib/actions/partners/update-reward.ts (1)

26-26: LGTM: tooltipDescription added to update flow

The tooltipDescription field follows the same pattern as the existing description field with appropriate null fallback. The schema validation ensures proper constraints are applied.

Also applies to: 59-59

packages/prisma/schema/reward.prisma (1)

16-16: LGTM: Optional tooltipDescription field added

The optional tooltipDescription field is appropriate for storing additional descriptive content. The nullable String type is consistent with the existing description field pattern.

apps/web/lib/actions/partners/create-reward.ts (1)

30-30: LGTM: tooltipDescription added to creation flow

The tooltipDescription field is properly integrated into the reward creation flow, following the same pattern as the existing description field with appropriate null fallback.

Also applies to: 68-68

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

35-48: LGTM: Tooltip content logic supports custom descriptions

The component correctly handles both tooltipDescription and modifiers content:

  • Returns early when neither exists
  • Prioritizes tooltipDescription when present
  • Applies left-aligned styling for custom descriptions (more natural for reading longer text)
  • Falls back to structured modifiers content
apps/web/ui/partners/program-reward-list.tsx (1)

70-77: LGTM: Tooltip rendering condition broadened for custom descriptions

The rendering condition now correctly shows the tooltip when either modifiers exist or tooltipDescription is present. The Boolean() coercion ensures type safety and is consistent with the tooltip component's rendering logic.

apps/web/lib/zod/schemas/rewards.ts (1)

170-170: LGTM: Well-structured schema additions with proper constraints

The changes introduce tooltipDescription with clear length constraints:

  • Extracted magic number into REWARD_DESCRIPTION_MAX_LENGTH constant (good refactoring)
  • Added REWARD_TOOLTIP_DESCRIPTION_MAX_LENGTH (250 chars) for longer tooltip content
  • Both fields are properly validated and nullish
  • Exported constants enable UI components to display character limits

The longer max length for tooltipDescription (250) vs description (100) appropriately accommodates more detailed explanatory content.

Also applies to: 178-193

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

14-24: Prop narrowing and tooltip condition look consistent with tooltipDescription usage

Narrowing reward to a Pick<RewardProps, ...> that includes tooltipDescription matches how this component is used (particularly from the preview payload) and keeps the dependency surface small while still satisfying constructRewardAmount and the tooltip logic.

The updated modifiers block:

{showModifiersTooltip &&
  (!!reward.modifiers?.length || Boolean(reward.tooltipDescription)) && (
    <>
      {" "}
      <ProgramRewardModifiersTooltip reward={reward} />
    </>
  )}

is aligned with ProgramRewardModifiersTooltip’s own guard (!reward?.modifiers?.length && !reward?.tooltipDescription) and ensures the info icon appears even when only a custom tooltip (no modifiers) is configured.

No issues from a correctness or type‑safety perspective here.

Also applies to: 32-79

apps/web/ui/partners/rewards/add-edit-reward-sheet.tsx (1)

487-507: Nice integration of description limits and live preview

Hooking InlineBadgePopoverInput and InlineBadgePopoverRichTextArea up to REWARD_DESCRIPTION_MAX_LENGTH and REWARD_TOOLTIP_DESCRIPTION_MAX_LENGTH keeps the UI aligned with zod constraints and surfaces limits directly to the user.

Placing <RewardPreviewCard /> inline with the sheet and discount partners card makes the new tooltip behavior easy to verify in real time while editing.

No functional issues spotted in this section.

Also applies to: 509-525, 548-555

@steven-tey steven-tey merged commit bf6c8c4 into main Nov 22, 2025
7 of 8 checks passed
@steven-tey steven-tey deleted the reward-tooltip-description branch November 22, 2025 02:01
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