import { CpuIcon, Lock, Microchip } from 'lucide-react' import { useMemo } from 'react' import { UseFormReturn } from 'react-hook-form' import { useParams } from 'common' import { DocsButton } from 'components/ui/DocsButton' import { InlineLink } from 'components/ui/InlineLink' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled' import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization' import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject' import { getCloudProviderArchitecture } from 'lib/cloudprovider-utils' import { DOCS_URL, InstanceSpecs } from 'lib/constants' import Link from 'next/link' import { cn, FormField_Shadcn_, RadioGroupCard, RadioGroupCardItem, Skeleton, Tooltip, TooltipContent, TooltipTrigger, } from 'ui' import { ComputeBadge } from 'ui-patterns' import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout' import { DiskStorageSchemaType } from '../DiskManagement.schema' import { ComputeInstanceAddonVariantId, InfraInstanceSize } from '../DiskManagement.types' import { calculateComputeSizePrice, getAvailableComputeOptions, showMicroUpgrade, } from '../DiskManagement.utils' import { BillingChangeBadge } from '../ui/BillingChangeBadge' import FormMessage from '../ui/FormMessage' import { NoticeBar } from '../ui/NoticeBar' /** * to do: this could be a type from api-types */ type ComputeOption = { identifier: ComputeInstanceAddonVariantId name: string price: number price_interval: 'monthly' | 'hourly' meta?: InstanceSpecs } type ComputeSizeFieldProps = { form: UseFormReturn disabled?: boolean } export function ComputeSizeField({ form, disabled }: ComputeSizeFieldProps) { const { ref } = useParams() const { data: org } = useSelectedOrganizationQuery() const { data: project, isLoading: isProjectLoading } = useSelectedProjectQuery() const showComputePrice = useIsFeatureEnabled('project_addons:show_compute_price') const { computeSize, storageType } = form.watch() const { data: addons, isLoading: isAddonsLoading, error: addonsError, } = useProjectAddonsQuery({ projectRef: ref }) const isLoading = isProjectLoading || isAddonsLoading const { control, formState, setValue, trigger } = form const availableAddons = useMemo(() => { return addons?.available_addons ?? [] }, [addons]) const availableOptions = useMemo(() => { /** * Returns the available compute options for the project * Also handles backwards compatibility for older API versions * Also handles a case in which Nano is not available from the API */ return getAvailableComputeOptions(availableAddons, project?.cloud_provider) }, [availableAddons, project?.cloud_provider]) const subscriptionPitr = addons?.selected_addons.find((addon) => addon.type === 'pitr') const computeSizePrice = calculateComputeSizePrice({ availableOptions: availableOptions, oldComputeSize: form.formState.defaultValues?.computeSize || 'ci_micro', newComputeSize: form.getValues('computeSize'), plan: org?.plan.id ?? 'free', }) const showUpgradeBadge = showMicroUpgrade( org?.plan.id ?? 'free', project?.infra_compute_size ?? 'nano' ) return ( ( { setValue('computeSize', value, { shouldDirty: true, shouldValidate: true, }) trigger('provisionedIOPS') trigger('throughput') }} defaultValue={field.value} disabled={disabled} >

Hardware resources allocated to your Postgres database

} >
{isLoading ? ( Array(10) .fill(0) .map((_, i) => ) ) : addonsError ? (

{addonsError?.message}

) : ( <> {availableOptions.map((compute: ComputeOption) => { const cpuArchitecture = getCloudProviderArchitecture(project?.cloud_provider) const lockedMicroDueToPITR = compute.identifier === 'ci_micro' && !!subscriptionPitr const lockedNanoDueToPlan = org?.plan.id !== 'free' && project?.infra_compute_size !== 'nano' && compute.identifier === 'ci_nano' const lockedOption = lockedNanoDueToPlan || lockedMicroDueToPITR const price = org?.plan.id !== 'free' && project?.infra_compute_size === 'nano' && compute.identifier === 'ci_nano' ? availableOptions.find( (option: ComputeOption) => option.identifier === 'ci_micro' )?.price : compute.price return (
{showUpgradeBadge && compute.identifier === 'ci_micro' && (
No additional charge
)}
{lockedOption ? (
) : ( showComputePrice && ( <> ${price} {' '} /{' '} {compute.price_interval === 'monthly' ? 'month' : 'hour'} ) )}
{compute.identifier === 'ci_nano' && 'Up to '} {compute.meta?.memory_gb ?? 0} GB memory
{compute.meta?.cpu_cores ?? 0} {compute.meta?.cpu_cores !== 'Shared' && `-core ${cpuArchitecture}`}{' '} CPU
{lockedMicroDueToPITR && ( Project has PITR enabled which requires a minimum of Small compute. Please{' '} disable PITR {' '} first before selecting Micro )} } /> ) })} e.preventDefault()} className={cn( 'relative text-sm text-left flex flex-col gap-0 px-0 py-3 [&_label]:w-full group] w-full h-[110px]' )} label={
Contact Us
Custom memory
Custom CPU
} /> )}
)} /> ) }