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

Skip to content

Conversation

@TWilson023
Copy link
Collaborator

@TWilson023 TWilson023 commented Jun 12, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a comprehensive program analytics dashboard featuring interactive time series charts and a paginated partner analytics table.
    • Added advanced filter options with AI-assisted suggestions and streamlined filter management via a new custom hook.
    • Enabled analytics sorting and grouping by event types and top partners, with enhanced data fetching and schema support.
    • Added an "Analytics" section to the sidebar for easy navigation.
    • Introduced a tabbed interface for switching between event types and sale units in analytics views.
    • Added a chart view switcher to toggle between timeseries and funnel visualizations.
  • Improvements

    • Enhanced data visualization with detailed tooltips, gradient fills, and customizable chart views.
    • Enriched partner analytics with detailed partner information, revenue insights, and improved loading/error states.
    • Centralized query parameter parsing and query string construction for consistent analytics filtering across components.
    • Refactored analytics tabs rendering for cleaner UI and better state management.
    • Simplified analytics filter UI by extracting logic into a dedicated hook.
    • Improved link filtering control in top links component.
    • Updated revenue data fetching to use direct API calls with caching.
    • Refined analytics provider to delegate query parameter parsing to a custom hook.
  • Bug Fixes

    • Improved loading and error state handling across analytics components and partner tables.
    • Added validation to prevent unauthorized program ID queries in analytics API.

@vercel
Copy link
Contributor

vercel bot commented Jun 12, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
dub ✅ Ready (Inspect) Visit Preview Jun 16, 2025 10:49pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 12, 2025

Walkthrough

This update introduces new React components for program analytics, including a time series chart and a paginated partners table, alongside a tabbed interface and enhanced filter management via custom hooks. Backend support for top partner analytics is added with expanded schemas and a new Tinybird pipe. The UI and data fetching logic are refactored for modularity and improved query handling, including removal of a deprecated revenue hook.

Changes

File(s) / Group Change Summary
analytics-chart.tsx, analytics-partners-table.tsx, analytics-tabs.tsx, use-analytics-filters.tsx, use-analytics-query.tsx, chart-view-switcher.tsx Added new React components and hooks for analytics charts, partners tables, tabs, filter management, query construction, and chart view switching.
page-client.tsx, page.tsx Added main program analytics dashboard pages and context providers.
main.tsx, toggle.tsx, top-links.tsx Refactored tab rendering, filter logic, and link generation for modularity and feature support; added optional filtering control to top links.
analytics-provider.tsx Refactored provider to use new analytics query hook, simplifying internal logic.
utils.ts Updated analytics filter result types and context usage in filter option hook.
get-analytics.ts Added support for grouping analytics by top partners with partner data enrichment.
types.ts Added AnalyticsResponse type mapping analytics response schemas.
use-program-revenue.ts Removed deprecated useProgramRevenue hook entirely.
zod/schemas/analytics-response.ts Extended top_partners schema with nested partner detail fields.
zod/schemas/analytics.ts Added optional sortBy field to analytics query schema and related filters.
sidebar/app-sidebar-nav.tsx Added "Analytics" navigation item to program sidebar.
v2_top_partners.pipe Added Tinybird pipe defining SQL nodes for top partner analytics aggregation.
apps/web/app/api/analytics/route.ts Modified folder ID fetching logic to skip if programId is present and added program ID validation.
overview-chart.tsx Replaced useProgramRevenue with direct SWR data fetching for revenue data.
api/programs/[programId]/revenue/route.ts Removed API route handler for program revenue timeseries.
analytics-funnel-chart.tsx Added default prop and removed fixed sizing wrapper from funnel chart container.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ProgramAnalyticsPageClient
  participant ProgramAnalyticsContext
  participant AnalyticsChart
  participant AnalyticsPartnersTable
  participant API
  participant Database

  User->>ProgramAnalyticsPageClient: Loads analytics dashboard
  ProgramAnalyticsPageClient->>ProgramAnalyticsContext: Provides query/filter context
  ProgramAnalyticsPageClient->>AnalyticsChart: Renders chart with context
  AnalyticsChart->>API: Fetches time series analytics data
  API->>Database: Queries analytics tables
  Database-->>API: Returns time series data
  API-->>AnalyticsChart: Returns analytics response
  AnalyticsChart-->>User: Displays time series chart

  ProgramAnalyticsPageClient->>AnalyticsPartnersTable: Renders partners table with context
  AnalyticsPartnersTable->>API: Fetches top partners analytics
  API->>Database: Runs top partners pipe
  Database-->>API: Returns top partners data
  API-->>AnalyticsPartnersTable: Returns enriched partner analytics
  AnalyticsPartnersTable-->>User: Displays partners table
Loading

Suggested reviewers

  • steven-tey

Poem

🐇 In data fields where numbers play,
New charts and tables light the way.
Partners counted, filters spun,
Analytics shines like morning sun.
Pipes and hooks now weave the tale,
Hop with joy, let insights sail! 🌿📈✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d95c977 and 60d87c5.

📒 Files selected for processing (6)
  • README.md (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/analytics-chart.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/analytics-partners-table.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/page-client.tsx (1 hunks)
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/overview-chart.tsx (5 hunks)
  • apps/web/lib/zod/schemas/analytics-response.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • README.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • apps/web/lib/zod/schemas/analytics-response.ts
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/analytics-chart.tsx
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/overview-chart.tsx
  • apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/analytics-partners-table.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (2)
apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/page-client.tsx (2)

26-36: Constant interval overrides URL-supplied value

interval from the query string is ignored in favour of DUB_PARTNERS_ANALYTICS_INTERVAL.
Confirm this is intentional; otherwise, users changing interval via the URL will observe silently ignored input.


38-46: ```shell
#!/bin/bash

Display the first 200 lines of the analytics page-client component for context

sed -n '1,200p' 'apps/web/app/app.dub.co/(dashboard)/[slug]/(ee)/program/analytics/page-client.tsx'


</details>

</blockquote></details>

</details>
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=dubinc/dub&utm_content=2519):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) 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)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 12, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 13, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 13, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 13, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 13, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 13, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 13, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 13, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 13, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@steven-tey
Copy link
Collaborator

@CodeRabbit final review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 16, 2025

Tip

For best results, initiate chat on the files or code changes.

@steven-tey, I've already provided two comprehensive final reviews of this Program Analytics implementation. My assessment remains unchanged:

🎯 Final Decision: APPROVED FOR MERGE

Key Highlights:

  • Excellent architecture with clean separation of concerns
  • High-quality components with proper error handling and loading states
  • Robust backend integration with Tinybird pipeline
  • Performance optimized with smart caching and memoization
  • All tests passing consistently
  • Production-ready code quality

This is a well-engineered analytics solution that follows best practices and provides a solid foundation for future enhancements.

Ready to ship! 🚀

  ╭─╮
 ( o.o )
  > ^ <

Confident and ready to hop into production!

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 16, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 16, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 16, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

@bug0-qa-agent
Copy link

bug0-qa-agent bot commented Jun 16, 2025

🤖 Bug0 QA Agent

Here are the results of the automated tests for PR #2519:

To re-run the tests, please comment /bug0 run or push a new commit to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants