Files
calendar/packages/lib/hooks/useHasPaidPlan.ts
T
Amit SharmaGitHubKeith WilliamsDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2ed0380e4f feat: adds user plan info in useHasPaidPlan for intercom (#23790)
* feat: adds user plan info in `useHasPaidPlan` for intercom

* add to support api route

* Update constants.ts

* sql migration to backfill plans and create/change plans on upgrade/downgrade/create of teams and orgs

* fix: breaking unit tests

* test: add comprehensive tests for billing plan service and team/org flows

- Add unit tests for BillingPlanService.getUserPlanByMemberships() covering all plan determination scenarios
- Add tests for team creation handler verifying TEAMS vs ORGANIZATIONS plan assignment
- Add tests for hasTeamPlan handler integration with BillingPlanService
- Add tests for MembershipRepository.findAllMembershipsByUserIdForBilling() data fetching
- Add tests for InternalTeamBilling upgrade/downgrade flows with proper mocking
- All tests follow existing vitest patterns with proper Prisma and service mocking
- Covers both self-serve and platform billing scenarios with comprehensive edge cases

Co-Authored-By: amit@cal.com <samit91848@gmail.com>

* Revert "test: add comprehensive tests for billing plan service and team/org flows"

This reverts commit 58e511f15caf8757c3ec45f6d026caf96ee1a75e.

* fix: make `BillingPlanService` instantiable and use `TeamRepository`

* Revert "fix: make `BillingPlanService` instantiable and use `TeamRepository`"

This reverts commit ae1ff8f15b725566b828864a217d8d0e308b520f.

* revert to runtime calculations. review fixes

* remove uneccessary changes and logs

* review fixes

* review fixes

* fix: type check

---------

Co-authored-by: Keith Williams <keithwillcode@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2025-09-25 13:00:19 +05:30

58 lines
2.0 KiB
TypeScript

import { trpc } from "@calcom/trpc/react";
import { IS_SELF_HOSTED } from "../constants";
import hasKeyInMetadata from "../hasKeyInMetadata";
export function useHasPaidPlan() {
if (IS_SELF_HOSTED) return { isPending: false, hasPaidPlan: true };
const { data, isPending: isPendingTeamQuery } = trpc.viewer.teams.hasTeamPlan.useQuery();
const { data: user, isPending: isPendingUserQuery } = trpc.viewer.me.get.useQuery();
const isPending = isPendingTeamQuery || isPendingUserQuery;
const isCurrentUsernamePremium =
user && hasKeyInMetadata(user, "isPremium") ? !!user.metadata.isPremium : false;
const hasPaidPlan = data?.hasTeamPlan || isCurrentUsernamePremium;
return { isPending, hasPaidPlan, plan: data?.plan };
}
export function useTeamInvites() {
const listInvites = trpc.viewer.teams.listInvites.useQuery();
return { isPending: listInvites.isPending, listInvites: listInvites.data };
}
export function useHasTeamPlan() {
const { data: hasTeamPlan, isPending } = trpc.viewer.teams.hasTeamPlan.useQuery();
return { isPending, hasTeamPlan: hasTeamPlan?.hasTeamPlan };
}
export function useHasEnterprisePlan() {
// TODO: figure out how to get "has Enterprise / has Org" from the backend
const { data: hasTeamPlan, isPending } = trpc.viewer.teams.hasTeamPlan.useQuery();
return { isPending, hasTeamPlan: hasTeamPlan?.hasTeamPlan };
}
export function useHasActiveTeamPlan() {
if (IS_SELF_HOSTED) return { isPending: false, hasActiveTeamPlan: true, isTrial: false };
const { data, isPending } = trpc.viewer.teams.hasActiveTeamPlan.useQuery();
return { isPending, hasActiveTeamPlan: !!data?.isActive, isTrial: !!data?.isTrial };
}
export function useHasActiveTeamPlanAsOwner() {
if (IS_SELF_HOSTED) return { isPending: false, hasActiveTeamPlan: true, isTrial: false };
const { data, isPending } = trpc.viewer.teams.hasActiveTeamPlan.useQuery({ ownerOnly: true });
return { isPending, hasActiveTeamPlan: !!data?.isActive, isTrial: !!data?.isTrial };
}
export default useHasPaidPlan;