Skip to content

Update AdminPage and Organizations components for improved tab manage…#486

Merged
goldflag merged 5 commits intomasterfrom
improve-admin
Jul 22, 2025
Merged

Update AdminPage and Organizations components for improved tab manage…#486
goldflag merged 5 commits intomasterfrom
improve-admin

Conversation

@goldflag
Copy link
Copy Markdown
Collaborator

@goldflag goldflag commented Jul 18, 2025

…ment and formatting

  • Changed the default active tab in AdminPage from "users" to "organizations" for better user experience.
  • Consolidated and streamlined JSX formatting in Organizations component for enhanced readability.
  • Introduced a new utility function, parseUtcTimestamp, for converting UTC timestamps to local time.
  • Improved consistency in the handling of subscription status and event counts across components.

Summary by CodeRabbit

  • New Features

    • Added a utility to correctly parse and display UTC timestamps in the local timezone.
    • Introduced new "Events (30d)" and "Subscription" columns in the Sites admin table with status-indicative badges.
    • Enhanced subscription data display for organizations and sites with detailed plan and status information.
    • Added a reusable GrowthChart component to visualize growth data trends in admin tables.
  • Style

    • Improved code formatting and readability across multiple admin components, including condensing imports and JSX expressions.
  • Refactor

    • Updated the default active tab in the admin panel to "organizations" and rearranged tab order for easier navigation.
    • Changed sorting of organizations and sites to display the most recently created entries first.
    • Streamlined error handling and badge color assignment logic in admin tables.
    • Centralized subscription data retrieval via a new service for better performance and maintainability.

…ment and formatting

- Changed the default active tab in AdminPage from "users" to "organizations" for better user experience.
- Consolidated and streamlined JSX formatting in Organizations component for enhanced readability.
- Introduced a new utility function, parseUtcTimestamp, for converting UTC timestamps to local time.
- Improved consistency in the handling of subscription status and event counts across components.
@vercel
Copy link
Copy Markdown

vercel bot commented Jul 18, 2025

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

Name Status Preview Comments Updated (UTC)
rybbit ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 22, 2025 1:21am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jul 18, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

The updates include stylistic and formatting refinements in admin UI components and backend API handlers, with the addition of a parseUtcTimestamp utility for date parsing. Backend queries for organizations and sites now sort by creation date descending. Subscription data retrieval was refactored into a dedicated service. The default admin tab is switched to "organizations." A new GrowthChart component was added to visualize growth data in organizations and sites views.

Changes

File(s) Change Summary
client/src/app/admin/components/organizations/Organizations.tsx, client/src/app/admin/components/sites/Sites.tsx Refactored imports and JSX formatting, added GrowthChart component above search input, replaced date parsing with parseUtcTimestamp, added new columns for sites table, simplified conditional JSX and pagination logic.
client/src/app/admin/page.tsx Changed default active tab to "organizations," reordered tab triggers, condensed multiline paragraph in settings tab.
client/src/lib/dateTimeUtils.ts Added parseUtcTimestamp utility to parse UTC timestamps into local DateTime objects.
client/src/api/admin/getAdminSites.ts Extended AdminSiteData interface with eventsLast30Days and subscription fields.
client/src/app/admin/components/shared/GrowthChart.tsx Added new GrowthChart React component for visualizing growth data with a line chart, supporting customizable color and title.
server/src/api/admin/getAdminOrganizations.ts Refactored subscription retrieval to use new subscription service, changed sort order to createdAt descending, removed helper function.
server/src/api/admin/getAdminSites.ts Updated to fetch both 24-hour and 30-day event counts, included subscription data, changed sort order to createdAt descending.
server/src/services/admin/subscriptionService.ts New service added to fetch and map Stripe subscription data for organizations, including detailed subscription info and defaults.

Sequence Diagram(s)

sequenceDiagram
    participant AdminUI
    participant BackendAPI
    participant SubscriptionService
    participant Database
    participant StripeAPI

    AdminUI->>BackendAPI: Request organizations/sites data
    BackendAPI->>Database: Query organizations/sites ordered by createdAt desc
    BackendAPI->>SubscriptionService: getOrganizationSubscriptions(organizations)
    SubscriptionService->>StripeAPI: Fetch active subscriptions by customer IDs (paginated)
    StripeAPI-->>SubscriptionService: Return subscription data
    SubscriptionService-->>BackendAPI: Return mapped subscription data
    BackendAPI-->>AdminUI: Return enriched organizations/sites data with subscriptions and event counts
    AdminUI->>parseUtcTimestamp: Parse createdAt timestamps (organizations)
