-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Fix getStartEndDates #3193
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
Fix getStartEndDates #3193
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughThis PR updates date handling across multiple files by switching from ISO string representations to native Date objects in database queries and enhances email formatting with dynamic pluralization in the payout notification system. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ 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)
🔇 Additional comments (2)
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. Comment |
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: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/lib/analytics/utils/get-start-end-dates.ts (1)
25-31: Critical bug:differenceInDaysarguments are in wrong order.
differenceInDays(startDate, endDate)returnsstartDate - endDate, which yields a negative value whenstartDate < endDate(the normal case). This breaks the granularity logic:
daysDifference <= 2will almost always be true (negatives are ≤ 2)daysDifference > 180will almost never be trueSwap the arguments to get the positive difference:
- const daysDifference = differenceInDays(startDate, endDate); + const daysDifference = differenceInDays(endDate, startDate);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/count/route.ts(1 hunks)apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/route.ts(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/page-client.tsx(1 hunks)apps/web/lib/analytics/utils/get-start-end-dates.ts(2 hunks)apps/web/lib/api/commissions/get-commissions-count.ts(1 hunks)apps/web/lib/api/commissions/get-commissions.ts(2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-17T17:44:03.965Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2857
File: apps/web/lib/actions/partners/update-program.ts:96-0
Timestamp: 2025-09-17T17:44:03.965Z
Learning: In apps/web/lib/actions/partners/update-program.ts, the team prefers to keep the messagingEnabledAt update logic simple by allowing client-provided timestamps rather than implementing server-controlled timestamp logic to avoid added complexity.
Applied to files:
apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/count/route.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/page-client.tsxapps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/route.ts
📚 Learning: 2025-10-31T19:45:25.702Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 3044
File: apps/web/lib/analytics/utils/get-interval-data.ts:31-0
Timestamp: 2025-10-31T19:45:25.702Z
Learning: In apps/web/lib/analytics/utils/get-interval-data.ts, the `mtd` and `qtd` interval functions are designed to work in both server and client contexts. When no timezone is provided, they intentionally fall back to `new Date()` (local timezone) because front-end code calls these methods without passing a timezone and should use the browser's local timezone for the user's context.
Applied to files:
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/page-client.tsxapps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/route.tsapps/web/lib/api/commissions/get-commissions-count.tsapps/web/lib/analytics/utils/get-start-end-dates.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/page-client.tsx
⏰ 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 (6)
apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/count/route.ts (1)
48-51: LGTM!Passing
Dateobjects directly to Prisma'sDateTimefields is valid and cleaner than converting to ISO strings. This aligns with the broader refactoring across the codebase.apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/route.ts (1)
60-63: LGTM!Consistent with the pattern used in the count route. Prisma natively handles
Dateobjects forDateTimefields.apps/web/lib/api/commissions/get-commissions-count.ts (1)
53-56: LGTM!Consistent date handling refactor using
Dateobjects directly.apps/web/lib/api/commissions/get-commissions.ts (1)
50-56: LGTM on date handling; verify the new default status filter is intentional.The
Dateobject usage is consistent with the rest of the PR. However, lines 50-56 introduce a new default behavior that excludesduplicate,fraud, andcanceledstatuses when no status filter is provided. This matchesget-commissions-count.ts, so it appears intentional—just confirming this behavioral change is expected as part of this fix.Also applies to: 60-63
apps/web/lib/analytics/utils/get-start-end-dates.ts (1)
23-23: Good fix: UsingendOfDayensures the entire end date is included.This correctly sets the end boundary to 23:59:59.999 of the specified day, ensuring queries include all records from that day.
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/page-client.tsx (1)
47-53: Preservingstart/endsearch params (no extra ISO conversion) looks correctSwitching from
new Date(start/end).toISOString()to spreading the raw{ start, end }keeps the query aligned with whatever canonical date stringsgetStartEndDates/ router logic already produce, and avoids an extra parse/serialize step that could introduce timezone drift. Behavior of only including bothstartandendwhen both are present is preserved, and the downstreamAnalyticsContextstill gets parseable values vianew Date(start/end).This is consistent with the broader PR goal of centralizing Date construction in shared utilities and letting the API handle the date math.
Based on learnings, this also keeps the “browser local timezone + explicit timezone param” pattern intact.
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
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: 3
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
apps/web/lib/analytics/format-date-tooltip.ts(2 hunks)apps/web/lib/analytics/utils/valid-date-range-for-plan.ts(3 hunks)packages/utils/src/functions/datetime/get-days-difference.ts(0 hunks)packages/utils/src/functions/datetime/index.ts(0 hunks)
💤 Files with no reviewable changes (2)
- packages/utils/src/functions/datetime/index.ts
- packages/utils/src/functions/datetime/get-days-difference.ts
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-31T19:45:25.702Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 3044
File: apps/web/lib/analytics/utils/get-interval-data.ts:31-0
Timestamp: 2025-10-31T19:45:25.702Z
Learning: In apps/web/lib/analytics/utils/get-interval-data.ts, the `mtd` and `qtd` interval functions are designed to work in both server and client contexts. When no timezone is provided, they intentionally fall back to `new Date()` (local timezone) because front-end code calls these methods without passing a timezone and should use the browser's local timezone for the user's context.
Applied to files:
apps/web/lib/analytics/format-date-tooltip.tsapps/web/lib/analytics/utils/valid-date-range-for-plan.ts
⏰ 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
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: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/web/lib/analytics/utils/get-start-end-dates.ts (1)
1-26: Normalizeendto a Date before callingendOfDayto fix a TypeScript type error.
endis typed asstring | Date | null, butendOfDayfromdate-fnshas the signatureendOfDay(date: Date | number): Date. The expressionendOfDay(end ?? Date.now())has typestring | Date | numberat compile time, which does not match the expectedDate | numberparameter type.You can keep the same semantics and fix the typing by normalizing
endbefore passing it:if (start || (interval === "all" && dataAvailableFrom)) { - startDate = new Date(start ?? dataAvailableFrom ?? Date.now()); - endDate = new Date(endOfDay(end ?? Date.now())); - - const daysDifference = differenceInDays(startDate, endDate); + const startInput = start ?? dataAvailableFrom ?? Date.now(); + startDate = new Date(startInput); + + const endInput = end ? new Date(end) : new Date(); + endDate = endOfDay(endInput); + + const daysDifference = differenceInDays(startDate, endDate);This preserves the intended behavior (inclusive end-of-day semantics) while satisfying the date-fns type signature.
♻️ Duplicate comments (2)
apps/web/lib/analytics/format-date-tooltip.ts (1)
30-33: differenceInDays arguments are reversed, inverting the day-range logic.
differenceInDays(later, earlier)returns a positive count; passing(start, end)(wherestartis usually earlier thanend) yields negative values and breaks the<= 2/> 180checks, causing wrong tooltip formatting for most ranges. Swap the arguments soend(typically “now” or the upper bound) is first.Suggested fix:
- const daysDifference = differenceInDays( - typeof start === "string" ? new Date(start) : start, - typeof end === "string" ? new Date(end) : end, - ); + const daysDifference = differenceInDays( + typeof end === "string" ? new Date(end) : end, + typeof start === "string" ? new Date(start) : start, + );To double‑check, please verify against the date-fns docs for
differenceInDays(that the first argument is treated as the later date) before merging.apps/web/lib/analytics/utils/valid-date-range-for-plan.ts (1)
35-36:differenceInDaysarguments reversed; free/pro limits never trigger.
differenceInDays(start, end || now)yields a negative value for normal ranges wherestart < end, so the> 31(free) and> 366(pro) checks are effectively disabled. You needend || nowas the first argument andstartas the second.Apply this diff:
- (start && differenceInDays(start, end || now) > 31)) + (start && differenceInDays(end || now, start) > 31)) @@ - if (plan === "pro" && start && differenceInDays(start, end || now) > 366) { + if (plan === "pro" && start && differenceInDays(end || now, start) > 366) {Also applies to: 46-46
🧹 Nitpick comments (1)
apps/web/lib/api/commissions/get-commissions.ts (1)
4-63: CommissionStatus import + default status filter + Date bounds all look consistent.
- Importing
CommissionStatusfrom@dub/prisma/clientlines up withget-commissions-count.tsand the shared Prisma client.- The
status: status ?? { notIn: [duplicate, fraud, canceled] }default on the non‑invoice path is a sensible guard so “no filter” excludes obviously invalid states, while still respecting explicitstatusfilters.- Moving
createdAttogte: startDate/lte: endDatematches the rest of the PR and Prisma’s natural usage ofDatevalues.Assuming callers rely on this function for user-facing commission lists (and not for low-level auditing), this behavior shift looks intentional and correct.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/count/route.ts(1 hunks)apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/route.ts(1 hunks)apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/page-client.tsx(1 hunks)apps/web/lib/analytics/format-date-tooltip.ts(2 hunks)apps/web/lib/analytics/utils/get-start-end-dates.ts(2 hunks)apps/web/lib/analytics/utils/valid-date-range-for-plan.ts(3 hunks)apps/web/lib/api/commissions/get-commissions-count.ts(1 hunks)apps/web/lib/api/commissions/get-commissions.ts(2 hunks)packages/utils/src/functions/datetime/get-days-difference.ts(0 hunks)packages/utils/src/functions/datetime/index.ts(0 hunks)
💤 Files with no reviewable changes (2)
- packages/utils/src/functions/datetime/get-days-difference.ts
- packages/utils/src/functions/datetime/index.ts
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-09-17T17:44:03.965Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2857
File: apps/web/lib/actions/partners/update-program.ts:96-0
Timestamp: 2025-09-17T17:44:03.965Z
Learning: In apps/web/lib/actions/partners/update-program.ts, the team prefers to keep the messagingEnabledAt update logic simple by allowing client-provided timestamps rather than implementing server-controlled timestamp logic to avoid added complexity.
Applied to files:
apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/route.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/page-client.tsxapps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/count/route.ts
📚 Learning: 2025-10-31T19:45:25.702Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 3044
File: apps/web/lib/analytics/utils/get-interval-data.ts:31-0
Timestamp: 2025-10-31T19:45:25.702Z
Learning: In apps/web/lib/analytics/utils/get-interval-data.ts, the `mtd` and `qtd` interval functions are designed to work in both server and client contexts. When no timezone is provided, they intentionally fall back to `new Date()` (local timezone) because front-end code calls these methods without passing a timezone and should use the browser's local timezone for the user's context.
Applied to files:
apps/web/lib/analytics/format-date-tooltip.tsapps/web/lib/analytics/utils/get-start-end-dates.tsapps/web/lib/analytics/utils/valid-date-range-for-plan.ts
📚 Learning: 2025-07-09T20:52:56.592Z
Learnt from: TWilson023
Repo: dubinc/dub PR: 2614
File: apps/web/ui/partners/design/previews/lander-preview.tsx:181-181
Timestamp: 2025-07-09T20:52:56.592Z
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.
Applied to files:
apps/web/lib/analytics/format-date-tooltip.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/lib/api/commissions/get-commissions.tsapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/page-client.tsx
🧬 Code graph analysis (1)
apps/web/lib/api/commissions/get-commissions.ts (1)
packages/prisma/client.ts (1)
CommissionStatus(10-10)
🔇 Additional comments (5)
apps/web/lib/analytics/utils/valid-date-range-for-plan.ts (1)
1-1: date-fns import usage looks correct.
differenceInDaysis imported from the canonicaldate-fnsentrypoint and is used below for plan window checks; no issues here.apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/page-client.tsx (1)
47-53: Passing raw start/end query params looks correct, assuming the picker always sets both.Including
start/enddirectly fromsearchParamsObjwhen both exist avoids double serialization and keeps the API aligned with the newgetStartEndDatesbehavior. This does change behavior slightly if only one ofstart/endcould be set, but withSimpleDateRangePickertypically providing both, that seems acceptable.apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/route.ts (1)
48-63: Using Date objects for createdAt bounds matches Prisma expectations.Switching
createdAtto usegte: startDate/lte: endDatedirectly is consistent with the updatedgetStartEndDatesbehavior and with other endpoints in this PR; Prisma will serialize the Dates correctly.apps/web/lib/api/commissions/get-commissions-count.ts (1)
35-56: Consistent Date-based createdAt filtering.Using
gte: startDate/lte: endDatein thecreatedAtfilter keeps commissions count aligned with the other updated routes and avoids unnecessary ISO string conversion.apps/web/app/(ee)/api/partner-profile/programs/[programId]/earnings/count/route.ts (1)
41-51: Date object bounds for createdAt are consistent with the rest of the API.The change to use
startDate/endDatedirectly in thecreatedAtfilter brings this endpoint in line with the other earnings/commissions queries and with the updatedgetStartEndDatesbehavior.
Summary by CodeRabbit
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.