import { AlertTriangle, BarChart2 } from 'lucide-react' import Link from 'next/link' import { useMemo } from 'react' import { Button, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui' import { ShimmeringLoader } from 'ui-patterns/ShimmeringLoader' import { SectionContent } from '../SectionContent' import { CategoryAttribute } from '../Usage.constants' import { ChartTooltipValueFormatter, ChartYFormatterCompactNumber, useGetUpgradeUrl, } from '../Usage.utils' import UsageBarChart from '../UsageBarChart' import { ChartMeta } from './UsageSection' import AlertError from '@/components/ui/AlertError' import Panel from '@/components/ui/Panel' import SparkBar from '@/components/ui/SparkBar' import type { OrgSubscription } from '@/data/subscriptions/types' import type { OrgMetricsUsage, OrgUsageResponse } from '@/data/usage/org-usage-query' import { USAGE_APPROACHING_THRESHOLD } from '@/lib/constants' import type { ResponseError } from '@/types' export interface AttributeUsageProps { slug: string projectRef?: string | null attribute: CategoryAttribute usage?: OrgUsageResponse usageMeta?: OrgMetricsUsage chartMeta: ChartMeta subscription?: OrgSubscription error: ResponseError | null isLoading: boolean isError: boolean isSuccess: boolean currentBillingCycleSelected: boolean } const AttributeUsage = ({ slug, projectRef, attribute, usage, usageMeta, chartMeta, subscription, error, isLoading, isError, isSuccess, currentBillingCycleSelected, }: AttributeUsageProps) => { const upgradeUrl = useGetUpgradeUrl(slug ?? '', subscription, attribute.key) const usageRatio = (usageMeta?.usage ?? 0) / (usageMeta?.pricing_free_units ?? 0) const usageExcess = (usageMeta?.usage ?? 0) - (usageMeta?.pricing_free_units ?? 0) const usageBasedBilling = subscription?.usage_billing_enabled const exceededLimitStyle = !usageBasedBilling ? 'text-red-900' : 'text-amber-900' const chartData = useMemo(() => chartMeta[attribute.key]?.data ?? [], [attribute.key, chartMeta]) const showUsageWarning = projectRef === undefined && currentBillingCycleSelected && usageBasedBilling === false && usageRatio >= USAGE_APPROACHING_THRESHOLD const notAllValuesZero = useMemo(() => { return ( attribute.attributes ?.map((attr) => { return chartData.some((dataPoint) => Number(dataPoint[attr.key]) !== 0) }) .some((x) => !!x) ?? false ) }, [attribute.attributes, chartData]) return (
{attribute.name} usage
{showUsageWarning && (Exceeded limit
Approaching limit
Exceeding your plans included usage will lead to restrictions to your project.
Upgrade to a usage-based plan or disable the spend cap to avoid restrictions.
Included in {subscription?.plan?.name} Plan
{usageMeta.unlimited ? (Unlimited
) : ({attribute.unit === 'bytes' || attribute.unit === 'gigabytes' ? `${usageMeta.pricing_free_units ?? 0} GB` : (usageMeta.pricing_free_units ?? 0).toLocaleString()}
)}{attribute.chartPrefix || 'Used '} in period
{attribute.unit === 'bytes' || attribute.unit === 'gigabytes' ? `${(usageMeta?.usage ?? 0).toFixed(2)} GB` : (usageMeta?.usage ?? 0).toLocaleString()}
Overage in period
{(usageMeta?.pricing_free_units ?? 0) === -1 || usageExcess < 0 ? `0${attribute.unit === 'bytes' || attribute.unit === 'gigabytes' ? ' GB' : ''}` : attribute.unit === 'bytes' || attribute.unit === 'gigabytes' ? `${usageExcess.toFixed(2)} GB` : usageExcess.toLocaleString()}
{attribute.chartPrefix || ''} {attribute.name}{' '} {attribute.chartSuffix || 'per day'}
{attribute.chartDescription.split('\n').map((paragraph, idx) => ({paragraph}
))}No data in period
May take up to 24 hours to show
Not included in plan
You need to be on a higher plan in order to use this feature.