Loading

Estimated code review effort

3 (~45 minutes)

Poem

🐇
A hop, a skip, a tidy sweep,
Code lines condensed, no need to weep.
Dates parsed right, tabs rearranged,
Organizations now first—how things have changed!
With order by "createdAt" now in sight,
The admin burrow feels just right.
📅✨


📜 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 9ed9e15 and 837fd08.

📒 Files selected for processing (1)
  • client/src/app/admin/components/sites/Sites.tsx (8 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • 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 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 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 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 for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

- Added support for tracking events over the last 30 days in the admin site data.
- Introduced subscription details in the admin site and organization responses, improving visibility into user plans.
- Refactored event count retrieval to streamline data fetching from Clickhouse for both 24-hour and 30-day periods.
- Updated the Sites component to display new subscription and event count information, enhancing the admin interface.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a 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 (2)
client/src/app/admin/components/sites/Sites.tsx (2)

9-9: Unused import detected.

The parseUtcTimestamp import is not used in this file. Consider removing it or implementing its usage for consistent date handling.

-import { parseUtcTimestamp } from "@/lib/dateTimeUtils";

44-44: Use optional chaining for better readability.

The static analysis tool correctly identifies that optional chaining would be more concise and readable.

-        (site.organizationOwnerEmail && site.organizationOwnerEmail.toLowerCase().includes(lowerSearchQuery))
+        site.organizationOwnerEmail?.toLowerCase().includes(lowerSearchQuery)
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4293705 and 1a19e48.

📒 Files selected for processing (6)
  • client/src/app/admin/components/organizations/Organizations.tsx (16 hunks)
  • client/src/app/admin/components/sites/Sites.tsx (8 hunks)
  • client/src/app/admin/page.tsx (2 hunks)
  • client/src/lib/dateTimeUtils.ts (1 hunks)
  • server/src/api/admin/getAdminOrganizations.ts (9 hunks)
  • server/src/api/admin/getAdminSites.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
{client,server}/**/*.{ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
🧠 Learnings (3)
client/src/app/admin/components/sites/Sites.tsx (2)
Learnt from: CR
PR: rybbit-io/rybbit#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-17T23:25:24.134Z
Learning: Applies to client/**/*.{tsx} : Client: Use React functional components with minimal useEffect and inline functions
Learnt from: CR
PR: rybbit-io/rybbit#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-17T23:25:24.134Z
Learning: Frontend: Use Next.js, Tailwind CSS, Shadcn UI, Tanstack Query, Zustand, Luxon, and Nivo
server/src/api/admin/getAdminOrganizations.ts (1)
Learnt from: CR
PR: rybbit-io/rybbit#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-17T23:25:24.134Z
Learning: Backend: Use Fastify, Drizzle ORM (Postgres), and ClickHouse
client/src/app/admin/components/organizations/Organizations.tsx (3)
Learnt from: CR
PR: rybbit-io/rybbit#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-17T23:25:24.134Z
Learning: Applies to client/**/*.{tsx} : Client: Use React functional components with minimal useEffect and inline functions
Learnt from: CR
PR: rybbit-io/rybbit#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-17T23:25:24.134Z
Learning: Applies to {client,server}/**/*.{ts,tsx} : Group imports by external, then internal, and sort alphabetically within groups
Learnt from: CR
PR: rybbit-io/rybbit#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-17T23:25:24.134Z
Learning: Frontend: Use Next.js, Tailwind CSS, Shadcn UI, Tanstack Query, Zustand, Luxon, and Nivo
🧬 Code Graph Analysis (3)
server/src/api/admin/getAdminSites.ts (3)
server/src/lib/auth-utils.ts (1)
  • getIsUserAdmin (26-36)
server/src/db/postgres/postgres.ts (1)
  • db (20-20)
server/src/db/postgres/schema.ts (1)
  • sites (48-77)
client/src/app/admin/components/sites/Sites.tsx (3)
client/src/app/admin/components/shared/SortableHeader.tsx (1)
  • SortableHeader (13-36)
client/src/components/Favicon.tsx (1)
  • Favicon (4-32)
client/src/app/admin/components/shared/SearchInput.tsx (1)
  • SearchInput (13-30)
server/src/api/admin/getAdminOrganizations.ts (2)
server/src/db/postgres/schema.ts (2)
  • organization (138-152)
  • sites (48-77)
client/src/api/admin/getAdminOrganizations.ts (1)
  • AdminOrganizationData (4-33)
🪛 Biome (1.9.4)
client/src/app/admin/components/sites/Sites.tsx

[error] 44-44: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ 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). (2)
  • GitHub Check: Build Client Images (ubuntu-24.04-arm, linux/arm64)
  • GitHub Check: Build Client Images (ubuntu-latest, linux/amd64)
🔇 Additional comments (21)
client/src/lib/dateTimeUtils.ts (1)

213-220: Well-implemented utility function.

The parseUtcTimestamp function is correctly implemented with proper JSDoc documentation and uses the appropriate Luxon methods for UTC timestamp parsing and local time conversion.

client/src/app/admin/page.tsx (3)

12-12: Consistent default tab update.

The change from "users" to "organizations" as the default active tab aligns with the PR objectives and is consistently applied.


17-17: Proper defaultValue synchronization.

The Tabs component's defaultValue is correctly updated to match the activeTab state.


21-21: Tab order updated to reflect new priority.

Moving the users tab after sites reflects the new emphasis on organizations as the primary focus.

server/src/api/admin/getAdminSites.ts (2)

23-25: Improved performance with database-level ordering.

Moving the sorting operation from JavaScript to the database query with orderBy is more efficient and aligns with the frontend's emphasis on recent sites.


83-83: Clean formatting improvement.

The conditional assignment formatting is more concise while maintaining readability.

client/src/app/admin/components/sites/Sites.tsx (1)

80-82: Improved date handling.

Removing the unnecessary new Date() wrapper simplifies the code since formatDistanceToNow can handle string timestamps directly.

client/src/app/admin/components/organizations/Organizations.tsx (4)

10-10: Good import addition for consistent date handling.

The parseUtcTimestamp import is properly added and used in the component.


132-134: Proper timezone-aware date parsing.

Using parseUtcTimestamp ensures consistent handling of UTC timestamps from the server, converting them to local time for display. This is a significant improvement over direct new Date() usage.


86-86: Clean error handling simplification.

The error message extraction is more concise while maintaining type safety.


101-101: Acceptable nested ternary for subscription status.

The nested ternary is readable and appropriate for this simple three-way conditional logic.

server/src/api/admin/getAdminOrganizations.ts (10)

8-8: Import consolidation looks good.

The consolidation of the import statement into a single line improves readability without affecting functionality.


21-21: Function formatting improvement.

The single-line formatting with trailing comma follows TypeScript best practices and improves consistency.


60-60: Function signature formatting is consistent.

The single-line function signature aligns with the coding guidelines and improves readability.


112-112: Conditional formatting improvement.

The formatting consolidation maintains the same logic while improving readability. The ternary operator correctly handles the case when allOrgIds.length is 0.


144-144: Console warning formatting improvement.

The single-line formatting is more concise while maintaining the same functionality.


165-166: Filtering and mapping consolidation looks good.

The single-line formatting improves readability while maintaining the same filtering logic for organizations with Stripe customer IDs.


200-205: Object property formatting improvements.

The consolidation of multiline property assignments into single lines improves consistency and readability. The logic remains unchanged.


212-212: Pagination logic formatting improvement.

The single-line formatting maintains the same array access logic while being more concise.


226-245: Organization mapping consolidation is well-structured.

The reformatting of the organization mapping from multiline to a more compact structure improves readability. The logic remains functionally equivalent:

  • Proper subscription data retrieval
  • Correct fallback handling for missing subscription data
  • Appropriate default values for free plans

70-70: Verify frontend handling of organization sorting

The server API for admin organizations now orders by createdAt (descending) instead of monthlyEventCount. A search in the client/ directory didn’t reveal any code that explicitly sorts or assumes sorting by monthlyEventCount. Please manually confirm:

  • The Admin Organizations list in the client UI displays organizations in the correct order (newest first).
  • Any related components or tests that may rely on the previous event-count ordering.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 1a19e48 and 4c3a6b8.

📒 Files selected for processing (5)
  • client/src/api/admin/getAdminSites.ts (1 hunks)
  • client/src/app/admin/components/sites/Sites.tsx (8 hunks)
  • server/src/api/admin/getAdminOrganizations.ts (6 hunks)
  • server/src/api/admin/getAdminSites.ts (3 hunks)
  • server/src/services/admin/subscriptionService.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/src/api/admin/getAdminSites.ts
🧰 Additional context used
📓 Path-based instructions (1)
{client,server}/**/*.{ts,tsx}

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • CLAUDE.md
🧠 Learnings (2)
server/src/api/admin/getAdminOrganizations.ts (1)
Learnt from: CR
PR: rybbit-io/rybbit#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-17T23:25:24.134Z
Learning: Backend: Use Fastify, Drizzle ORM (Postgres), and ClickHouse
client/src/app/admin/components/sites/Sites.tsx (2)
Learnt from: CR
PR: rybbit-io/rybbit#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-17T23:25:24.134Z
Learning: Applies to client/**/*.{tsx} : Client: Use React functional components with minimal useEffect and inline functions
Learnt from: CR
PR: rybbit-io/rybbit#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-17T23:25:24.134Z
Learning: Frontend: Use Next.js, Tailwind CSS, Shadcn UI, Tanstack Query, Zustand, Luxon, and Nivo
🧬 Code Graph Analysis (1)
server/src/api/admin/getAdminOrganizations.ts (3)
server/src/db/postgres/schema.ts (2)
  • organization (138-152)
  • sites (48-77)
server/src/services/admin/subscriptionService.ts (1)
  • getOrganizationSubscriptions (104-146)
client/src/api/admin/getAdminOrganizations.ts (1)
  • AdminOrganizationData (4-33)
🪛 Biome (1.9.4)
client/src/app/admin/components/sites/Sites.tsx

[error] 44-44: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ 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). (2)
  • GitHub Check: Build Client Images (ubuntu-24.04-arm, linux/arm64)
  • GitHub Check: Build Client Images (ubuntu-latest, linux/amd64)
