import { PermissionAction } from '@supabase/shared-types/out/constants' import dayjs from 'dayjs' import { Calendar, ExternalLink } from 'lucide-react' import { useTheme } from 'next-themes' import Image from 'next/image' import Link from 'next/link' import { useParams } from 'common' import { ScaffoldSection, ScaffoldSectionContent, ScaffoldSectionDetail, } from 'components/layouts/Scaffold' import AlertError from 'components/ui/AlertError' import NoPermission from 'components/ui/NoPermission' import ShimmeringLoader from 'components/ui/ShimmeringLoader' import { useOrganizationBillingSubscriptionCancelSchedule } from 'data/subscriptions/org-subscription-cancel-schedule-mutation' import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query' import { useCheckPermissions } from 'hooks/misc/useCheckPermissions' import { useFlag } from 'hooks/ui/useFlag' import { BASE_PATH } from 'lib/constants' import { useOrgSettingsPageStateSnapshot } from 'state/organization-settings' import { Alert, AlertDescription_Shadcn_, AlertTitle_Shadcn_, Alert_Shadcn_, Button } from 'ui' import ProjectUpdateDisabledTooltip from '../ProjectUpdateDisabledTooltip' import SpendCapSidePanel from './SpendCapSidePanel' export interface CostControlProps {} const CostControl = ({}: CostControlProps) => { const { slug } = useParams() const { resolvedTheme } = useTheme() const canReadSubscriptions = useCheckPermissions( PermissionAction.BILLING_READ, 'stripe.subscriptions' ) const snap = useOrgSettingsPageStateSnapshot() const projectUpdateDisabled = useFlag('disableProjectCreationAndUpdate') const { data: subscription, error, isLoading, isSuccess, isError, } = useOrgSubscriptionQuery({ orgSlug: slug }, { enabled: canReadSubscriptions }) const currentPlan = subscription?.plan const isUsageBillingEnabled = subscription?.usage_billing_enabled ?? false const canChangeTier = !projectUpdateDisabled && !['team', 'enterprise'].includes(currentPlan?.id || '') const { mutate: cancelSubscriptionSchedule, isLoading: cancelSubscriptionScheduleLoading } = useOrganizationBillingSubscriptionCancelSchedule() return ( <>

Cost Control

Control whether to use beyond your plans included quota

More information

Spend cap

{!canReadSubscriptions ? ( ) : ( <> {isLoading && (
)} {isError && } {isSuccess && (
{['team', 'enterprise'].includes(currentPlan?.id || '') ? ( {currentPlan?.name || ''} plan requires you to have spend cap off at all times. Your projects will never become unresponsive. Only when your{' '} included usage {' '} is exceeded will you be charged for any additional usage. ) : (

You can control whether your organization is charged for additional usage beyond the{' '} included quota {' '} of your subscription plan. If you need to go beyond the included quota, simply switch off your spend cap to pay for additional usage.

)} {/** Toggled on spend cap, scheduled change for end-of-cycle */} {subscription?.scheduled_plan_change?.target_plan === 'pro' && subscription?.scheduled_plan_change?.usage_billing_enabled === false && subscription?.plan.id === 'pro' && ( Scheduled change
Your spend cap will be enabled on{' '} {dayjs(subscription?.scheduled_plan_change?.at).format('MMMM D, YYYY')}. You will not be charged for any over-usage moving on. If you would like to keep the spend cap disabled and scale as you go, you may still cancel the scheduled change.
)}
Spend Cap

Spend cap is {isUsageBillingEnabled ? 'disabled' : 'enabled'}

{isUsageBillingEnabled ? ( You will be charged for any usage above the included quota. ) : ( You won't be charged any extra for usage. However, your projects could become unresponsive or enter read only mode if you exceed the included quota. )}

{isUsageBillingEnabled && (

Your projects will never become unresponsive. Only when your usage reaches the quota limit will you be charged for any excess usage.

)}
)} )}
) } export default CostControl