change upgrade comms

This commit is contained in:
Jonathan Summers-Muir committed 2024-11-01 01:14:09 +08:00
1 parent e2d3a306e3
commit b5fc1cd3ca
6 files changed
+111 -76

No files matched your search

@@ -49,6 +49,7 @@ export const calculateComputeSizePrice = ({
availableOptions,
oldComputeSize,
newComputeSize,
plan,
}: {
availableOptions: {
identifier: string
@@ -56,8 +57,19 @@ export const calculateComputeSizePrice = ({
}[]
oldComputeSize: string
newComputeSize: string
plan: PlanId
}) => {
const oldPrice = availableOptions?.find((x) => x.identifier === oldComputeSize)?.price ?? 0
let _oldComputeSize = oldComputeSize
if (plan !== 'free') {
/**
* override the old compute size to micro if the plan is not free
* this is to handle the case in which nano compute is a paid entity
*/
_oldComputeSize = 'ci_micro'
}
const oldPrice = availableOptions?.find((x) => x.identifier === _oldComputeSize)?.price ?? 0
const newPrice = availableOptions?.find((x) => x.identifier === newComputeSize)?.price ?? 0
const oldPriceMonthly = oldPrice * 720
@@ -90,14 +90,14 @@ export function DiskManagementForm() {
*/
const {
data: databases,
isLoading: isReadReplicasLoading,
error: readReplicasError,
// isLoading: isReadReplicasLoading,
// error: readReplicasError,
isSuccess: isReadReplicasSuccess,
} = useReadReplicasQuery({ projectRef })
const {
data,
isLoading: isDiskAttributesLoading,
error: diskAttributesError,
// isLoading: isDiskAttributesLoading,
// error: diskAttributesError,
isSuccess: isDiskAttributesSuccess,
} = useDiskAttributesQuery(
{ projectRef },
@@ -125,28 +125,28 @@ export function DiskManagementForm() {
}
)
const {
isLoading: isAddonsLoading,
error: addonsError,
// isLoading: isAddonsLoading,
// error: addonsError,
isSuccess: isAddonsSuccess,
} = useProjectAddonsQuery({ projectRef })
const {
isWithinCooldownWindow,
isLoading: isCooldownLoading,
// isLoading: isCooldownLoading,
isSuccess: isCooldownSuccess,
} = useRemainingDurationForDiskAttributeUpdate({
projectRef,
})
const {
isLoading: isDiskUtilizationLoading,
error: diskUtilError,
// isLoading: isDiskUtilizationLoading,
// error: diskUtilError,
isSuccess: isDiskUtilizationSuccess,
} = useDiskUtilizationQuery({
projectRef,
})
const {
data: subscription,
isLoading: isSubscriptionLoading,
error: subscriptionError,
// isLoading: isSubscriptionLoading,
// error: subscriptionError,
isSuccess: isSubscriptionSuccess,
} = useOrgSubscriptionQuery({
orgSlug: org?.slug,
@@ -214,12 +214,12 @@ export function DiskManagementForm() {
const { mutateAsync: updateDiskConfiguration, isLoading: isUpdatingDisk } =
useUpdateDiskAttributesMutation({
// this is to supress to toast message
// this is to suppress to toast message
onError: () => {},
})
const { mutateAsync: updateSubscriptionAddon, isLoading: isUpdatingCompute } =
useProjectAddonUpdateMutation({
// this is to supress to toast message
// this is to suppress to toast message
onError: () => {},
onSuccess: () => {
/**
@@ -1,6 +1,6 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { ChevronRight } from 'lucide-react'
import { useMemo } from 'react'
import { ComponentProps, useMemo } from 'react'
import { UseFormReturn } from 'react-hook-form'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
@@ -39,11 +39,13 @@ import {
calculateThroughputPrice,
getAvailableComputeOptions,
mapAddOnVariantIdToComputeSize,
showMicroUpgrade,
} from './DiskManagement.utils'
import { DiskMangementRestartRequiredSection } from './DiskManagementRestartRequiredSection'
import { BillingChangeBadge } from './ui/BillingChangeBadge'
import { DiskType } from './ui/DiskManagement.constants'
import { DiskMangementCoolDownSection } from './ui/DiskManagementCoolDownSection'
import { InfraInstanceSize } from './DiskManagement.types'
const TableHeaderRow = () => (
<TableRow>
@@ -63,6 +65,7 @@ interface TableDataRowProps {
afterPrice: number
hidePrice?: boolean
priceTooltip?: string
upgradeIncluded?: boolean
}
const TableDataRow = ({
@@ -74,6 +77,7 @@ const TableDataRow = ({
afterPrice,
hidePrice = false,
priceTooltip,
upgradeIncluded = false,
}: TableDataRowProps) => (
<TableRow>
<TableCell className="pl-5">
@@ -101,14 +105,15 @@ const TableDataRow = ({
</TableCell>
<TableCell className="text-xs font-mono">{unit}</TableCell>
<TableCell className="text-right pr-5">
{hidePrice ? (
{!upgradeIncluded && hidePrice ? (
<span className="text-xs font-mono">-</span>
) : beforePrice !== afterPrice ? (
) : beforePrice !== afterPrice || upgradeIncluded ? (
<BillingChangeBadge
show={true}
beforePrice={beforePrice}
afterPrice={afterPrice}
tooltip={priceTooltip}
free={upgradeIncluded}
/>
) : (
<span className="text-xs font-mono">{formatCurrency(beforePrice)}</span>
@@ -179,6 +184,7 @@ export const DiskManagementReviewAndSubmitDialog = ({
availableOptions,
oldComputeSize: form.formState.defaultValues?.computeSize || 'ci_micro',
newComputeSize: form.getValues('computeSize'),
plan: subscription?.plan.id ?? 'free',
})
const diskSizePrice = calculateDiskSizePrice({
planId: planId,
@@ -265,6 +271,7 @@ export const DiskManagementReviewAndSubmitDialog = ({
unit="-"
beforePrice={Number(computeSizePrice.oldPrice)}
afterPrice={Number(computeSizePrice.newPrice)}
upgradeIncluded={true}
/>
)}
{form.formState.defaultValues?.storageType !== form.getValues('storageType') && (
@@ -93,6 +93,7 @@ export function ComputeSizeField({ form, disabled }: ComputeSizeFieldProps) {
availableOptions: availableOptions,
oldComputeSize: form.formState.defaultValues?.computeSize || 'ci_micro',
newComputeSize: form.getValues('computeSize'),
plan: subscription?.plan.id ?? 'free',
})
const showUpgradeBadge = showMicroUpgrade(
@@ -127,10 +128,10 @@ export function ComputeSizeField({ form, disabled }: ComputeSizeFieldProps) {
<NoticeBar
showIcon={false}
type="default"
className="mt-3"
visible={showUpgradeBadge && form.watch('computeSize') !== 'ci_micro'}
title="Free Compute upgrade to Micro"
description="Paid Plans include a free upgrade to Micro compute."
className="mt-3 border-violet-900 bg-violet-200 [&_h5]:text-violet-1100"
visible={showUpgradeBadge && form.watch('computeSize') === 'ci_nano'}
title={'Upgrade to Micro Compute at no additional charge'}
description="This Project is already paying for Micro Compute. You can upgrade to Micro Compute at any time when convenient."
/>
</>
}
@@ -166,72 +167,84 @@ export function ComputeSizeField({ form, disabled }: ComputeSizeFieldProps) {
project?.infra_compute_size !== 'nano' &&
compute.identifier === 'ci_nano'
const price =
subscription?.plan.id !== 'free' &&
project?.infra_compute_size === 'nano' &&
compute.identifier === 'ci_nano'
? availableOptions.find(
(option: ComputeOption) => option.identifier === 'ci_micro'
)?.price
: compute.price
return (
<RadioGroupCardItem
key={compute.identifier}
showIndicator={false}
value={compute.identifier}
className={cn(
'text-sm text-left flex flex-col gap-0 px-0 py-3 overflow-hidden [&_label]:w-full group] w-full h-[110px]',
'relative text-sm text-left flex flex-col gap-0 px-0 py-3 [&_label]:w-full group] w-full h-[110px]',
lockedOption && 'opacity-50'
)}
disabled={disabled || lockedOption}
// @ts-expect-error
label={
<div className="w-full flex flex-col gap-3 justify-between">
<div className="px-3 opacity-50 group-data-[state=checked]:opacity-100 flex justify-between">
<ComputeBadge
className="inline-flex font-semibold"
infraComputeSize={
compute.name as components['schemas']['DbInstanceSize']
}
/>
<div className="flex items-center space-x-1">
{lockedOption ? (
<div className="bg border rounded-lg h-7 w-7 flex items-center justify-center">
<Lock size={14} />
</div>
) : showUpgradeBadge && compute.identifier === 'ci_micro' ? (
<div className="w-full text-warning-600 flex items-center gap-1 bg-warning-200 py-0.5 px-2 rounded-full border border-warning-500">
<span className="font-mono">FREE UPGRADE</span>
</div>
) : (
<>
<span className="text-foreground text-sm font-semibold">
${compute.price}
</span>
<span className="text-foreground-light translate-y-[1px]">
{' '}
/ {compute.price_interval === 'monthly' ? 'month' : 'hour'}
</span>
</>
)}
<>
{showUpgradeBadge && compute.identifier === 'ci_micro' && (
<div className="absolute -top-4 -right-3 text-violet-1100 flex items-center gap-1 bg-surface-75 py-0.5 px-2 rounded-full border border-violet-900">
<span>No additional charge</span>
</div>
)}
<div className="w-full flex flex-col gap-3 justify-between">
<div className="relative px-3 opacity-50 group-data-[state=checked]:opacity-100 flex justify-between">
<ComputeBadge
className="inline-flex font-semibold"
infraComputeSize={
compute.name as components['schemas']['DbInstanceSize']
}
/>
<div className="flex items-center space-x-1">
{lockedOption ? (
<div className="bg border rounded-lg h-7 w-7 flex items-center justify-center">
<Lock size={14} />
</div>
) : (
<>
<span className="text-foreground text-sm font-semibold">
${price}
</span>
<span className="text-foreground-light translate-y-[1px]">
{' '}
/ {compute.price_interval === 'monthly' ? 'month' : 'hour'}
</span>
</>
)}
</div>
</div>
</div>
<div className="w-full">
<div className="px-3 text-sm flex flex-col gap-1">
<div className="text-foreground-light flex gap-2 items-center">
<Microchip
strokeWidth={1}
size={14}
className="text-foreground-lighter"
/>
<span>{compute.meta?.memory_gb ?? 0} GB memory</span>
</div>
<div className="text-foreground-light flex gap-2 items-center">
<CpuIcon
strokeWidth={1}
size={14}
className="text-foreground-lighter"
/>
<span>
{compute.meta?.cpu_cores ?? 0}-core {cpuArchitecture} CPU
</span>
<div className="w-full">
<div className="px-3 text-sm flex flex-col gap-1">
<div className="text-foreground-light flex gap-2 items-center">
<Microchip
strokeWidth={1}
size={14}
className="text-foreground-lighter"
/>
<span>{compute.meta?.memory_gb ?? 0} GB memory</span>
</div>
<div className="text-foreground-light flex gap-2 items-center">
<CpuIcon
strokeWidth={1}
size={14}
className="text-foreground-lighter"
/>
<span>
{compute.meta?.cpu_cores ?? 0}-core {cpuArchitecture} CPU
</span>
</div>
</div>
</div>
</div>
</div>
</>
}
/>
)
@@ -36,8 +36,8 @@ const BillingChangeBadge = ({
<Badge
variant="default"
className={cn(
!free ? `bg-alternative` : `bg-warning-200 border-warning-500 text-warning`,
`bg-opacity-100`,
!free ? `bg-alternative` : `bg-violet-200 border-violet-900 text-violet-1100`,
`bg-opacity-100 text-warning`,
className
)}
>
@@ -50,11 +50,14 @@ const BillingChangeBadge = ({
<ChevronRight size={12} strokeWidth={2} className="text-foreground-muted" />
<motion.span
key={afterPrice} // This key will change whenever any form value changes
className="text-xs font-mono text-foreground"
className={cn(
free ? 'text-violet-1100' : 'text-foreground',
'text-xs font-mono'
)}
animate={{ scale: [1, 1.1, 1] }}
transition={{ duration: 0.12 }}
>
{free ? 'Free' : `${formatCurrency(afterPrice)}/month`}
{`${formatCurrency(afterPrice)}/month`}
</motion.span>
</div>
</TooltipTrigger_Shadcn_>
@@ -233,7 +233,7 @@ const Addons = () => {
</div>
)}
{!diskAndComputeFormEnabled ? (
{true ? (
<ProjectUpdateDisabledTooltip
projectUpdateDisabled={projectUpdateDisabled || computeSizeChangesDisabled}
projectNotActive={!isProjectActive}