🔇 Additional comments (6)
client/src/api/admin/getAdminSites.ts (1)

10-15: LGTM! Interface properly extended for new data fields.

The additions to AdminSiteData interface correctly define the new subscription data structure and 30-day event count field, aligning with the backend changes.

client/src/app/admin/components/sites/Sites.tsx (2)

80-82: Good simplification!

Removing the unnecessary new Date() wrapper is correct since row.getValue("createdAt") already returns a valid date string that formatDistanceToNow can parse directly.


98-117: Well-implemented new columns with proper status-based styling.

The Events (30d) column correctly formats the count with locale-aware number formatting, and the Subscription column implements appropriate badge styling based on status (active → default, canceled → destructive, others → secondary).

server/src/api/admin/getAdminOrganizations.ts (2)

8-9: Excellent refactoring to centralize subscription logic.

The replacement of manual Stripe API pagination with the getOrganizationSubscriptions service improves code maintainability and reusability. The non-null assertion on line 162 is safe since the service guarantees a value for every organization (either actual subscription data or free plan defaults).

Also applies to: 157-174


63-63: Ordering change aligns with improved UX.

Changing from monthlyEventCount to createdAt descending order shows newest organizations first, which is typically more useful for administrators.

server/src/services/admin/subscriptionService.ts (1)

1-146: Well-architected subscription service with proper error handling.

This new service effectively centralizes subscription data retrieval with several strong implementation details:

  • Proper Stripe API pagination with rate limiting (20 req/s)
  • Defensive programming with fallback values for missing data
  • Consistent error handling that logs but doesn't throw
  • Clear separation between fetching raw data and organization mapping
  • Appropriate use of TypeScript types and interfaces

The service ensures every organization receives subscription data (either actual or free plan defaults), making it safe for consumers to use non-null assertions.

- Integrated GrowthChart into both Organizations and Sites components to visualize data trends.
- Enhanced user interface by providing graphical representation of organization and site data.
- Maintained consistent styling and functionality across both components.
goldflag and others added 2 commits July 21, 2025 21:20
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@goldflag goldflag merged commit bee7a07 into master Jul 22, 2025
3 of 6 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Oct 3, 2025
Merged
@coderabbitai coderabbitai bot mentioned this pull request Dec 5, 2025
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.

1 participant