-
Notifications
You must be signed in to change notification settings - Fork 636
[PRO-138] Dashboard: Update Project highlights card revenue tab #8515
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 GitHub.
|
|
WalkthroughAdds x402 settlement revenue into project highlights (fetch, propagate, and aggregate), enables stacked chart bars with per-key stackedKeys and hideAsTab options, refactors X402 settlement types to extend a common overall interface, tightens USD formatting precision, and makes an empty-chart CTA link optional. Changes
Sequence Diagram(s)sequenceDiagram
participant Wrapper as AsyncAppHighlightsCard
participant API as Analytics API
participant Card as ProjectHighlightsCard
participant Processor as TimeSeriesProcessor
participant Charts as BarChart / UI
Wrapper->>API: getX402Settlements()
API-->>Wrapper: x402Settlements[]
Wrapper->>API: getAggregatedUserStats()
API-->>Wrapper: InAppWalletStats[]
Wrapper->>API: getUniversalBridgeStats()
API-->>Wrapper: UniversalBridgeStats[]
Wrapper->>Card: render(x402Settlements, userStats, volumeStats)
Card->>Processor: processTimeSeriesData(userStats, volumeStats, x402Settlements)
Processor->>Processor: normalize dates, compute bridgeRevenue & x402Revenue, aggregate metrics
Processor-->>Card: TimeSeriesMetrics[]
Card->>Charts: render(timeSeriesData, chartConfig with stackedKeys)
Charts-->>Card: stacked / single-bar visuals
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Pre-merge checks and finishing touches❌ Failed checks (3 warnings)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
Comment |
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8515 +/- ##
=======================================
Coverage 54.65% 54.65%
=======================================
Files 920 920
Lines 61114 61114
Branches 4141 4141
=======================================
Hits 33399 33399
Misses 27613 27613
Partials 102 102
🚀 New features to boost your workflow:
|
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
🧹 Nitpick comments (4)
apps/dashboard/src/@/types/analytics.ts (1)
120-126: Consider extendingX402SettlementsOverallfor consistency.
X402SettlementsByAssetduplicates the same fields (date,totalRequests,totalValue,totalValueUSD) instead of extendingX402SettlementsOveralllike the other settlement types. This could lead to drift if the base type changes.-interface X402SettlementsByAsset { - date: string; +interface X402SettlementsByAsset extends X402SettlementsOverall { asset: string; - totalRequests: number; - totalValue: number; - totalValueUSD: number; }apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsx (1)
97-122: Minor: Redundant ternary checks after status verification.Lines 108-111 contain a ternary check for
walletUserStatsTimeSeries.status === "fulfilled", but this is already guaranteed by the outerifcondition on line 98. The same applies touniversalBridgeUsageon lines 113-117.<ProjectHighlightsCard aggregatedUserStats={ aggregatedUserStats.status === "fulfilled" ? aggregatedUserStats.value : [] } - userStats={ - walletUserStatsTimeSeries.status === "fulfilled" - ? walletUserStatsTimeSeries.value - : [] - } - volumeStats={ - universalBridgeUsage.status === "fulfilled" - ? universalBridgeUsage.value - : [] - } + userStats={walletUserStatsTimeSeries.value} + volumeStats={universalBridgeUsage.value} x402Settlements={ x402Settlements.status === "fulfilled" ? x402Settlements.value : [] } />apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx (1)
103-158: Good story coverage.The three stories provide useful scenarios: full 30-day data, single-day revenue, and no x402 settlements. Consider adding an edge case with empty
bridgeVolumeStatsbut populatedx402Settlementsto verify x402-only revenue display.export function SingleDayRevenueX402Only() { const days = 1; const data = { aggregatedUserStats: [], userStats: [], bridgeVolumeStats: [], x402Settlements: generateX402Settlements(days), }; return ( <ProjectHighlightsCard aggregatedUserStats={data.aggregatedUserStats} userStats={data.userStats} volumeStats={data.bridgeVolumeStats} x402Settlements={data.x402Settlements} /> ); }apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsx (1)
98-102: Redundant field declarations inTimeSeriesMetrics.
TimeSeriesMetricsextendsAggregatedMetricswhich already includesbridgeRevenueandx402Revenue. Re-declaring them here is unnecessary.type TimeSeriesMetrics = AggregatedMetrics & { date: string; - bridgeRevenue: number; - x402Revenue: number; };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
apps/dashboard/src/@/components/analytics/empty-chart-state.tsx(2 hunks)apps/dashboard/src/@/types/analytics.ts(1 hunks)apps/dashboard/src/@/utils/number.ts(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsx(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsx(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/types.ts(0 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx(0 hunks)apps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsx(4 hunks)apps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx(2 hunks)
💤 Files with no reviewable changes (2)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/types.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each TypeScript file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes in TypeScript
Avoidanyandunknownin TypeScript unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.) in TypeScript
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity and testability
Re-use shared types from @/types or local types.ts barrel exports
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics whenever possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic in TypeScript files; avoid restating TypeScript types and signatures in prose
Files:
apps/dashboard/src/@/components/analytics/empty-chart-state.tsxapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/@/types/analytics.ts
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}: Import UI component primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground
Use Tailwind CSS only – no inline styles or CSS modules in dashboard and playground
Usecn()from@/lib/utilsfor conditional Tailwind class merging
Use design system tokens for styling (backgrounds:bg-card, borders:border-border, muted text:text-muted-foreground)
ExposeclassNameprop on root element for component overrides
Files:
apps/dashboard/src/@/components/analytics/empty-chart-state.tsxapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/@/types/analytics.ts
apps/dashboard/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/dashboard/src/**/*.{ts,tsx}: UseNavLinkfor internal navigation with automatic active states in dashboard
Start server component files withimport "server-only";in Next.js
Read cookies/headers withnext/headersin server components
Access server-only environment variables in server components
Perform heavy data fetching in server components
Implement redirect logic withredirect()fromnext/navigationin server components
Begin client component files with'use client';directive in Next.js
Handle interactive UI with React hooks (useState,useEffect, React Query, wallet hooks) in client components
Access browser APIs (localStorage,window,IntersectionObserver) in client components
Support fast transitions with prefetched data in client components
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader for API calls – never embed tokens in URLs
Return typed results (Project[],User[]) from server-side data fetches – avoidany
Wrap client-side API calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysin React Query for cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components – only use analytics client-side
Files:
apps/dashboard/src/@/components/analytics/empty-chart-state.tsxapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/@/types/analytics.ts
apps/dashboard/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/*.{ts,tsx}: Always import from the central UI library under@/components/ui/*for reusable core UI components likeButton,Input,Select,Tabs,Card,Sidebar,Separator,Badge
UseNavLinkfrom@/components/ui/NavLinkfor internal navigation to ensure active states are handled automatically
For notices and skeletons, rely onAnnouncementBanner,GenericLoadingPage, andEmptyStateCardcomponents
Import icons fromlucide-reactor the project-specific…/iconsexports; never embed raw SVG
Keep components pure; fetch data outside using server components or hooks and pass it down via props
Use Tailwind CSS as the styling system; avoid inline styles or CSS modules
Merge class names withcnfrom@/lib/utilsto keep conditional logic readable
Stick to design tokens: usebg-card,border-border,text-muted-foregroundand other Tailwind variables instead of hard-coded colors
Use spacing utilities (px-*,py-*,gap-*) instead of custom margins
Follow mobile-first responsive design with Tailwind helpers (max-sm,md,lg,xl)
Never hard-code colors; always use Tailwind variables
Combine class names viacn, and exposeclassNameprop if useful in components
Use React Query (@tanstack/react-query) for all client-side data fetching with typed hooks
Files:
apps/dashboard/src/@/components/analytics/empty-chart-state.tsxapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/@/types/analytics.ts
apps/dashboard/**/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
Add
classNameprop to the root element of every component to allow external overrides
Files:
apps/dashboard/src/@/components/analytics/empty-chart-state.tsxapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx
**/*.{js,jsx,ts,tsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Biome governs formatting and linting; its rules live in biome.json. Run
pnpm fix&pnpm lintbefore committing, ensure there are no linting errors
Files:
apps/dashboard/src/@/components/analytics/empty-chart-state.tsxapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/@/types/analytics.ts
apps/{dashboard,playground}/**/*.{tsx,ts}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{tsx,ts}: Import UI primitives from @/components/ui/_ (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in Dashboard and Playground apps
Use NavLink for internal navigation so active states are handled automatically
Use Tailwind CSS for styling – no inline styles or CSS modules
Merge class names with cn() from @/lib/utils to keep conditional logic readable
Stick to design tokens for styling: backgrounds (bg-card), borders (border-border), muted text (text-muted-foreground), etc.
Server Components: Read cookies/headers with next/headers, access server-only environment variables or secrets, perform heavy data fetching, implement redirect logic with redirect() from next/navigation, and start files with import 'server-only'; to prevent client bundling
Client Components: Begin files with 'use client'; before imports, handle interactive UI relying on React hooks (useState, useEffect, React Query, wallet hooks), access browser APIs (localStorage, window, IntersectionObserver, etc.), and support fast transitions with client-side data prefetching
For client-side data fetching: Wrap calls in React Query (@tanstack/react-query), use descriptive and stable queryKeys for cache hits, configure staleTime / cacheTime based on freshness requirements (default ≥ 60 s), and keep tokens secret by calling internal API routes or server actions
Files:
apps/dashboard/src/@/components/analytics/empty-chart-state.tsxapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/@/types/analytics.ts
apps/{dashboard,playground}/**/components/**/*.{tsx,ts}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/components/**/*.{tsx,ts}: Group feature-specific components under feature/components/_ and expose a barrel index.ts when necessary
Expose a className prop on the root element of every component for styling overrides
Files:
apps/dashboard/src/@/components/analytics/empty-chart-state.tsxapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx
apps/{dashboard,playground}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{ts,tsx}: For server-side data fetching: Always call getAuthToken() to retrieve the JWT from cookies and inject the token as an Authorization: Bearer header – never embed it in the URL. Return typed results (Project[], User[], …) – avoid any
Never import posthog-js in server components; analytics reporting is client-side only
Files:
apps/dashboard/src/@/components/analytics/empty-chart-state.tsxapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/@/types/analytics.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Lazy-import optional features; avoid top-level side-effects
Files:
apps/dashboard/src/@/components/analytics/empty-chart-state.tsxapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/@/types/analytics.ts
**/*.stories.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Add Storybook stories (
*.stories.tsx) alongside new UI components for documentation
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx
**/*.stories.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
For new UI components, add Storybook stories (*.stories.tsx) alongside the code
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx
apps/dashboard/**/*analytics*
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
Use human-readable event names in
<subject> <verb>phrase format (e.g.,"contract deployed")
Files:
apps/dashboard/src/@/types/analytics.ts
🧬 Code graph analysis (5)
apps/dashboard/src/@/components/analytics/empty-chart-state.tsx (1)
packages/thirdweb/src/react/web/ui/components/text.tsx (1)
Link(46-64)
apps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx (2)
apps/dashboard/src/app/(app)/team/components/Analytics/Stat.tsx (1)
Stat(3-32)apps/dashboard/src/@/utils/number.ts (1)
toUSD(10-12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsx (1)
ProjectHighlightsCard(22-96)apps/dashboard/src/@/types/analytics.ts (3)
InAppWalletStats(14-19)UniversalBridgeStats(42-50)X402SettlementsOverall(97-102)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsx (1)
apps/dashboard/src/@/api/analytics.ts (3)
getInAppWalletUsage(303-308)getUniversalBridgeUsage(740-745)getX402Settlements(1040-1042)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsx (2)
apps/dashboard/src/@/types/analytics.ts (3)
InAppWalletStats(14-19)UniversalBridgeStats(42-50)X402SettlementsOverall(97-102)apps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx (1)
CombinedBarChartConfig(7-16)
⏰ 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). (4)
- GitHub Check: Vercel Agent Review
- GitHub Check: Size
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (12)
apps/dashboard/src/@/utils/number.ts (1)
1-8: LGTM!Reducing
maximumFractionDigitsfrom 6 to 2 is appropriate for compact USD currency display. This improves readability for revenue metrics (e.g.,$1.5Kvs$1.500000K).apps/dashboard/src/@/components/analytics/empty-chart-state.tsx (1)
38-73: LGTM!Making the
linkprop optional with conditional rendering is a clean approach that allows the CTA to be used in contexts where no navigation action is needed, while maintaining type safety.apps/dashboard/src/@/types/analytics.ts (1)
104-118: Good use of inheritance for shared fields.Extending
X402SettlementsOverallfor the settlement subtypes reduces duplication and improves maintainability.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsx (1)
49-95: LGTM!Good use of
Promise.allSettledto fetch x402 settlements alongside existing data sources, allowing graceful degradation if the x402 API fails.apps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsx (2)
28-48: LGTM!Good implementation of stacking support. The
isEmptycheck correctly handles both stacked and non-stacked data by verifying if all stacked keys are zero whenstackedKeysis present.
104-128: LGTM!Clean conditional rendering for stacked vs. single bars. The color fallback chain (per-key → activeKey → default) and consistent
stackIdassignment ensure proper stacking behavior.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx (1)
10-27: LGTM!Good Storybook setup with appropriate decorator for responsive search params context. As per coding guidelines, adding stories alongside new UI components is the right approach.
apps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx (2)
7-16: LGTM!Good addition of
hideAsTabandstackedKeysto the config type. ExportingCombinedBarChartConfigenables type-safe configuration in consuming components.
59-86: LGTM!Clean implementation of tab filtering with
hideAsTab. This allows metrics likebridgeRevenueandx402Revenueto be hidden as individual tabs while still contributing to the stacked "Revenue" visualization.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsx (3)
31-39: LGTM!Moving to local
useStatefor chart selection simplifies the component. The x402Settlements integration follows the same pattern as other data sources.
87-93: Verify trend calculation logic.The
trendFncomparesdata[data.length - 2](second-to-last) againstdata[0](first). This calculates the overall trend from start to near-end, not period-over-period change. If period-over-period is intended:trendFn={(data, key) => data.filter((d) => (d[key] as number) > 0).length >= 2 - ? ((data[data.length - 2]?.[key] as number) ?? 0) / - ((data[0]?.[key] as number) ?? 0) - + ? ((data[data.length - 1]?.[key] as number) ?? 0) / + ((data[data.length - 2]?.[key] as number) ?? 0) - 1 : undefined }
155-157: LGTM!
ignoreTimePeriodcorrectly normalizes ISO timestamps toYYYY-MM-DDformat for consistent date matching across datasets with different time components.
size-limit report 📦
|
Merge activity
|
<!--
## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"
If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):
## Notes for the reviewer
Anything important to call out? Be sure to also clarify these in your comments.
## How to test
Unit tests, playground, etc.
-->
<!-- start pr-codex -->
---
## PR-Codex overview
This PR focuses on enhancing the analytics components by adding new functionalities and refining existing code for better performance and readability. It introduces new data handling for `x402Settlements`, updates chart configurations, and improves conditional rendering in various components.
### Detailed summary
- Added `x402Settlements` data handling in `AsyncAppHighlightsCard`.
- Updated `CombinedBarChartConfig` to include `stackedKeys`.
- Improved conditional rendering for the `EmptyChartStateGetStartedCTA`.
- Refined the `BarChart` component for better data processing.
- Enhanced `ProjectHighlightsCard` to include `bridgeRevenue` and `x402Revenue`.
- Introduced utility functions for generating mock data in stories.
- Updated types in various components for better type safety.
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
* **New Features**
* Added stacked data visualization support to charts.
* Integrated x402 revenue tracking into analytics highlights.
* Added ability to hide specific chart tabs from display.
* **Improvements**
* Refined USD currency formatting to display 2 decimal places for cleaner presentation.
* Made analytics CTA buttons conditionally displayed based on configuration.
* **Refactor**
* Simplified settlement data model with inheritance to reduce redundancy.
<sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
6ff4367 to
9856ee4
Compare
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
🧹 Nitpick comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsx (1)
155-157: Consider adding JSDoc for clarity.The
ignoreTimePeriodhelper is clear but undocumented. Adding a brief JSDoc comment would explain the UTC normalization behavior.+/** + * Normalizes a date string to YYYY-MM-DD format in UTC. + * Used to aggregate metrics by calendar day regardless of time. + */ function ignoreTimePeriod(date: string) { return new Date(date).toISOString().slice(0, 10); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
apps/dashboard/src/@/components/analytics/empty-chart-state.tsx(2 hunks)apps/dashboard/src/@/types/analytics.ts(1 hunks)apps/dashboard/src/@/utils/number.ts(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx(1 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsx(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsx(4 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/types.ts(0 hunks)apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx(0 hunks)apps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsx(4 hunks)apps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx(2 hunks)
💤 Files with no reviewable changes (2)
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/types.ts
- apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/project-wallet/project-wallet-details.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/dashboard/src/@/components/analytics/empty-chart-state.tsx
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each TypeScript file to one stateless, single-responsibility function for clarity
Re-use shared types from@/typesor localtypes.tsbarrels
Prefer type aliases over interface except for nominal shapes in TypeScript
Avoidanyandunknownin TypeScript unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial,Pick, etc.) in TypeScript
**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity and testability
Re-use shared types from @/types or local types.ts barrel exports
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics whenever possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic in TypeScript files; avoid restating TypeScript types and signatures in prose
Files:
apps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/@/types/analytics.ts
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/src/**/*.{ts,tsx}: Import UI component primitives from@/components/ui/*(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground
Use Tailwind CSS only – no inline styles or CSS modules in dashboard and playground
Usecn()from@/lib/utilsfor conditional Tailwind class merging
Use design system tokens for styling (backgrounds:bg-card, borders:border-border, muted text:text-muted-foreground)
ExposeclassNameprop on root element for component overrides
Files:
apps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/@/types/analytics.ts
apps/dashboard/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/dashboard/src/**/*.{ts,tsx}: UseNavLinkfor internal navigation with automatic active states in dashboard
Start server component files withimport "server-only";in Next.js
Read cookies/headers withnext/headersin server components
Access server-only environment variables in server components
Perform heavy data fetching in server components
Implement redirect logic withredirect()fromnext/navigationin server components
Begin client component files with'use client';directive in Next.js
Handle interactive UI with React hooks (useState,useEffect, React Query, wallet hooks) in client components
Access browser APIs (localStorage,window,IntersectionObserver) in client components
Support fast transitions with prefetched data in client components
Always callgetAuthToken()to retrieve JWT from cookies on server side
UseAuthorization: Bearerheader for API calls – never embed tokens in URLs
Return typed results (Project[],User[]) from server-side data fetches – avoidany
Wrap client-side API calls in React Query (@tanstack/react-query)
Use descriptive, stablequeryKeysin React Query for cache hits
ConfigurestaleTime/cacheTimein React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-jsin server components – only use analytics client-side
Files:
apps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/@/types/analytics.ts
apps/dashboard/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
apps/dashboard/**/*.{ts,tsx}: Always import from the central UI library under@/components/ui/*for reusable core UI components likeButton,Input,Select,Tabs,Card,Sidebar,Separator,Badge
UseNavLinkfrom@/components/ui/NavLinkfor internal navigation to ensure active states are handled automatically
For notices and skeletons, rely onAnnouncementBanner,GenericLoadingPage, andEmptyStateCardcomponents
Import icons fromlucide-reactor the project-specific…/iconsexports; never embed raw SVG
Keep components pure; fetch data outside using server components or hooks and pass it down via props
Use Tailwind CSS as the styling system; avoid inline styles or CSS modules
Merge class names withcnfrom@/lib/utilsto keep conditional logic readable
Stick to design tokens: usebg-card,border-border,text-muted-foregroundand other Tailwind variables instead of hard-coded colors
Use spacing utilities (px-*,py-*,gap-*) instead of custom margins
Follow mobile-first responsive design with Tailwind helpers (max-sm,md,lg,xl)
Never hard-code colors; always use Tailwind variables
Combine class names viacn, and exposeclassNameprop if useful in components
Use React Query (@tanstack/react-query) for all client-side data fetching with typed hooks
Files:
apps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/@/types/analytics.ts
**/*.{js,jsx,ts,tsx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Biome governs formatting and linting; its rules live in biome.json. Run
pnpm fix&pnpm lintbefore committing, ensure there are no linting errors
Files:
apps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/@/types/analytics.ts
apps/{dashboard,playground}/**/*.{tsx,ts}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{tsx,ts}: Import UI primitives from @/components/ui/_ (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in Dashboard and Playground apps
Use NavLink for internal navigation so active states are handled automatically
Use Tailwind CSS for styling – no inline styles or CSS modules
Merge class names with cn() from @/lib/utils to keep conditional logic readable
Stick to design tokens for styling: backgrounds (bg-card), borders (border-border), muted text (text-muted-foreground), etc.
Server Components: Read cookies/headers with next/headers, access server-only environment variables or secrets, perform heavy data fetching, implement redirect logic with redirect() from next/navigation, and start files with import 'server-only'; to prevent client bundling
Client Components: Begin files with 'use client'; before imports, handle interactive UI relying on React hooks (useState, useEffect, React Query, wallet hooks), access browser APIs (localStorage, window, IntersectionObserver, etc.), and support fast transitions with client-side data prefetching
For client-side data fetching: Wrap calls in React Query (@tanstack/react-query), use descriptive and stable queryKeys for cache hits, configure staleTime / cacheTime based on freshness requirements (default ≥ 60 s), and keep tokens secret by calling internal API routes or server actions
Files:
apps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/@/types/analytics.ts
apps/{dashboard,playground}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/*.{ts,tsx}: For server-side data fetching: Always call getAuthToken() to retrieve the JWT from cookies and inject the token as an Authorization: Bearer header – never embed it in the URL. Return typed results (Project[], User[], …) – avoid any
Never import posthog-js in server components; analytics reporting is client-side only
Files:
apps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/@/types/analytics.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Lazy-import optional features; avoid top-level side-effects
Files:
apps/dashboard/src/@/utils/number.tsapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsxapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsxapps/dashboard/src/@/types/analytics.ts
apps/dashboard/**/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
Add
classNameprop to the root element of every component to allow external overrides
Files:
apps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx
apps/{dashboard,playground}/**/components/**/*.{tsx,ts}
📄 CodeRabbit inference engine (AGENTS.md)
apps/{dashboard,playground}/**/components/**/*.{tsx,ts}: Group feature-specific components under feature/components/_ and expose a barrel index.ts when necessary
Expose a className prop on the root element of every component for styling overrides
Files:
apps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsxapps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx
**/*.stories.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Add Storybook stories (
*.stories.tsx) alongside new UI components for documentation
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx
**/*.stories.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
For new UI components, add Storybook stories (*.stories.tsx) alongside the code
Files:
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx
apps/dashboard/**/*analytics*
📄 CodeRabbit inference engine (.cursor/rules/dashboard.mdc)
Use human-readable event names in
<subject> <verb>phrase format (e.g.,"contract deployed")
Files:
apps/dashboard/src/@/types/analytics.ts
🧬 Code graph analysis (3)
apps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx (2)
apps/dashboard/src/app/(app)/team/components/Analytics/Stat.tsx (1)
Stat(3-32)apps/dashboard/src/@/utils/number.ts (1)
toUSD(10-12)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsx (1)
apps/dashboard/src/@/api/analytics.ts (3)
getInAppWalletUsage(303-308)getUniversalBridgeUsage(740-745)getX402Settlements(1040-1042)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx (2)
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsx (1)
ProjectHighlightsCard(22-96)apps/dashboard/src/@/types/analytics.ts (3)
InAppWalletStats(14-19)UniversalBridgeStats(42-50)X402SettlementsOverall(97-102)
⏰ 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). (7)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Lint Packages
- GitHub Check: Vercel Agent Review
- GitHub Check: Analyze (javascript)
🔇 Additional comments (17)
apps/dashboard/src/@/utils/number.ts (1)
1-8: LGTM!Reducing
maximumFractionDigitsfrom 6 to 2 aligns with standard USD display conventions where cents-level precision is sufficient for user-facing currency values.apps/dashboard/src/app/(app)/team/components/Analytics/CombinedBarChartCard.tsx (2)
7-16: LGTM!Good type extension with
hideAsTabandstackedKeysoptional properties. Exporting the type enables reuse across analytics components.
59-86: Tab filtering and rendering logic looks correct.The filtering with
hideAsTaband the visual indicator for active state are well-implemented. One minor note: on line 73,trendFn(data, key) || undefinedconverts0toundefined, but sinceStatalready guards with{trend && ...}, this is effectively correct behavior (zero trends aren't displayed).apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card.tsx (3)
4-8: LGTM!Clean import addition for
getX402Settlementsalongside existing analytics API functions.
49-95: LGTM! Good use of Promise.allSettled for independent data fetching.The parallel fetching of all four data sources with
Promise.allSettledis appropriate for independent API calls, allowing graceful degradation if individual sources fail.
97-122: Verify intentional exclusion of x402Settlements from render condition.The render condition on lines 97-99 only checks
walletUserStatsTimeSeriesanduniversalBridgeUsagefulfilled status, notx402Settlements. This means the card renders even if x402 fetching fails (passing an empty array). If this graceful degradation is intentional, this is fine. Otherwise, consider whether x402 failures should also show the empty state.apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.stories.tsx (3)
10-29: LGTM!Good Storybook meta configuration with proper decorators for
ResponsiveSearchParamsProviderand container styling. Thenextjs.appDirectoryparameter is correctly set for Next.js app router support.
31-101: Well-structured mock data generators.The helper functions create realistic mock data matching the expected type interfaces (
InAppWalletStats,UniversalBridgeStats,X402SettlementsOverall). ThegenerateDateSeriesproduces proper ISO date strings, andrandomValueensures non-negative values withMath.max(0, ...).
103-158: Good story coverage for different scenarios.The three stories cover useful test cases:
ThirtyDays: Full dataset with all metricsSingleDayRevenue: Edge case with minimal data pointsSingleDayRevenueNoX402: Tests graceful handling when x402 data is emptyapps/dashboard/src/app/(app)/team/components/Analytics/BarChart.tsx (3)
28-32: Type extension for stackedKeys support.The intersection type with an index signature works, though it's somewhat redundant with
ChartConfig's existing index signature. This approach is acceptable for adding the optionalstackedKeysproperty.
40-48: Correct isEmpty logic for stacked charts.The empty state detection properly handles both scenarios:
- For stacked charts: checks if all
stackedKeysvalues are zero across all data points- For non-stacked: checks if
activeKeyvalues are all zeroThe defensive type assertion on line 41 ensures safe property access.
104-128: LGTM! Stacked bar rendering implementation.The conditional rendering correctly:
- Uses
stackId={activeKey}to group stacked bars together- Applies per-key colors with sensible fallback chain
- Maintains consistent styling (
radius,strokeWidth,className) across both pathsapps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsx (4)
3-8: LGTM!The new imports (
useStateandX402SettlementsOverall) correctly support the component's updated functionality.
31-33: Verify loss of deep-linking is acceptable.The component now uses local state instead of URL search params for chart selection. This simplifies the implementation but removes the ability to deep-link to a specific chart view or persist the selection across page refreshes.
If deep-linking was a desired feature, consider keeping the URL-based approach or adding logic to sync local state with URL params.
107-153: Logic is sound, but watch for timezone edge cases.The time-series aggregation correctly:
- Combines dates from all three data sources (lines 115-118)
- Filters bridge revenue to only
completedtransactions (line 134)- Sums x402 revenue from
totalValueUSD(line 140)- Composes
feesCollectedfrom both revenue streams (line 145)However,
ignoreTimePeriodconverts dates to UTC viatoISOString()(line 156). If input dates are in different timezones, this could misalign data points at day boundaries.Verify that all input data sources (
userStats,volumeStats,x402Settlements) use consistent timezone-aware date strings, or that UTC normalization is the intended behavior for daily aggregation.
41-63: BothhideAsTabandstackedKeysare supported byCombinedBarChartCard. The type definition inCombinedBarChartConfigincludes both optional properties, and the implementation actively uses them:hideAsTabfilters which charts appear in the tab list, andstackedKeysenables rendering multiple bars stacked together in the chart.apps/dashboard/src/@/types/analytics.ts (1)
104-118: Good refactoring—DRY compliance improved.The inheritance approach eliminates duplicate field declarations across the X402Settlement interfaces. The removal of the export on
X402SettlementsByReceiveris safe; this type has no external consumers.
| type TimeSeriesMetrics = AggregatedMetrics & { | ||
| date: string; | ||
| bridgeRevenue: number; | ||
| x402Revenue: number; | ||
| }; |
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.
Remove duplicate field declarations.
TimeSeriesMetrics extends AggregatedMetrics (line 98), which already includes bridgeRevenue and x402Revenue (lines 18-19). Re-declaring them here (lines 100-101) is redundant.
type TimeSeriesMetrics = AggregatedMetrics & {
date: string;
- bridgeRevenue: number;
- x402Revenue: number;
};🤖 Prompt for AI Agents
In
apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/_analytics/highlights-card-ui.tsx
around lines 98 to 102, the TimeSeriesMetrics type re-declares bridgeRevenue and
x402Revenue even though they are already defined on AggregatedMetrics; remove
the duplicate bridgeRevenue and x402Revenue properties from the
TimeSeriesMetrics definition so it simply extends AggregatedMetrics and adds
only the date field.

PR-Codex overview
This PR focuses on enhancing the analytics components of the dashboard by refining data handling and visualization, adding new properties to interfaces, and improving the rendering logic for charts and highlights.
Detailed summary
maximumFractionDigitsto2inproject-wallet-details.tsx.stackedKeystoCombinedBarChartConfiginCombinedBarChartCard.BarChartto handlestackedKeysfor conditional rendering.x402Settlementshandling inProjectHighlightCard.highlights-card-ui.stories.tsx.ProjectHighlightsCardto includebridgeRevenueandx402Revenue.Summary by CodeRabbit
New Features
Improvements
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.