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 (
{isLoading && (
)} {isError && } {isSuccess && ( <> {!usageMeta || usageMeta?.available_in_plan ? ( <> {!projectRef && (

{attribute.name} usage

{showUsageWarning && ( {usageRatio >= 1 ? (

Exceeded limit

) : ( usageRatio >= USAGE_APPROACHING_THRESHOLD && (

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.

)}
{currentBillingCycleSelected && usageMeta && !usageMeta.unlimited && ( = 1 ? usageBasedBilling ? 'bg-foreground-light' : 'bg-red-900' : usageBasedBilling === false && usageRatio >= USAGE_APPROACHING_THRESHOLD ? 'bg-amber-900' : 'bg-foreground-light' )} bgClass="bg-surface-300" value={usageMeta?.usage ?? 0} max={usageMeta?.pricing_free_units || 1} /> )}
{usageMeta && usageMeta.pricing_free_units !== 0 && (

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()}

)}
)} {currentBillingCycleSelected && usageMeta && (

{attribute.chartPrefix || 'Used '} in period

{attribute.unit === 'bytes' || attribute.unit === 'gigabytes' ? `${(usageMeta?.usage ?? 0).toFixed(2)} GB` : (usageMeta?.usage ?? 0).toLocaleString()}

)} {currentBillingCycleSelected && (usageMeta?.pricing_free_units ?? 0) > 0 && (

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.additionalInfo?.(usage)}

{attribute.chartPrefix || ''} {attribute.name}{' '} {attribute.chartSuffix || 'per day'}

{attribute.chartDescription.split('\n').map((paragraph, idx) => (

{paragraph}

))}
{chartMeta[attribute.key].isLoading ? (
) : chartData.length > 0 && notAllValuesZero ? ( ChartYFormatterCompactNumber(value, attribute.unit)} tooltipFormatter={(value) => ChartTooltipValueFormatter(value, attribute.unit)} /> ) : (

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.

)} )}
) } export default AttributeUsage