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

Skip to content

Conversation

@TWilson023
Copy link
Collaborator

@TWilson023 TWilson023 commented Oct 21, 2025

Adds a new "Confirm bounty creation" modal with a checkbox for whether to send notification emails to partners

Screenshot 2025-10-21 at 4 40 13 PM

Summary by CodeRabbit

  • New Features

    • Confirmation modal when creating a bounty showing details, dates, rewards and recipient count
    • Optional "Send notifications" toggle when creating a bounty (plan-gated)
    • Creation flow now accepts a sendNotificationEmails flag
    • New partners upgrade modal and in-place upgrade buttons in messaging and resources flows
    • Plan-based gating for email campaign availability and updated plan feature descriptions
  • Chores

    • Removed automatic partner notifications triggered when a bounty's start date changes

@vercel
Copy link
Contributor

vercel bot commented Oct 21, 2025

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

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Oct 22, 2025 0:28am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 21, 2025

Walkthrough

Adds an optional sendNotificationEmails flag to bounty creation and gates partner-notification publishing by a new plan capability; introduces a confirm-create modal with a notification toggle in the UI; updates plan-capabilities and partner/upgrade modal usages; removes qstash-based publish on bounty startsAt updates.

Changes

Cohort / File(s) Summary
API — create handler
apps/web/app/(ee)/api/bounties/route.ts
Parse optional sendNotificationEmails on POST create; retrieve plan capability (canSendEmailCampaigns) and only publish notify-partners when sendNotificationEmails and capability are true.
API — update handler
apps/web/app/(ee)/api/bounties/[bountyId]/route.ts
Remove qstash publish block and qstash / APP_DOMAIN_WITH_NGROK imports; delete runtime publish on startsAt changes.
UI — bounty creation sheet
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/add-edit-bounty-sheet.tsx
Replace prior confirm flow with useConfirmCreateBountyModal; add groupIds state and include groups in payload; propagate sendNotificationEmails to POST body; expose setShowCreateBountySheet from useBountySheet.
UI — confirm-create modal & hook
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx
New ConfirmCreateBountyModal and useConfirmCreateBountyModal hook: shows bounty preview, send-notifications toggle gated by plan capability with upgrade tooltip, calls onConfirm(sendNotificationEmails).
Plan capability & helpers
apps/web/lib/plan-capabilities.ts, apps/web/lib/swr/use-partners-count-bounty.ts
Add canSendEmailCampaigns flag to plan capabilities (enabled for advanced/enterprise); narrow usePartnersCountBounty input type to { groups }.
Validation schema
apps/web/lib/zod/schemas/bounties.ts
Add optional sendNotificationEmails: z.boolean().optional() to createBountySchema.
Partners upgrade & messaging UI
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/messages/messages-upsell.tsx, apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/resources/program-help-and-support.tsx, apps/web/ui/partners/partners-upgrade-modal.tsx
Replace link-based upgrade flows with usePartnersUpgradeModal modal pattern; update plan feature entries and icons in partners-upgrade-modal; render modal and trigger via button/setter.
Integrations tooltip adjustment
apps/web/app/app.dub.co/(dashboard)/[slug]/settings/(basic-layout)/integrations/[integrationSlug]/page-client.tsx
Restrict HubSpot disabled tooltip to explicit plans ["free","pro"] (plan truthiness + includes check) and update tooltip text.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Sheet as Bounty Sheet (UI)
    participant Modal as ConfirmCreateBountyModal
    participant API as Bounty API
    participant Queue as Queue (notify-partners)

    User->>Sheet: Fill form & submit
    Sheet->>Modal: Open confirm modal (preview)
    alt Plan allows email campaigns
        Modal->>User: Show sendNotificationEmails toggle (enabled)
    else
        Modal->>User: Show disabled toggle + upgrade tooltip
    end
    User->>Modal: Confirm (with sendNotificationEmails true/false)
    Modal->>API: POST /bounties { ..., sendNotificationEmails }
    API->>API: Validate & create bounty
    alt sendNotificationEmails && canSendEmailCampaigns
        API->>Queue: Publish notify-partners job
        Queue-->>API: Scheduled
    else
        API->>API: Skip partner notification publish
    end
    API-->>Sheet: Return created bounty
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Improve webhooks page #2729: Also modifies getPlanCapabilities to add new capability flags — likely overlaps with the new canSendEmailCampaigns addition.
  • Bounties updates #2786: Changes the bounty PATCH/update handler — related to the removed qstash publish behavior in the bounty update route.
  • Updates for dub.co pricing page #2680: Touches PLAN_FEATURE_ICONS used by the partners upgrade modal — likely related to the icon/feature adjustments in partners-upgrade-modal.tsx.

