-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Fix lander calculator getProgramApplicationRewardsAndDiscount #2639
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis change refactors how rewards and discounts are fetched, processed, and passed into partner program landing page components. It introduces new hooks and helper functions to consistently merge rewards, discounts, and lander-specific data into the Changes
Sequence Diagram(s)sequenceDiagram
participant UI as UI Component (Block)
participant Hooks as useRewards/useDiscounts
participant Helper as getProgramApplicationRewardsAndDiscount
participant DB as Prisma
UI->>Hooks: Fetch rewards and discounts
UI->>Helper: Merge rewards, discounts, landerData into program prop
UI->>Block: Render with extended program prop
Possibly related PRs
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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/ui/partners/lander/blocks/earnings-calculator-block.tsx (1)
32-32: Consider a fallback state instead of returning null.Returning
nullwhen no rewards are found causes the entire earnings calculator block to disappear. Consider showing a placeholder or disabled state to maintain layout consistency and provide better user feedback.- if (!rewards.length) return null; + if (!rewards.length) { + return ( + <div className="space-y-5"> + {showTitleAndDescription && ( + <div className="space-y-2"> + <BlockTitle title="Earnings calculator" /> + <BlockDescription description="Earnings calculator will be available once rewards are configured." /> + </div> + )} + </div> + ); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/web/app/(ee)/partners.dub.co/(apply)/[programSlug]/page.tsx(1 hunks)apps/web/lib/actions/partners/generate-lander.ts(3 hunks)apps/web/ui/partners/design/modals/earnings-calculator-block-modal.tsx(3 hunks)apps/web/ui/partners/design/previews/lander-preview.tsx(3 hunks)apps/web/ui/partners/lander/blocks/earnings-calculator-block.tsx(2 hunks)
🧰 Additional context used
🧠 Learnings (5)
apps/web/app/(ee)/partners.dub.co/(apply)/[programSlug]/page.tsx (1)
Learnt from: TWilson023
PR: dubinc/dub#2614
File: apps/web/ui/partners/design/previews/lander-preview.tsx:181-181
Timestamp: 2025-07-09T20:52:56.571Z
Learning: In apps/web/ui/partners/design/previews/lander-preview.tsx, the ellipsis wave animation delay calculation `3 - i * -0.15` is intentionally designed to create negative delays that offset each dot's animation cycle. This pattern works correctly for the intended ellipsis effect and should not be changed to positive incremental delays.
apps/web/ui/partners/design/previews/lander-preview.tsx (2)
Learnt from: TWilson023
PR: dubinc/dub#2614
File: apps/web/ui/partners/design/previews/lander-preview.tsx:181-181
Timestamp: 2025-07-09T20:52:56.571Z
Learning: In apps/web/ui/partners/design/previews/lander-preview.tsx, the ellipsis wave animation delay calculation `3 - i * -0.15` is intentionally designed to create negative delays that offset each dot's animation cycle. This pattern works correctly for the intended ellipsis effect and should not be changed to positive incremental delays.
Learnt from: TWilson023
PR: dubinc/dub#2519
File: apps/web/ui/analytics/utils.ts:35-37
Timestamp: 2025-06-16T19:21:23.506Z
Learning: In the `useAnalyticsFilterOption` function in `apps/web/ui/analytics/utils.ts`, the pattern `options?.context ?? useContext(AnalyticsContext)` is intentionally designed as a complete replacement strategy, not a merge. When `options.context` is provided, it should contain all required fields (`baseApiPath`, `queryString`, `selectedTab`, `requiresUpgrade`) and completely replace the React context, not be merged with it. This is used for dependency injection or testing scenarios.
apps/web/ui/partners/design/modals/earnings-calculator-block-modal.tsx (2)
Learnt from: TWilson023
PR: dubinc/dub#2614
File: apps/web/ui/partners/design/previews/lander-preview.tsx:181-181
Timestamp: 2025-07-09T20:52:56.571Z
Learning: In apps/web/ui/partners/design/previews/lander-preview.tsx, the ellipsis wave animation delay calculation `3 - i * -0.15` is intentionally designed to create negative delays that offset each dot's animation cycle. This pattern works correctly for the intended ellipsis effect and should not be changed to positive incremental delays.
Learnt from: TWilson023
PR: dubinc/dub#2538
File: apps/web/ui/partners/overview/blocks/commissions-block.tsx:16-27
Timestamp: 2025-06-18T20:26:25.177Z
Learning: In the Dub codebase, components that use workspace data (workspaceId, defaultProgramId) are wrapped in `WorkspaceAuth` which ensures these values are always available, making non-null assertions safe. This is acknowledged as a common pattern in their codebase, though not ideal.
apps/web/lib/actions/partners/generate-lander.ts (3)
Learnt from: TWilson023
PR: dubinc/dub#2614
File: apps/web/ui/partners/design/previews/lander-preview.tsx:181-181
Timestamp: 2025-07-09T20:52:56.571Z
Learning: In apps/web/ui/partners/design/previews/lander-preview.tsx, the ellipsis wave animation delay calculation `3 - i * -0.15` is intentionally designed to create negative delays that offset each dot's animation cycle. This pattern works correctly for the intended ellipsis effect and should not be changed to positive incremental delays.
Learnt from: devkiran
PR: dubinc/dub#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.
Learnt from: devkiran
PR: dubinc/dub#2177
File: apps/web/lib/api/links/bulk-create-links.ts:66-84
Timestamp: 2025-06-06T07:59:03.120Z
Learning: In apps/web/lib/api/links/bulk-create-links.ts, the team accepts the risk of potential undefined results from links.find() operations when building invalidLinks arrays, because existing links are fetched from the database based on the input links, so matches are expected to always exist.
apps/web/ui/partners/lander/blocks/earnings-calculator-block.tsx (2)
Learnt from: TWilson023
PR: dubinc/dub#2614
File: apps/web/ui/partners/design/previews/lander-preview.tsx:181-181
Timestamp: 2025-07-09T20:52:56.571Z
Learning: In apps/web/ui/partners/design/previews/lander-preview.tsx, the ellipsis wave animation delay calculation `3 - i * -0.15` is intentionally designed to create negative delays that offset each dot's animation cycle. This pattern works correctly for the intended ellipsis effect and should not be changed to positive incremental delays.
Learnt from: devkiran
PR: dubinc/dub#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.
🧬 Code Graph Analysis (2)
apps/web/ui/partners/design/previews/lander-preview.tsx (2)
apps/web/lib/swr/use-rewards.ts (1)
useRewards(6-25)apps/web/lib/swr/use-discounts.ts (1)
useDiscounts(6-24)
apps/web/ui/partners/lander/blocks/earnings-calculator-block.tsx (2)
apps/web/lib/types.ts (1)
ProgramWithLanderDataProps(412-414)apps/web/lib/partners/get-program-application-rewards.ts (1)
getProgramApplicationRewardsAndDiscount(11-66)
⏰ 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 (5)
apps/web/app/(ee)/partners.dub.co/(apply)/[programSlug]/page.tsx (1)
59-63: LGTM: Clean enrichment of program prop with processed rewards and discount data.The spreading pattern correctly preserves existing program properties while adding the processed rewards and discount from the helper function.
apps/web/ui/partners/lander/blocks/earnings-calculator-block.tsx (1)
26-34: LGTM: Proper use of helper function with defensive programming.The helper function usage is correct and the early return prevents errors when no rewards are available. The type change to
ProgramWithLanderDataPropsis also appropriate.apps/web/lib/actions/partners/generate-lander.ts (3)
35-43: LGTM: Direct Prisma query with proper relations.The replacement of
getProgramOrThrowwith a direct Prisma query is clean and includes the necessaryrewardsanddiscountsrelations for the helper function.
45-46: LGTM: Consistent use of helper function.The helper function usage aligns with the pattern established in other files and properly extracts the processed rewards and discount data.
101-104: LGTM: Improved prompt generation with processed data.The prompt now uses the properly formatted rewards and discount data instead of raw program properties, which should result in better AI-generated content.
| const { rewards } = useRewards(); | ||
| const { discounts } = useDiscounts(); | ||
| const landerData = useWatch({ | ||
| control: brandingFormControl, | ||
| name: "landerData", | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Handle loading states for rewards and discounts data.
The useRewards and useDiscounts hooks return loading states, but they're not being handled here. If the data is still loading when passed to EarningsCalculatorBlock, it could cause rendering issues or incorrect calculations.
Consider handling the loading states:
const { rewards } = useRewards();
const { discounts } = useDiscounts();
+
+ if (!rewards || !discounts) {
+ return <div>Loading...</div>; // or some appropriate loading state
+ }🤖 Prompt for AI Agents
In apps/web/ui/partners/design/modals/earnings-calculator-block-modal.tsx around
lines 187 to 192, the loading states returned by useRewards and useDiscounts
hooks are not handled, which may cause rendering or calculation issues if data
is not ready. Update the code to check the loading states from both hooks before
rendering EarningsCalculatorBlock, and display a loading indicator or fallback
UI until the data is fully loaded. This ensures that rewards and discounts data
passed to EarningsCalculatorBlock are valid and complete.
| const { rewards } = useRewards(); | ||
| const { discounts } = useDiscounts(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Handle loading states for rewards and discounts data.
Similar to the modal component, the loading states from useRewards and useDiscounts are not being handled, which could lead to undefined data being passed to block components during initial load.
Consider handling loading states before rendering blocks:
const { rewards } = useRewards();
const { discounts } = useDiscounts();
+
+ if (!rewards || !discounts) {
+ // Return early or show loading state for the affected blocks
+ return <div>Loading preview...</div>;
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { rewards } = useRewards(); | |
| const { discounts } = useDiscounts(); | |
| const { rewards } = useRewards(); | |
| const { discounts } = useDiscounts(); | |
| if (!rewards || !discounts) { | |
| // Return early or show loading state for the affected blocks | |
| return <div>Loading preview...</div>; | |
| } |
🤖 Prompt for AI Agents
In apps/web/ui/partners/design/previews/lander-preview.tsx around lines 54 to
55, the loading states from useRewards and useDiscounts hooks are not handled,
which may cause undefined data issues. Update the code to check if rewards or
discounts are still loading before rendering the block components, and render a
loading indicator or return null until the data is ready to ensure safe data
usage.
|
@CodeRabbit final review |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chainI'll conduct a comprehensive final review of your PR. Let me examine the key files to understand the implementation details and identify any potential issues. 🏁 Script executed: Length of output: 26086 🏁 Script executed: Length of output: 56013 @steven-tey Here's my comprehensive final review of this PR. The refactoring looks solid overall, but I've identified several areas that could benefit from improvements: 🔍 Key Issues & Recommendations1. Error Handling & Edge CasesIssue: The earnings calculator can fail silently if reward data is malformed: const reward = rewards[0];
const rewardAmount = reward.amount ?? 0; // Could still be null in DBRecommendation: Add more robust validation: const reward = rewards[0];
if (!reward || typeof reward.amount !== 'number') {
console.warn('Invalid reward data in earnings calculator');
return null;
}2. Type Safety ConcernsIssue: The helper function accepts landerData: Prisma.JsonValue;Recommendation: Consider using a more specific type or adding runtime validation: landerData: Prisma.JsonValue | ProgramLanderData;3. Performance & Data ConsistencyIssue: Different components fetch rewards/discounts inconsistently:
Recommendation: Standardize data fetching approach and consider memoization for the helper function. 4. Calculation Logic RobustnessIssue: The earnings calculation could produce incorrect results: Math.floor(
reward.type === "flat"
? (value * rewardAmount) / 100
: revenue * (rewardAmount / 100),
)Concerns:
5. Complex Fallback LogicIssue: The helper function has intricate fallback logic that may be hard to maintain: const reward =
rewards.find((r) => r.id === landerReward && r.event === event) ||
defaultReward;Recommendation: Add comments explaining the business logic and consider breaking into smaller, more testable functions. ✅ What's Working Well
🧪 Suggested TestsConsider adding tests for these edge cases:
🔧 Minor Improvements
The refactoring achieves its goal of centralizing reward/discount logic, but addressing these points would make it more robust and maintainable. Would you like me to elaborate on any of these recommendations? |
Simplifies the program prop passed to block components by removing the spread of rewards and discount. The program object is now passed as-is.
Summary by CodeRabbit
New Features
Bug Fixes
Refactor