Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/features/shell/useBottomNavItems.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { User as UserAuth } from "next-auth";

import { IS_DUB_REFERRALS_ENABLED } from "@calcom/lib/constants";
import { useHasActiveTeamPlan } from "@calcom/lib/hooks/useHasPaidPlan";
import { useHasActiveTeamPlanAsOwner } from "@calcom/lib/hooks/useHasPaidPlan";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { trpc } from "@calcom/trpc/react";
import { showToast } from "@calcom/ui/components/toast";
Expand All @@ -20,7 +20,7 @@ export function useBottomNavItems({
user,
}: BottomNavItemsProps): NavigationItemType[] {
const { t } = useLocale();
const { isTrial } = useHasActiveTeamPlan();
const { isTrial } = useHasActiveTeamPlanAsOwner();
const utils = trpc.useUtils();

const skipTeamTrialsMutation = trpc.viewer.teams.skipTeamTrials.useMutation({
Expand Down
7 changes: 7 additions & 0 deletions packages/lib/hooks/useHasPaidPlan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,12 @@ export function useHasActiveTeamPlan() {

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;
3 changes: 2 additions & 1 deletion packages/trpc/server/routers/viewer/teams/_router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ZGetInternalNotesPresetsInputSchema } from "./getInternalNotesPresets.s
import { ZGetMemberAvailabilityInputSchema } from "./getMemberAvailability.schema";
import { ZGetMembershipbyUserInputSchema } from "./getMembershipbyUser.schema";
import { ZGetUserConnectedAppsInputSchema } from "./getUserConnectedApps.schema";
import { ZHasActiveTeamPlanInputSchema } from "./hasActiveTeamPlan.schema";
import { ZHasEditPermissionForUserSchema } from "./hasEditPermissionForUser.schema";
import { ZInviteMemberInputSchema } from "./inviteMember/inviteMember.schema";
import { ZInviteMemberByTokenSchemaInputSchema } from "./inviteMemberByToken.schema";
Expand Down Expand Up @@ -187,7 +188,7 @@ export const viewerTeamsRouter = router({
const { default: handler } = await import("./updateInternalNotesPresets.handler");
return handler({ ctx, input });
}),
hasActiveTeamPlan: authedProcedure.query(async (opts) => {
hasActiveTeamPlan: authedProcedure.input(ZHasActiveTeamPlanInputSchema).query(async (opts) => {
const { default: handler } = await import("./hasActiveTeamPlan.handler");
return handler(opts);
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,37 @@
import type { Prisma } from "@prisma/client";

import { InternalTeamBilling } from "@calcom/ee/billing/teams/internal-team-billing";
import { IS_SELF_HOSTED } from "@calcom/lib/constants";
import { prisma } from "@calcom/prisma";
import type { TrpcSessionUser } from "@calcom/trpc/server/types";

import type { THasActiveTeamPlanInputSchema } from "./hasActiveTeamPlan.schema";

type HasActiveTeamPlanOptions = {
ctx: {
user: Pick<NonNullable<TrpcSessionUser>, "id">;
};
input: THasActiveTeamPlanInputSchema;
};

export const hasActiveTeamPlanHandler = async ({ ctx }: HasActiveTeamPlanOptions) => {
export const hasActiveTeamPlanHandler = async ({ ctx, input }: HasActiveTeamPlanOptions) => {
if (IS_SELF_HOSTED) return { isActive: true, isTrial: false };

const teams = await prisma.team.findMany({
where: {
members: {
some: {
userId: ctx.user.id,
accepted: true,
},
},
const whereClause: Prisma.MembershipWhereInput = { userId: ctx.user.id, accepted: true };

if (input?.ownerOnly) {
whereClause.role = "OWNER";
}

const memberships = await prisma.membership.findMany({
where: whereClause,
select: {
team: true,
},
});

const teams = memberships.map((membership) => membership.team);

if (!teams.length) return { isActive: false, isTrial: false };

let isTrial = false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
export {};
import { z } from "zod";

export const ZHasActiveTeamPlanInputSchema = z
.object({
ownerOnly: z.boolean().optional(),
})
.optional();

export type THasActiveTeamPlanInputSchema = z.infer<typeof ZHasActiveTeamPlanInputSchema>;
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,19 @@ export const skipTeamTrialsHandler = async ({ ctx }: SkipTeamTrialsOptions) => {
},
});

const ownedTeams = await prisma.team.findMany({
const memberships = await prisma.membership.findMany({
where: {
members: {
some: {
userId: ctx.user.id,
accepted: true,
role: "OWNER",
},
},
userId: ctx.user.id,
accepted: true,
role: "OWNER",
},
select: {
team: true,
},
});

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.


for (const team of ownedTeams) {
const teamBillingService = new InternalTeamBilling(team);

Expand Down
Loading