Poem

🐰 I tapped a toggle, soft and small,
"Shall partners hear?" — I asked the hall.
Plans hold the key, the modal said,
I hop, I wait, then nod my head.
A tiny rabbit seals the call.

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 pull request title "Create bounty confirmation improvements" is directly related to the main change in the changeset. According to the PR objectives and file summaries, the primary focus is adding a new "Confirm bounty creation" modal that allows users to choose whether to send notification emails to partners. The title accurately describes this core feature—introducing a confirmation flow with improvements to the bounty creation experience. While the changeset includes supporting infrastructure (API gating, plan capabilities, schema updates), the user-facing primary change is the confirmation modal and its associated workflow, which the title clearly captures.
✨ 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 create-bounty-confirmation

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.

@TWilson023 TWilson023 requested a review from steven-tey October 21, 2025 21:03
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 (1)
apps/web/app/(ee)/api/bounties/[bountyId]/route.ts (1)

218-227: Remove commented-out code.

The commented notification logic should be removed rather than left in the codebase. If this code might be needed in the future, document the decision in a comment or track it in an issue.

Apply this diff to remove the dead code:

-        // sendNotificationEmails &&
-        //   // if bounty.startsAt was updated, publish a new message to the queue
-        //   updatedBounty.startsAt.getTime() !== bounty.startsAt.getTime() &&
-        //   qstash.publishJSON({
-        //     url: `${APP_DOMAIN_WITH_NGROK}/api/cron/bounties/notify-partners`,
-        //     body: {
-        //       bountyId: updatedBounty.id,
-        //     },
-        //     notBefore: Math.floor(updatedBounty.startsAt.getTime() / 1000),
-        //   }),
       ]),
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9889d44 and f61cc6f.

