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

Skip to content

Conversation

@TWilson023
Copy link
Collaborator

@TWilson023 TWilson023 commented Nov 13, 2025

Screenshot 2025-11-13 at 12 19 01 PM

Summary by CodeRabbit

Release Notes

  • New Features

    • Added campaign filtering by trigger condition
    • Campaign editor now displays interactive warning when duplicate campaigns are detected, with links to view duplicates
  • Enhancements

    • Enhanced campaign type icon styling customization options
    • New clone icon added to UI component library

@vercel
Copy link
Contributor

vercel bot commented Nov 13, 2025

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

Project Deployment Preview Updated (UTC)
dub Ready Ready Preview Nov 13, 2025 5:35pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 13, 2025

Warning

Rate limit exceeded

@TWilson023 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 17 minutes and 38 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 83f07a5 and e001f0e.

📒 Files selected for processing (1)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/duplicate-logic-warning.tsx (1 hunks)

Walkthrough

This PR introduces duplicate campaign detection functionality. It adds API filtering by trigger condition, a new warning component that detects and displays campaigns with duplicate logic, extends the CampaignTypeIcon component for customization, introduces a new Clone2 SVG icon, and updates the query schema to support trigger condition filtering.

Changes

Cohort / File(s) Summary
API Filtering by Trigger Condition
apps/web/app/(ee)/api/campaigns/route.ts
Added triggerCondition query parameter to GET handler; implements Prisma filter to match campaigns by workflow's triggerConditions array when provided.
Query Schema
apps/web/lib/zod/schemas/campaigns.ts
Added optional triggerCondition field to getCampaignsQuerySchema with JSON parsing and validation against workflowConditionSchema.
Campaign Editor Integration
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/campaign-editor.tsx
Removed useProgram hook; added DuplicateLogicWarning component rendering conditioned on editable state.
Duplicate Detection Component
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/duplicate-logic-warning.tsx
New component that fetches campaigns with matching trigger conditions via SWR, filters duplicates, and renders collapsible UI listing duplicate campaigns with links and icons.
Icon Component Enhancement
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-type-icon.tsx
Added optional iconClassName prop to CampaignTypeIcon for customizing icon styling; internal variable renamed to avoid shadowing.
New Clone Icon
packages/ui/src/icons/nucleo/clone2.tsx, packages/ui/src/icons/nucleo/index.ts
Introduced new Clone2 SVG icon component with 18x18 viewBox; re-exported from icons index.

Sequence Diagram

sequenceDiagram
    actor User
    participant Editor as Campaign Editor
    participant Warning as Duplicate Warning
    participant API as Campaigns API
    participant DB as Database

    User->>Editor: Open campaign for editing
    activate Editor
    Editor->>Warning: Render (with triggerCondition)
    activate Warning
    Warning->>API: GET /api/campaigns?triggerCondition={condition}
    activate API
    API->>DB: Query campaigns by triggerCondition
    DB-->>API: Return matching campaigns
    API-->>Warning: Campaign list
    deactivate API
    Warning->>Warning: Filter duplicates<br/>(exclude current, draft, canceled)
    alt Duplicates found
        Warning->>Warning: Render accordion with duplicates
        Warning-->>User: Show warning with duplicate links
    else No duplicates
        Warning->>Warning: Hide/disable accordion
    end
    deactivate Warning
    deactivate Editor
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • The DuplicateLogicWarning component introduces new data-fetching and filtering logic that requires careful review of the SWR integration, duplicate detection criteria, and state management.
  • API filtering implementation is straightforward but should be verified against the schema validation.
  • Multiple inter-dependent changes across schema, API, and UI layers require tracing the flow to ensure consistency.

Areas requiring extra attention:

  • SWR fetch logic in duplicate-logic-warning.tsx and error handling
  • Prisma filter correctness for triggerConditions array matching in the API route
  • Schema validation pipeline with JSON parsing in getCampaignsQuerySchema
  • Component integration points between campaign-editor.tsx and duplicate-logic-warning.tsx regarding context and form data passing

Possibly related PRs

  • Email campaign workflows #2891: Modified the same campaigns API route (apps/web/app/(ee)/api/campaigns/route.ts) and introduced foundational workflow/campaign wiring; this PR extends that endpoint with trigger condition filtering.

Suggested reviewers

  • steven-tey

Poem

🐰 A rabbit's tail of clones so neat,
Duplicates spotted, warnings sweet!
With icons fresh and filters bright,
Campaign logic shines just right! ✨

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 a warning component that detects and displays duplicate campaigns based on logic/trigger conditions.

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

🧹 Nitpick comments (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/duplicate-logic-warning.tsx (1)

74-78: Consider showing loading state only on initial load.

The loading spinner appears every time the trigger condition changes due to keepPreviousData: true. This might create a flickering effect during form editing. Consider showing the spinner only when there's no previous data.

- {isLoading ? (
+ {isLoading && !campaigns ? (
    <LoadingSpinner className="size-3 shrink-0" />
  ) : (
    <Clone2 className="text-content-emphasis size-3 shrink-0" />
  )}

This way, the Clone2 icon remains visible during background refreshes, providing a smoother UX.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ae4aab6 and 83f07a5.

📒 Files selected for processing (7)
  • apps/web/app/(ee)/api/campaigns/route.ts (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/campaign-editor.tsx (2 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/duplicate-logic-warning.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-type-icon.tsx (1 hunks)
  • apps/web/lib/zod/schemas/campaigns.ts (1 hunks)
  • packages/ui/src/icons/nucleo/clone2.tsx (1 hunks)
  • packages/ui/src/icons/nucleo/index.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
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: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/zod/schemas/campaigns.ts
📚 Learning: 2025-08-25T17:33:45.072Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2736
File: apps/web/app/(ee)/api/stripe/integration/webhook/invoice-paid.ts:12-12
Timestamp: 2025-08-25T17:33:45.072Z
Learning: The WorkflowTrigger enum in packages/prisma/schema/workflow.prisma contains three values: leadRecorded, saleRecorded, and commissionEarned. All three are properly used throughout the codebase.

Applied to files:

  • apps/web/lib/zod/schemas/campaigns.ts
📚 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/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/duplicate-logic-warning.tsx
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-type-icon.tsx
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/campaign-editor.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/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-type-icon.tsx
📚 Learning: 2025-05-29T04:45:18.504Z
Learnt from: devkiran
Repo: dubinc/dub PR: 2448
File: packages/email/src/templates/partner-program-summary.tsx:0-0
Timestamp: 2025-05-29T04:45:18.504Z
Learning: In the PartnerProgramSummary email template (packages/email/src/templates/partner-program-summary.tsx), the stat titles are hardcoded constants ("Clicks", "Leads", "Sales", "Earnings") that will always match the ICONS object keys after toLowerCase() conversion, so icon lookup failures are not possible.

Applied to files:

  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-type-icon.tsx
🧬 Code graph analysis (4)
apps/web/lib/zod/schemas/campaigns.ts (1)
apps/web/lib/zod/schemas/workflows.ts (1)
  • workflowConditionSchema (66-70)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/duplicate-logic-warning.tsx (4)
apps/web/lib/swr/use-workspace.ts (1)
  • useWorkspace (6-46)
apps/web/lib/zod/schemas/workflows.ts (1)
  • workflowConditionSchema (66-70)
apps/web/lib/types.ts (1)
  • CampaignList (629-629)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-type-icon.tsx (1)
  • CampaignTypeIcon (4-27)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-type-icon.tsx (2)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-type-badges.tsx (1)
  • CAMPAIGN_TYPE_BADGES (3-16)
packages/ui/src/icons/index.tsx (1)
  • Icon (80-80)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/campaign-editor.tsx (1)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/duplicate-logic-warning.tsx (1)
  • DuplicateLogicWarning (14-122)
🔇 Additional comments (2)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/campaign-type-icon.tsx (1)

4-27: LGTM! Clean prop enhancement with proper shadowing avoidance.

The refactor correctly introduces the iconClassName prop while avoiding variable shadowing by renaming the internal variable to typeIconClassName. This enables customization of the icon's styling independently from the container's styling.

apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/campaigns/[campaignId]/duplicate-logic-warning.tsx (1)

27-39: The review comment regarding JSON serialization in query parameters is incorrect.

The codebase already implements the proper pattern: the getCampaignsQuerySchema uses .pipe() with .preprocess() to convert the JSON string from query parameters back into a parsed object, then validates it against workflowConditionSchema.

Since the schema contains only three small fields (attribute enum, operator enum, and value number), URL length limitations are not a realistic concern here. The serialized size will be minimal (under 200 characters).

The current implementation is correct and handles JSON in query strings properly without needing changes.

Likely an incorrect or invalid review comment.

Comment on lines +109 to +117
triggerCondition: z
.string()
.pipe(
z.preprocess(
(input: string) => JSON.parse(input),
workflowConditionSchema,
),
)
.optional(),
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Harden triggerCondition parsing against malformed input.

JSON.parse inside the preprocess will throw a SyntaxError for any malformed triggerCondition query string. Because this happens during getCampaignsQuerySchema.parse, the exception bypasses Zod’s validation path and bubbles out as a 500 response instead of a 400. Please guard the parse and surface a validation error, e.g.:

-    triggerCondition: z
-      .string()
-      .pipe(
-        z.preprocess(
-          (input: string) => JSON.parse(input),
-          workflowConditionSchema,
-        ),
-      )
-      .optional(),
+    triggerCondition: z
+      .string()
+      .transform((raw) => {
+        try {
+          return JSON.parse(raw);
+        } catch {
+          throw new z.ZodError([
+            {
+              code: z.ZodIssueCode.custom,
+              message: "triggerCondition must be valid JSON",
+              path: ["triggerCondition"],
+            },
+          ]);
+        }
+      })
+      .pipe(workflowConditionSchema)
+      .optional(),

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In apps/web/lib/zod/schemas/campaigns.ts around lines 109 to 117, the preprocess
currently calls JSON.parse directly which will throw on malformed input and
escape Zod's validation flow; wrap the JSON.parse call in a try/catch inside the
preprocess, return the parsed value on success and (on failure) return the
original input (or undefined) so that workflowConditionSchema receives a
non-parsed value and Zod produces a validation error (400) instead of letting
the SyntaxError bubble up; ensure no raw exceptions are thrown from the
preprocess.

@steven-tey steven-tey enabled auto-merge November 13, 2025 17:27
@steven-tey steven-tey merged commit 7c16bf1 into main Nov 13, 2025
7 of 8 checks passed
@steven-tey steven-tey deleted the duplicate-campaign-logic branch November 13, 2025 20: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