"use client"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { trpc } from "@calcom/trpc/react"; import classNames from "@calcom/ui/classNames"; import { Button } from "@calcom/ui/components/button"; import { Dialog, DialogContent, DialogFooter, DialogHeader } from "@calcom/ui/components/dialog"; import { showToast } from "@calcom/ui/components/toast"; import { usePathname } from "next/navigation"; import { useSession } from "next-auth/react"; import { useMemo, useState } from "react"; import { ActiveUserBreakdown } from "~/settings/billing/components/ActiveUserBreakdown"; import BillingCredits from "~/settings/billing/components/BillingCredits"; import { InvoicesTable } from "~/settings/billing/components/InvoicesTable"; interface CtaRowProps { title: string; description: string; children: React.ReactNode; className?: string; } declare global { interface Window { Support?: { open: () => void; shouldShowTriggerButton: (showTrigger: boolean) => void; }; } } export const CtaRow = ({ title, description, className, children }: CtaRowProps) => { return ( <>

{title}

{description}

{children}
); }; const BillingView = () => { const pathname = usePathname(); const session = useSession(); const { t } = useLocale(); const returnTo = pathname; const [showSkipTrialDialog, setShowSkipTrialDialog] = useState(false); const utils = trpc.useUtils(); const teamIdNumber = useMemo(() => { if (!pathname) return null; if (pathname.includes("/teams/") && pathname.includes("/billing")) { const teamIdMatch = pathname.match(/\/teams\/(\d+)\/billing/); return teamIdMatch ? parseInt(teamIdMatch[1], 10) : null; } if (pathname.includes("/organizations/billing")) { const orgId = session.data?.user?.org?.id; return typeof orgId === "number" ? orgId : null; } return null; }, [pathname, session.data?.user?.org?.id]); const { data: subscriptionStatus, isLoading: isLoadingStatus } = trpc.viewer.teams.getSubscriptionStatus.useQuery( { teamId: teamIdNumber ?? 0 }, { enabled: !!teamIdNumber } ); const skipTrialMutation = trpc.viewer.teams.skipTrialForTeam.useMutation({ onSuccess: () => { showToast(t("trial_skipped_successfully"), "success"); setShowSkipTrialDialog(false); // Invalidate the subscription status cache to hide the skip trial button if (teamIdNumber) { utils.viewer.teams.getSubscriptionStatus.invalidate({ teamId: teamIdNumber }); } }, onError: (error) => { showToast(error.message || t("error_skipping_trial"), "error"); }, }); const billingHref = teamIdNumber ? `/api/integrations/stripepayment/portal?teamId=${teamIdNumber}&returnTo=${WEBAPP_URL}${returnTo}` : `/api/integrations/stripepayment/portal?returnTo=${WEBAPP_URL}${returnTo}`; const onContactSupportClick = async () => { if (window.Support) { window.Support.open(); } }; const handleSkipTrial = () => { if (teamIdNumber) { skipTrialMutation.mutate({ teamId: teamIdNumber }); } }; const isTrialing = subscriptionStatus?.isTrialing && teamIdNumber; return ( <>

{t("manage_billing")}

{t("view_and_manage_billing_details")}

{isTrialing && (

{t("skip_trial")}

{t("skip_trial_description")}

)}

{t("need_help")}

{teamIdNumber && subscriptionStatus?.billingMode === "ACTIVE_USERS" && ( )}

{t("skip_trial_confirmation_description")}

); }; export default BillingView;