Skip to content

Conversation

@anikdhabal
Copy link
Contributor

@anikdhabal anikdhabal commented Aug 12, 2025

What does this PR do?

Make sure to show the skip trial button to the correct team owner

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 12, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

  • Replaced useHasActiveTeamPlan with useHasActiveTeamPlanAsOwner in shell bottom-nav hook; isTrial is now derived from the new hook.
  • Added useHasActiveTeamPlanAsOwner hook that runs the paid-plan TRPC query with ownerOnly: true and preserves the self-hosted short-circuit.
  • Added ZHasActiveTeamPlanInputSchema and THasActiveTeamPlanInputSchema; viewer teams router now validates hasActiveTeamPlan input with that schema.
  • hasActiveTeamPlan handler signature now accepts input, queries memberships (optionally filtering role = OWNER) and maps memberships to teams; return shape unchanged.
  • skipTeamTrials handler and its tests now fetch memberships (selecting team) and map to teams; update.handler now calls hasActiveTeamPlanHandler with input: { ownerOnly: false } for non-premium users.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch skip_trial_button_visibility

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.

❤️ Share
🪧 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@graphite-app graphite-app bot requested a review from a team August 12, 2025 09:50
@vercel
Copy link

vercel bot commented Aug 12, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Aug 26, 2025 5:05am
cal-eu Ignored Ignored Aug 26, 2025 5:05am

@keithwillcode keithwillcode added the core area: core, team members only label Aug 12, 2025
@anikdhabal anikdhabal requested a review from joeauyeung August 12, 2025 09:52
@dosubot dosubot bot added the 🐛 bug Something isn't working label Aug 12, 2025
@graphite-app
Copy link

graphite-app bot commented Aug 12, 2025

Graphite Automations

"Add consumer team as reviewer" took an action on this PR • (08/12/25)

1 reviewer was added to this PR based on Keith Williams's automation.

"Add ready-for-e2e label" took an action on this PR • (08/26/25)

1 label was added to this PR based on Keith Williams's automation.

Copy link
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: 1

🔭 Outside diff range comments (1)
packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts (1)

41-41: Apply select pattern to platformBilling query

Following the coding guideline to only select necessary data in Prisma queries, limit the selection to only the plan field.

-const platformBilling = await prisma.platformBilling.findUnique({ where: { id: team.id } });
+const platformBilling = await prisma.platformBilling.findUnique({ 
+  where: { id: team.id },
+  select: { plan: true }
+});
🧹 Nitpick comments (3)
packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts (3)

1-1: Consider using more specific Prisma type imports

Instead of importing the entire Prisma namespace, consider importing only the specific type needed (MembershipWhereInput) for better tree-shaking and clarity.

-import type { Prisma } from "@prisma/client";
+import type { MembershipWhereInput } from "@prisma/client";

Then update line 20:

-const whereClause: Prisma.MembershipWhereInput = { userId: ctx.user.id, accepted: true };
+const whereClause: MembershipWhereInput = { userId: ctx.user.id, accepted: true };

33-33: Consider adding null safety for team mapping

While the Prisma query should return teams, adding a defensive check ensures robustness in case of data inconsistencies.

-const teams = memberships.map((membership) => membership.team);
+const teams = memberships.map((membership) => membership.team).filter(Boolean);

39-55: Consider extracting team billing logic into a separate function

The nested loop with multiple return statements and complex billing logic could benefit from extraction into a separate function for better readability and testability.

Consider refactoring this logic into a helper function:

async function checkTeamBillingStatus(team: typeof teams[0]) {
  if (team.isPlatform && team.isOrganization) {
    const platformBilling = await prisma.platformBilling.findUnique({ 
      where: { id: team.id },
      select: { plan: true }
    });
    if (platformBilling && platformBilling.plan !== "none" && platformBilling.plan !== "FREE") {
      return { isActive: true, isTrial: false };
    }
  }
  
  const teamBillingService = new InternalTeamBilling(team);
  const subscriptionStatus = await teamBillingService.getSubscriptionStatus();
  
  if (subscriptionStatus === "active" || subscriptionStatus === "past_due") {
    return { isActive: true, isTrial: false };
  }
  
  if (subscriptionStatus === "trialing") {
    return { isActive: false, isTrial: true };
  }
  
  return null;
}

Then simplify the main loop:

for (const team of teams) {
  const status = await checkTeamBillingStatus(team);
  if (status) {
    if (status.isActive) return status;
    isTrial = status.isTrial || isTrial;
  }
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 01a0d43 and 103fcbd.

📒 Files selected for processing (6)
  • packages/features/shell/useBottomNavItems.ts (2 hunks)
  • packages/lib/hooks/useHasPaidPlan.ts (1 hunks)
  • packages/trpc/server/routers/viewer/teams/_router.tsx (2 hunks)
  • packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts (1 hunks)
  • packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.schema.ts (1 hunks)
  • packages/trpc/server/routers/viewer/teams/skipTeamTrials.handler.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.ts

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/lib/hooks/useHasPaidPlan.ts
  • packages/trpc/server/routers/viewer/teams/skipTeamTrials.handler.ts
  • packages/features/shell/useBottomNavItems.ts
  • packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts
  • packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.schema.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/lib/hooks/useHasPaidPlan.ts
  • packages/trpc/server/routers/viewer/teams/skipTeamTrials.handler.ts
  • packages/trpc/server/routers/viewer/teams/_router.tsx
  • packages/features/shell/useBottomNavItems.ts
  • packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts
  • packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.schema.ts
**/*.tsx

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

Always use t() for text localization in frontend code; direct text embedding should trigger a warning

Files:

  • packages/trpc/server/routers/viewer/teams/_router.tsx
🧬 Code Graph Analysis (4)
packages/lib/hooks/useHasPaidPlan.ts (2)
packages/lib/constants.ts (1)
  • IS_SELF_HOSTED (59-59)
apps/web/app/_trpc/trpc.ts (1)
  • trpc (7-7)
packages/trpc/server/routers/viewer/teams/_router.tsx (1)
packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.schema.ts (1)
  • ZHasActiveTeamPlanInputSchema (3-7)
packages/features/shell/useBottomNavItems.ts (1)
packages/lib/hooks/useHasPaidPlan.ts (1)
  • useHasActiveTeamPlanAsOwner (49-55)
packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts (2)
packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.schema.ts (1)
  • THasActiveTeamPlanInputSchema (9-9)
packages/lib/constants.ts (1)
  • IS_SELF_HOSTED (59-59)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (8)
packages/trpc/server/routers/viewer/teams/skipTeamTrials.handler.ts (1)

32-43: LGTM! Membership-based query aligns with ownership filtering pattern.

The change from a nested Team query to a direct Membership query with explicit filtering is consistent with the PR's pattern of using membership-based ownership checks. The logic correctly filters for accepted OWNER memberships and maps to teams.

packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.schema.ts (1)

1-9: LGTM! Well-structured input schema with appropriate typing.

The schema correctly defines an optional ownerOnly boolean parameter wrapped in an optional object, providing flexibility for the API consumers. The type inference and exports are properly structured.

packages/features/shell/useBottomNavItems.ts (1)

23-23: LGTM! Trial detection now correctly uses owner-only filtering.

The change ensures that the skip trial button only appears when the user owns teams in trial status, rather than being a member of any team in trial status. This addresses the core issue described in the PR.

packages/lib/hooks/useHasPaidPlan.ts (1)

49-55: LGTM! New hook correctly implements owner-only team plan checking.

The new hook properly mirrors the existing useHasActiveTeamPlan pattern while adding the ownerOnly: true parameter to the TRPC query. The self-hosted short-circuit and return structure are consistent with the existing hook.

packages/trpc/server/routers/viewer/teams/_router.tsx (1)

16-16: LGTM! Input validation properly added to hasActiveTeamPlan route.

The import of ZHasActiveTeamPlanInputSchema and its application to the hasActiveTeamPlan route ensures proper validation of the ownerOnly parameter. The route structure remains consistent with other routes in the router.

Also applies to: 191-194

packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts (3)

26-31: Good use of select over include for Prisma query

The query correctly uses select to fetch only the necessary data (team), following the Prisma best practices outlined in the coding guidelines.


17-58: Overall implementation looks good with owner-only filtering

The handler successfully implements the owner-only filtering feature for team plan checking, aligning well with the PR objectives to fix "Skip trial button visibility". The membership-based approach is consistent with other handlers in the codebase and properly handles both platform and regular team billing scenarios.


22-24: No action needed: ownerOnly is defined in the input schema

Verified that ZHasActiveTeamPlanInputSchema in packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.schema.ts declares ownerOnly as an optional boolean. The handler’s check on input?.ownerOnly is valid.

Copy link
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: 1

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 103fcbd and 8698abb.

📒 Files selected for processing (1)
  • packages/trpc/server/routers/viewer/workflows/update.handler.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.ts

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/trpc/server/routers/viewer/workflows/update.handler.ts
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/trpc/server/routers/viewer/workflows/update.handler.ts
🧬 Code Graph Analysis (1)
packages/trpc/server/routers/viewer/workflows/update.handler.ts (1)
packages/trpc/server/routers/viewer/teams/hasActiveTeamPlan.handler.ts (1)
  • hasActiveTeamPlanHandler (17-58)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Detect changes

Copy link
Contributor

@joeauyeung joeauyeung left a comment

Choose a reason for hiding this comment

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

Since this is a non urgent fix and we're making changes to the prisma queries. Let's take the time and move the queries to a repository.

},
});

const ownedTeams = memberships.map((membership) => membership.team);
Copy link
Contributor

Choose a reason for hiding this comment

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

NIT: Personally I'm not a huge fan of iterating over this array here and on line 45.

@github-actions github-actions bot marked this pull request as draft August 15, 2025 16:33
@anikdhabal anikdhabal requested a review from joeauyeung August 26, 2025 04:14
@anikdhabal anikdhabal marked this pull request as ready for review August 26, 2025 04:15
@dosubot dosubot bot added the teams area: teams, round robin, collective, managed event-types label Aug 26, 2025
Copy link
Contributor

@Devanshusharma2005 Devanshusharma2005 left a comment

Choose a reason for hiding this comment

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

LGTM

@github-actions
Copy link
Contributor

github-actions bot commented Aug 26, 2025

E2E results are ready!

@anikdhabal anikdhabal merged commit bb3ba88 into main Aug 26, 2025
87 of 90 checks passed
@anikdhabal anikdhabal deleted the skip_trial_button_visibility branch August 26, 2025 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 bug Something isn't working core area: core, team members only ready-for-e2e teams area: teams, round robin, collective, managed event-types

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants