DiskManagementReviewAndSubmitDialog.hooks.ts186 lines · main
1import { useMemo } from 'react'
2import { UseFormReturn } from 'react-hook-form'
3
4import { DiskStorageSchemaType } from '../DiskManagement.schema'
5import {
6 calculateComputeSizePrice,
7 calculateDiskSizePrice,
8 calculateIOPSPrice,
9 calculateThroughputPrice,
10 getAvailableComputeOptions,
11 mapAddOnVariantIdToComputeSize,
12} from '../DiskManagement.utils'
13import { DiskType } from '../ui/DiskManagement.constants'
14import { useProjectAddonsQuery } from '@/data/subscriptions/project-addons-query'
15import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
16import {
17 useIsAwsNimbusCloudProvider,
18 useSelectedProjectQuery,
19} from '@/hooks/misc/useSelectedProject'
20
21export function useDiskManagementReviewChanges(
22 form: UseFormReturn<DiskStorageSchemaType>,
23 numReplicas: number
24) {
25 const { data: project } = useSelectedProjectQuery()
26 const { data: org } = useSelectedOrganizationQuery()
27 const isAwsNimbus = useIsAwsNimbusCloudProvider()
28 const { data: addons } = useProjectAddonsQuery({ projectRef: project?.ref })
29
30 const isAwsK8sProject = project?.cloud_provider === 'AWS_K8S'
31 const planId = org?.plan.id ?? 'free'
32
33 const availableAddons = useMemo(() => addons?.available_addons ?? [], [addons])
34 const availableOptions = useMemo(
35 () => getAvailableComputeOptions(availableAddons, project?.cloud_provider),
36 [availableAddons, project?.cloud_provider]
37 )
38
39 // --- Prices ---
40
41 const computeSizePrice = calculateComputeSizePrice({
42 availableOptions,
43 oldComputeSize: form.formState.defaultValues?.computeSize || 'ci_micro',
44 newComputeSize: form.getValues('computeSize'),
45 plan: planId,
46 })
47 const diskSizePrice = calculateDiskSizePrice({
48 planId,
49 oldSize: form.formState.defaultValues?.totalSize || 0,
50 oldStorageType: form.formState.defaultValues?.storageType as DiskType,
51 newSize: form.getValues('totalSize'),
52 newStorageType: form.getValues('storageType') as DiskType,
53 numReplicas,
54 })
55 const iopsPrice = calculateIOPSPrice({
56 oldStorageType: form.formState.defaultValues?.storageType as DiskType,
57 oldProvisionedIOPS: form.formState.defaultValues?.provisionedIOPS || 0,
58 newStorageType: form.getValues('storageType') as DiskType,
59 newProvisionedIOPS: form.getValues('provisionedIOPS'),
60 numReplicas,
61 })
62 const throughputPrice = calculateThroughputPrice({
63 storageType: form.getValues('storageType') as DiskType,
64 newThroughput: form.getValues('throughput') || 0,
65 oldThroughput: form.formState.defaultValues?.throughput || 0,
66 numReplicas,
67 })
68
69 const totalBeforePrice =
70 Number(computeSizePrice.oldPrice) +
71 Number(diskSizePrice.oldPrice) +
72 Number(iopsPrice.oldPrice) +
73 Number(throughputPrice.oldPrice)
74
75 const totalAfterPrice =
76 Number(computeSizePrice.newPrice) +
77 Number(diskSizePrice.newPrice) +
78 Number(iopsPrice.newPrice) +
79 Number(throughputPrice.newPrice)
80
81 // --- Change flags ---
82
83 const hasComputeChanges =
84 form.formState.defaultValues?.computeSize !== form.getValues('computeSize')
85
86 const hasTotalSizeChanges =
87 !isAwsK8sProject &&
88 !isAwsNimbus &&
89 form.formState.defaultValues?.totalSize !== form.getValues('totalSize')
90
91 const hasStorageTypeChanges =
92 !isAwsK8sProject &&
93 !isAwsNimbus &&
94 form.formState.defaultValues?.storageType !== form.getValues('storageType')
95
96 const hasThroughputChanges =
97 !isAwsK8sProject &&
98 !isAwsNimbus &&
99 form.formState.defaultValues?.throughput !== form.getValues('throughput')
100
101 const hasIOPSChanges =
102 !isAwsK8sProject &&
103 !isAwsNimbus &&
104 form.formState.defaultValues?.provisionedIOPS !== form.getValues('provisionedIOPS')
105
106 const hasGrowthPercentChanges =
107 !isAwsK8sProject &&
108 !isAwsNimbus &&
109 form.formState.defaultValues?.growthPercent !== form.getValues('growthPercent')
110
111 const hasMinIncrementChanges =
112 !isAwsK8sProject &&
113 !isAwsNimbus &&
114 form.formState.defaultValues?.minIncrementGb !== form.getValues('minIncrementGb')
115
116 const hasMaxSizeChanges =
117 !isAwsK8sProject &&
118 !isAwsNimbus &&
119 form.formState.defaultValues?.maxSizeGb !== form.getValues('maxSizeGb')
120
121 // --- Derived predicates ---
122
123 const storageTypeBefore = (form.formState.defaultValues?.storageType ?? '') as DiskType
124 const storageTypeAfter = form.getValues('storageType') as DiskType
125
126 // Show hero whenever any line-item price actually changes, not just compute
127 const anyBillableDiskChange =
128 Number(diskSizePrice.newPrice) !== Number(diskSizePrice.oldPrice) ||
129 Number(iopsPrice.newPrice) !== Number(iopsPrice.oldPrice) ||
130 Number(throughputPrice.newPrice) !== Number(throughputPrice.oldPrice)
131
132 // Show cooldown warning whenever any disk attribute that enforces the 4-hour lock changes
133 const anyDiskAttributeChange = hasIOPSChanges || hasStorageTypeChanges || hasTotalSizeChanges
134
135 // Show throughput row whenever either the before or after storage type is GP3
136 // (covers GP3→IO2 where the throughput charge drops to zero)
137 const showThroughputRow =
138 !isAwsK8sProject &&
139 !isAwsNimbus &&
140 (storageTypeBefore === 'gp3' || storageTypeAfter === 'gp3') &&
141 (hasThroughputChanges || hasStorageTypeChanges)
142
143 const hasAnyBreakdownRows =
144 hasComputeChanges ||
145 hasStorageTypeChanges ||
146 hasIOPSChanges ||
147 showThroughputRow ||
148 hasTotalSizeChanges ||
149 hasGrowthPercentChanges ||
150 hasMinIncrementChanges ||
151 hasMaxSizeChanges
152
153 // --- Labels ---
154
155 const oldComputeLabel = mapAddOnVariantIdToComputeSize(
156 form.formState.defaultValues?.computeSize ?? 'ci_nano'
157 )
158 const newComputeLabel = mapAddOnVariantIdToComputeSize(form.getValues('computeSize'))
159
160 return {
161 // prices
162 computeSizePrice,
163 diskSizePrice,
164 iopsPrice,
165 throughputPrice,
166 totalBeforePrice,
167 totalAfterPrice,
168 // change flags
169 hasComputeChanges,
170 hasTotalSizeChanges,
171 hasStorageTypeChanges,
172 hasThroughputChanges,
173 hasIOPSChanges,
174 hasGrowthPercentChanges,
175 hasMinIncrementChanges,
176 hasMaxSizeChanges,
177 // derived predicates
178 anyBillableDiskChange,
179 anyDiskAttributeChange,
180 showThroughputRow,
181 hasAnyBreakdownRows,
182 // labels
183 oldComputeLabel,
184 newComputeLabel,
185 }
186}