Add /links prefix to analytics, events, customers, Program Events page - #4101
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@coderabbitai full review |
✅ Action performedFull review finished. |
📝 WalkthroughWalkthroughAdds product-aware analytics routing, query construction, navigation, and events-page wiring, including a new program events page and updated links for the short-links and program dashboards. ChangesProduct-scoped routing and analytics
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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.
Actionable comments posted: 4
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/middleware/utils/app-redirect.ts (1)
27-40: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winRestore the
RESERVED_SLUGSguard here.
APP_REDIRECTSonly covers a few exceptions; the generic workspace redirect still matches every other single-segment reserved path and turns it into/<slug>/<product>viagetWorkspaceProduct, which falls back tolinksfor unknown slugs.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/lib/middleware/utils/app-redirect.ts` around lines 27 - 40, Restore the RESERVED_SLUGS guard in appRedirect so reserved single-segment paths do not fall through to the generic workspace redirect logic. Update appRedirect to check the slug before calling getWorkspaceProduct, and short-circuit for any reserved slug that is not explicitly handled by APP_REDIRECTS. Keep the fix local to appRedirect and use the existing RESERVED_SLUGS and getWorkspaceProduct symbols to place the guard in the current matching flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/app/app.dub.co/`(dashboard)/[slug]/(ee)/program/events/page.tsx:
- Around line 9-21: The page title is nesting a second heading because
PageContent already renders the title inside an h1. Update
ProgramEventsPageTitleLink so it returns plain text or a span-style breadcrumb
label instead of its own h1, and keep WorkspaceProgramEventsPage passing that
component into PageContent as the single page heading.
In `@apps/web/ui/analytics/use-analytics-query.tsx`:
- Around line 92-93: The query builder in useAnalyticsQuery is allowing
programId to be included even when defaultProgramId is undefined, which results
in a literal programId=undefined in the request. Update the object spread near
the URLSearchParams call so it only adds programId when both product ===
"program" and defaultProgramId is defined, using the existing
useCurrentProduct/defaultProgramId flow to guard the param before serialization.
In `@apps/web/ui/layout/sidebar/app-sidebar-nav.tsx`:
- Around line 335-341: The pathname checks in app-sidebar-nav are still using
the old analytics/events routes, so the queryString omission never triggers.
Update the ternary comparisons in the sidebar item definitions for Analytics and
Events to match the new /links/ paths used in their href values, keeping the
logic in the same sidebar nav builder where pathname and queryString are
assembled.
In `@packages/ui/src/hooks/use-current-product.ts`:
- Around line 1-18: The `useCurrentProduct` hook is leaving a stale product
value when `pathname` no longer points to a `/links/` or `/program/` route, so
update `useCurrentProduct` to always return `null` for non-matching paths
instead of preserving prior state. Replace the current `useEffect`/`useState`
approach with a synchronous computed value (for example via `useMemo`) based on
`usePathname`, and ensure the logic explicitly handles both `"links"` and
`"program"` while resetting everything else to `null` so consumers like
`useAnalyticsQuery`, `AnalyticsToggle`, and `program-analytics-shell.tsx` always
get the correct product.
---
Outside diff comments:
In `@apps/web/lib/middleware/utils/app-redirect.ts`:
- Around line 27-40: Restore the RESERVED_SLUGS guard in appRedirect so reserved
single-segment paths do not fall through to the generic workspace redirect
logic. Update appRedirect to check the slug before calling getWorkspaceProduct,
and short-circuit for any reserved slug that is not explicitly handled by
APP_REDIRECTS. Keep the fix local to appRedirect and use the existing
RESERVED_SLUGS and getWorkspaceProduct symbols to place the guard in the current
matching flow.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4cdc26de-d0c4-4282-812c-d065cc4c3efc
📒 Files selected for processing (19)
apps/web/app/(ee)/admin.dub.co/(dashboard)/events/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/[customerId]/earnings/page-client.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/[customerId]/earnings/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/[customerId]/layout.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/[customerId]/sales/page-client.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/[customerId]/sales/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/events/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/program-analytics-shell.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/events/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/events/title-link.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/links/analytics/client.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/links/analytics/page.tsxapps/web/lib/middleware/utils/app-redirect.tsapps/web/ui/analytics/toggle.tsxapps/web/ui/analytics/use-analytics-query.tsxapps/web/ui/layout/sidebar/app-sidebar-nav.tsxpackages/ui/src/hooks/index.tspackages/ui/src/hooks/use-current-product.ts
There was a problem hiding this comment.
♻️ Duplicate comments (2)
apps/web/ui/analytics/use-analytics-query.tsx (1)
92-98: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winUnresolved: guard against
programId: undefined.
defaultProgramIdmay still beundefinedwhile workspace data loads; the spread should also check for its presence to avoid serializingprogramId=undefinedinto the request.🐛 Proposed fix
- ...(product === "program" && { programId: defaultProgramId }), + ...(product === "program" && defaultProgramId && { programId: defaultProgramId }),🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/ui/analytics/use-analytics-query.tsx` around lines 92 - 98, The query builder in useAnalyticsQuery should not serialize programId when defaultProgramId is still undefined. Update the object spread that adds programId in the useMemo logic to also guard on defaultProgramId being present, using the existing product check in use-analytics-query.tsx so the request never includes programId=undefined while workspace data is loading.packages/ui/src/hooks/use-current-product.ts (1)
1-18: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winStale/delayed
productstate — unresolved from prior review.Same issue flagged previously: no
elsebranch resetsproducttonullwhen navigating to non-/links//programroutes, soproductretains a stale value. Additionally, usinguseEffect+useStateinstead of computing synchronously meansproductisnullon the very first render even when the pathname already matches/linksor/program(confirmedusePathnamereturns the current path synchronously on render), delaying correct behavior by one render cycle.This propagates downstream:
useAnalyticsQuery'sprogramIdinjection andprogram-analytics-shell.tsx's initialtotalEventsSWR fetch (which depends onqueryStringfromuseAnalyticsQuery) will run withoutprogramIdon first mount, andAnalyticsToggle's "View Events"/"View Analytics" links can point to the wrong product segment after navigating away from a/links/or/program/page.🐛 Proposed fix
-import { usePathname } from "next/navigation"; -import { useEffect, useState } from "react"; - -export function useCurrentProduct() { - const pathname = usePathname(); - const [product, setProduct] = useState<"links" | "program" | null>(null); - - useEffect(() => { - const productParam = pathname.split("/")[2]; - if (productParam === "links") { - setProduct("links"); - } else if (productParam === "program") { - setProduct("program"); - } - }, [pathname]); - - return { product }; -} +import { usePathname } from "next/navigation"; +import { useMemo } from "react"; + +export function useCurrentProduct() { + const pathname = usePathname(); + + const product = useMemo<"links" | "program" | null>(() => { + const productParam = pathname.split("/")[2]; + if (productParam === "links") return "links"; + if (productParam === "program") return "program"; + return null; + }, [pathname]); + + return { product }; +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ui/src/hooks/use-current-product.ts` around lines 1 - 18, The useCurrentProduct hook is leaving stale product state and delaying the correct value by one render because it relies on useEffect plus useState without resetting to null for non-matching routes. Update useCurrentProduct to derive product synchronously from usePathname on each render (or ensure the effect always sets null in the fallback case), so pathname values for /links and /program are reflected immediately and other routes clear the product state. Use the useCurrentProduct symbol to locate the hook and keep its return shape unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Duplicate comments:
In `@apps/web/ui/analytics/use-analytics-query.tsx`:
- Around line 92-98: The query builder in useAnalyticsQuery should not serialize
programId when defaultProgramId is still undefined. Update the object spread
that adds programId in the useMemo logic to also guard on defaultProgramId being
present, using the existing product check in use-analytics-query.tsx so the
request never includes programId=undefined while workspace data is loading.
In `@packages/ui/src/hooks/use-current-product.ts`:
- Around line 1-18: The useCurrentProduct hook is leaving stale product state
and delaying the correct value by one render because it relies on useEffect plus
useState without resetting to null for non-matching routes. Update
useCurrentProduct to derive product synchronously from usePathname on each
render (or ensure the effect always sets null in the fallback case), so pathname
values for /links and /program are reflected immediately and other routes clear
the product state. Use the useCurrentProduct symbol to locate the hook and keep
its return shape unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c4dffde5-eb88-4ade-abe0-5c1b4b774bb1
📒 Files selected for processing (21)
apps/web/app/(ee)/admin.dub.co/(dashboard)/events/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/[customerId]/earnings/page-client.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/[customerId]/earnings/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/[customerId]/layout.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/[customerId]/sales/page-client.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/[customerId]/sales/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/customers/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/links/events/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/program-analytics-shell.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/events/page.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/events/title-link.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/links/analytics/client.tsxapps/web/app/app.dub.co/(dashboard)/[slug]/links/analytics/page.tsxapps/web/lib/middleware/utils/app-redirect.tsapps/web/ui/analytics/events/events-table.tsxapps/web/ui/analytics/events/events-tabs.tsxapps/web/ui/analytics/toggle.tsxapps/web/ui/analytics/use-analytics-query.tsxapps/web/ui/layout/sidebar/app-sidebar-nav.tsxpackages/ui/src/hooks/index.tspackages/ui/src/hooks/use-current-product.ts
Summary by CodeRabbit
New Features
Bug Fixes