📒 Files selected for processing (7)
  • apps/web/app/(ee)/api/bounties/[bountyId]/route.ts (2 hunks)
  • apps/web/app/(ee)/api/bounties/route.ts (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/add-edit-bounty-sheet.tsx (8 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (1 hunks)
  • apps/web/lib/plan-capabilities.ts (1 hunks)
  • apps/web/lib/swr/use-partners-count-bounty.ts (1 hunks)
  • apps/web/lib/zod/schemas/bounties.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-26T14:20:23.943Z
Learnt from: TWilson023
PR: dubinc/dub#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/zod/schemas/bounties.ts
🧬 Code graph analysis (3)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/add-edit-bounty-sheet.tsx (2)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (1)
  • useConfirmCreateBountyModal (180-196)
apps/web/lib/api/bounties/generate-performance-bounty-name.ts (1)
  • generatePerformanceBountyName (6-21)
apps/web/lib/swr/use-partners-count-bounty.ts (1)
apps/web/lib/types.ts (1)
  • BountyProps (584-584)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (5)
apps/web/lib/types.ts (1)
  • BountyProps (584-584)
apps/web/lib/plan-capabilities.ts (1)
  • getPlanCapabilities (4-22)
apps/web/lib/swr/use-partners-count-bounty.ts (1)
  • usePartnersCountBounty (5-37)
apps/web/lib/partners/get-bounty-reward-description.ts (1)
  • getBountyRewardDescription (4-20)
packages/ui/src/tooltip.tsx (2)
  • DynamicTooltipWrapper (280-294)
  • TooltipContent (90-128)
⏰ 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 (9)
apps/web/lib/zod/schemas/bounties.ts (1)

68-68: LGTM! Clean schema extension.

The optional sendNotificationEmails field is correctly added to the create schema. Note that it's appropriately excluded from the update schema (lines 71-77), ensuring notifications are only controlled during bounty creation, not updates.

apps/web/lib/plan-capabilities.ts (1)

19-20: LGTM! Capability flag follows established patterns.

The new canSendBountyNotifications capability correctly restricts bounty notifications to Advanced and Enterprise plans, consistent with other advanced features in the codebase.

apps/web/lib/swr/use-partners-count-bounty.ts (1)

5-9: LGTM! Good type narrowing.

Restricting the bounty parameter to only Pick<BountyProps, "groups"> makes the function's dependencies explicit and more maintainable. This aligns well with the minimal data requirements for calculating partner counts.

apps/web/app/(ee)/api/bounties/route.ts (1)

162-162: LGTM! Field extraction is clean.

The sendNotificationEmails field is correctly extracted from the validated request body.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/add-edit-bounty-sheet.tsx (3)

397-420: LGTM! Clean modal integration with proper validation gating.

The confirmation modal is correctly instantiated with a computed bounty object. The conditional construction (!validationError && rewardAmount) ensures the modal only receives valid data, preventing premature confirmations.


423-425: LGTM! Clean parameter addition.

The performSubmit function correctly accepts an optional sendNotificationEmails parameter with proper TypeScript typing.


480-488: LGTM! Proper flow separation for create vs. update.

The conditional logic correctly handles the different flows: updates submit directly (line 483), while creation shows the confirmation modal first (line 486). This provides a better UX for the creation flow without impacting updates.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (2)

63-178: LGTM! Well-structured confirmation modal with excellent UX.

The modal implementation includes:

  • Clear bounty preview with thumbnail, dates, and reward
  • Dynamic partner count with loading state
  • Plan-gated notification toggle with upgrade prompt
  • Proper loading/disabled states during submission

The integration of DynamicTooltipWrapper and plan capability checks provides a smooth upgrade path for users on lower-tier plans.


180-196: LGTM! Clean hook pattern.

The useConfirmCreateBountyModal hook follows React patterns well, exposing both the modal component and its visibility control function.

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 (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (1)

137-139: Consider more explicit boolean coercion.

The onCheckedChange callback receives checked which can be true | false | 'indeterminate' from Radix UI. While Boolean('indeterminate') evaluates to true, it would be clearer to use checked === true to be explicit about the intended behavior, even though this checkbox doesn't use the indeterminate state.

Apply this diff for more explicit handling:

-              onCheckedChange={(checked) =>
-                setSendNotificationEmails(Boolean(checked))
-              }
+              onCheckedChange={(checked) =>
+                setSendNotificationEmails(checked === true)
+              }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f61cc6f and b014b32.

📒 Files selected for processing (2)
  • apps/web/app/(ee)/api/bounties/route.ts (4 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/app/(ee)/api/bounties/route.ts
🧰 Additional context used
🧬 Code graph analysis (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (5)
apps/web/lib/types.ts (1)
  • BountyProps (584-584)
apps/web/lib/plan-capabilities.ts (1)
  • getPlanCapabilities (4-22)
apps/web/lib/swr/use-partners-count-bounty.ts (1)
  • usePartnersCountBounty (5-37)
apps/web/lib/partners/get-bounty-reward-description.ts (1)
  • getBountyRewardDescription (4-20)
packages/ui/src/tooltip.tsx (2)
  • DynamicTooltipWrapper (280-294)
  • TooltipContent (90-128)
⏰ 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/confirm-create-bounty-modal.tsx (1)

46-49: Past review feedback addressed correctly.

The state initialization now properly derives from canSendBountyNotifications, ensuring the internal state matches the UI capability from the start. This resolves the inconsistency noted in the previous review.

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

♻️ Duplicate comments (2)
apps/web/app/(ee)/api/bounties/route.ts (1)

163-165: Return 403 when sendNotificationEmails is requested but not allowed.

Avoid silently ignoring a client’s request; fail fast with a clear error. This aligns API behavior with UI gating and prevents confusing no‑ops.

@@
-    const { canSendEmailCampaigns } = getPlanCapabilities(workspace.plan);
+    const { canSendEmailCampaigns } = getPlanCapabilities(workspace.plan);
+    if (sendNotificationEmails && !canSendEmailCampaigns) {
+      throw new DubApiError({
+        code: "forbidden",
+        message: "Bounty notifications are not available on your plan.",
+      });
+    }
@@
-        sendNotificationEmails &&
-          canSendEmailCampaigns &&
+        sendNotificationEmails &&
+          canSendEmailCampaigns &&
           qstash.publishJSON({

Also applies to: 270-303

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (1)

46-49: Nice fix on default state.

Initializing from canSendEmailCampaigns resolves the previous UI inconsistency.

🧹 Nitpick comments (5)
apps/web/ui/partners/partners-upgrade-modal.tsx (2)

218-238: Use semantic list markup for features and tighten icon typing.

  • elements should live inside a
      /
        for a11y/semantics.
      1. Indexing PLAN_FEATURE_ICONS with a string id can yield implicit any; cast to a typed Record to satisfy TS.

    Apply:

    -            {features.map(({ id, text, tooltip }) => {
    -              const Icon =
    -                id && PLAN_FEATURE_ICONS[id] ? PLAN_FEATURE_ICONS[id] : Check;
    +            {features.map(({ id, text, tooltip }) => {
    +              const Icon =
    +                (PLAN_FEATURE_ICONS as Record<string, import("@/../packages/ui/src/icons").Icon>)[id] ??
    +                Check;
                   return (
    -                <li
    +                <li
                       key={id}
                       className="flex items-center gap-2 text-neutral-600"
                     >
                       <Icon className="size-3 shrink-0 [&_*]:stroke-2" />

    And wrap the list with a semantic container (change outside the mapped block):

    -          <div className="mt-6 flex flex-col gap-2 text-sm">
    +          <ul role="list" className="mt-6 flex flex-col gap-2 text-sm">
     ...
    -          </div>
    +          </ul>

    89-97: Consider formatting the groups count for consistency.

    If plan.limits.groups can be 1,000+, use nFormatter to match payouts formatting. Example:

    -            text: `${plan.limits.groups} partner groups`,
    +            text: `${nFormatter(plan.limits.groups)} partner groups`,
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/messages/messages-upsell.tsx (1)

53-57: Minor a11y: hint intent to open a dialog.

Add aria attributes to make the button’s behavior clearer to assistive tech.

-          <Button
-            onClick={() => setShowPartnersUpgradeModal(true)}
-            text="Upgrade to Advanced"
-            className="h-8 px-3"
-          />
+          <Button
+            onClick={() => setShowPartnersUpgradeModal(true)}
+            text="Upgrade to Advanced"
+            className="h-8 px-3"
+            aria-haspopup="dialog"
+            aria-expanded="false"
+          />
apps/web/app/app.dub.co/(dashboard)/[slug]/settings/(basic-layout)/integrations/[integrationSlug]/page-client.tsx (1)

274-283: Gating condition looks good; two small nits.

  • Brand: “HubSpot” (capital S).
  • Guard for undefined workspaceId to avoid the non‑null assertion crash if the user clicks before workspace loads.

Apply:

-                      title="Hubspot integration is only available on Business plans and above. Upgrade to get started."
+                      title="HubSpot integration is only available on Business plans and above. Upgrade to get started."

And defensively guard the click handler:

-                  execute({
-                    workspaceId: workspaceId!,
+                  if (!workspaceId) {
+                    toast.error("Workspace is still loading. Please try again.");
+                    return;
+                  }
+                  execute({
+                    workspaceId,
                     integrationSlug: integration.slug,
                   });
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (1)

46-50: Resync default when the modal opens to avoid stale state.

If plan loads after mount, the initial false won’t flip to true. Reinitialize on open.

-import { Dispatch, SetStateAction, useState } from "react";
+import { Dispatch, SetStateAction, useEffect, useState } from "react";
@@
   const [sendNotificationEmails, setSendNotificationEmails] = useState(
     canSendEmailCampaigns,
   );
+  useEffect(() => {
+    if (showConfirmCreateBountyModal) {
+      setSendNotificationEmails(canSendEmailCampaigns);
+    }
+  }, [showConfirmCreateBountyModal, canSendEmailCampaigns]);

Also applies to: 65-77

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71da578 and 7b63c1d.

📒 Files selected for processing (8)
  • apps/web/app/(ee)/api/bounties/[bountyId]/route.ts (1 hunks)
  • apps/web/app/(ee)/api/bounties/route.ts (4 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/messages/messages-upsell.tsx (3 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/resources/program-help-and-support.tsx (3 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/settings/(basic-layout)/integrations/[integrationSlug]/page-client.tsx (1 hunks)
  • apps/web/lib/plan-capabilities.ts (1 hunks)
  • apps/web/ui/partners/partners-upgrade-modal.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/lib/plan-capabilities.ts
  • apps/web/app/(ee)/api/bounties/[bountyId]/route.ts
🧰 Additional context used
🧬 Code graph analysis (6)
apps/web/app/(ee)/api/bounties/route.ts (1)
apps/web/lib/plan-capabilities.ts (1)
  • getPlanCapabilities (4-21)
apps/web/app/app.dub.co/(dashboard)/[slug]/settings/(basic-layout)/integrations/[integrationSlug]/page-client.tsx (1)
packages/ui/src/tooltip.tsx (1)
  • TooltipContent (90-128)
apps/web/ui/partners/partners-upgrade-modal.tsx (2)
packages/ui/src/icons/index.tsx (1)
  • Icon (80-80)
packages/ui/src/icons/plan-feature-icons.tsx (1)
  • PLAN_FEATURE_ICONS (34-70)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/messages/messages-upsell.tsx (1)
apps/web/ui/partners/partners-upgrade-modal.tsx (1)
  • usePartnersUpgradeModal (273-292)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/bounties/confirm-create-bounty-modal.tsx (5)
apps/web/lib/types.ts (1)
  • BountyProps (584-584)
apps/web/lib/plan-capabilities.ts (1)
  • getPlanCapabilities (4-21)
apps/web/lib/swr/use-partners-count-bounty.ts (1)
  • usePartnersCountBounty (5-39)
apps/web/lib/partners/get-bounty-reward-description.ts (1)
  • getBountyRewardDescription (4-20)
packages/ui/src/tooltip.tsx (2)
  • DynamicTooltipWrapper (280-294)
  • TooltipContent (90-128)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/resources/program-help-and-support.tsx (4)
apps/web/ui/partners/partners-upgrade-modal.tsx (1)
  • usePartnersUpgradeModal (273-292)
apps/web/app/(ee)/partners.dub.co/(dashboard)/profile/settings-row.tsx (1)
  • SettingsRow (3-28)
apps/web/lib/plan-capabilities.ts (1)
  • getPlanCapabilities (4-21)
packages/ui/src/tooltip.tsx (1)
  • TooltipContent (90-128)
⏰ 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 (7)
apps/web/ui/partners/partners-upgrade-modal.tsx (2)

79-87: Advanced “Messaging center” addition looks good.

Feature id aligns with PLAN_FEATURE_ICONS.messages and the help link is correct.


115-117: Enterprise “Unlimited partner groups” normalization to id "users" is consistent.

Matches PLAN_FEATURE_ICONS.users and avoids the previous "groups" mismatch.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/resources/program-help-and-support.tsx (2)

48-52: Modal integration pattern is solid.

Hook usage and element injection look correct.


124-151: Review comment is incorrect—Switch component already prevents toggling when disabledTooltip is set.

The Switch component's logic at line 29 is: switchDisabled = disabledTooltip ? true : disabled || loading. When disabledTooltip is provided (truthy), it automatically sets switchDisabled = true and passes this to the underlying Radix UI Switch's disabled prop. This prevents any client-side toggling.

The code in the PR already implements this correctly—providing disabledTooltip is sufficient. Adding an explicit disabled prop alongside it would be redundant, as disabledTooltip takes precedence and achieves the desired behavior.

Likely an incorrect or invalid review comment.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/messages/messages-upsell.tsx (2)

9-13: Good modal-based upgrade flow.

Hook usage and rendering are correct.


23-23: Render location of modal element is fine.

Keeping the modal element in-tree here is okay; Modal should portal to body.

apps/web/app/(ee)/api/bounties/route.ts (1)

270-303: Good: gating notification publish by plan capability.

The conditional publish using canSendEmailCampaigns is correct.

@steven-tey steven-tey merged commit 99456fe into main Oct 22, 2025
7 checks passed
@steven-tey steven-tey deleted the create-bounty-confirmation branch October 22, 2025 00:40
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