import dayjs from 'dayjs' import { ExternalLink } from 'lucide-react' import Link from 'next/link' import { usePathname } from 'next/navigation' import { Alert, AlertDescription, AlertTitle, Button, CriticalIcon, WarningIcon } from 'ui' import { PricingMetric } from '@/data/analytics/org-daily-stats-query' import { VIOLATION_TYPE_LABELS } from '@/data/usage/constants' import { useOrgUsageQuery } from '@/data/usage/org-usage-query' import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' import { DOCS_URL } from '@/lib/constants' export const Restriction = () => { const { data: org } = useSelectedOrganizationQuery() const { data: usage, isSuccess: isSuccessOrgUsage } = useOrgUsageQuery({ orgSlug: org?.slug }) const pathname = usePathname() const isUsagePage = pathname?.endsWith('/usage') const hasExceededAnyLimits = Boolean( usage?.usages.find( (metric) => metric.metric !== PricingMetric.DISK_SIZE_GB_HOURS_GP3 && !metric.unlimited && metric.capped && metric.usage > (metric?.pricing_free_units ?? 0) ) ) // don't show any alerts until everything has been fetched if (!isSuccessOrgUsage || !org) { return null } let shownAlert: 'exceededLimits' | 'gracePeriod' | 'gracePeriodOver' | 'restricted' | null = null if (hasExceededAnyLimits && !org?.restriction_status) { shownAlert = 'exceededLimits' } else if (org?.restriction_status === 'grace_period') { shownAlert = 'gracePeriod' } else if (org?.restriction_status === 'grace_period_over') { shownAlert = 'gracePeriodOver' } else if (org?.restriction_status === 'restricted') { shownAlert = 'restricted' } if (shownAlert === null || !org?.restriction_data) { return null } const violationLabels = Array.isArray(org.restriction_data['violations']) && org.restriction_data['violations'].length > 0 ? `(${org.restriction_data['violations'] .map((violation: string) => VIOLATION_TYPE_LABELS[violation] || violation) .join(', ')})` : '' return ( <> {shownAlert === 'exceededLimits' && ( Your organization's usage has exceeded its included quota

Your projects can become unresponsive or enter read-only mode.{' '} {org.plan.id === 'free' ? 'Please upgrade to the Pro Plan to ensure that your projects remain available.' : 'Please disable spend cap to ensure that your projects remain available.'}

{!isUsagePage && ( )}
)} {shownAlert === 'gracePeriod' && ( Your grace period has started.

Your organization went over its quota in the previous billing cycle {violationLabels && ` ${violationLabels}`}. You can continue with your projects until your grace period ends on{' '} {dayjs(org.restriction_data['grace_period_end']).format('DD MMM, YYYY')} . After that, the Fair Use Policy will apply. If you plan to maintain this level of usage, {org.plan.id === 'free' ? 'upgrade your plan' : 'disable spend cap'} to avoid any restrictions. If restrictions are applied, requests to your projects will return a 402 status code.

{!isUsagePage && ( )}
)} {shownAlert === 'gracePeriodOver' && ( Your grace period is over.

Your grace period ended on{' '} {dayjs(org.restriction_data['grace_period_end']).format('DD MMM, YYYY')} . Fair Use Policy applies now. Stay below your plan's quota or{' '} {org.plan.id === 'free' ? 'upgrade your plan' : 'disable spend cap'} if you expect to exceed it. If you exceed your quota, requests will respond with a 402 status code.

{!isUsagePage && ( )}
)} {shownAlert === 'restricted' && ( All services are restricted.

Fair Use Policy applies and your service is restricted. Your projects are not able to serve requests and will respond with a 402 status code. You have exceeded your plan's quota{violationLabels && ` ${violationLabels}`}.{' '} {org.plan.id === 'free' ? 'Upgrade your plan' : 'Disable spend cap'} to lift restrictions immediately, or wait until your quota refills at the start of your next billing period. Note that there may be a short delay after your billing period resets before restrictions are fully lifted.

{!isUsagePage && ( )}
)} ) }