@@ -2,13 +2,18 @@ import {
2
2
isJetpackPlan ,
3
3
isJetpackProduct ,
4
4
isMultiYearDomainProduct ,
5
+ isWpComPlan ,
5
6
} from '@automattic/calypso-products' ;
6
7
import { Gridicon } from '@automattic/components' ;
7
8
import { useTranslate } from 'i18n-calypso' ;
8
- import { FunctionComponent , useCallback , useEffect , useState } from 'react' ;
9
+ import { FunctionComponent , useCallback , useEffect , useMemo , useState } from 'react' ;
9
10
import isJetpackCheckout from 'calypso/lib/jetpack/is-jetpack-checkout' ;
11
+ import {
12
+ useStreamlinedPriceExperiment ,
13
+ isStreamlinedPriceDropdownTreatment ,
14
+ } from 'calypso/my-sites/plans-features-main/hooks/use-streamlined-price-experiment' ;
10
15
import { JetpackItemVariantDropDownPrice } from './jetpack-variant-dropdown-price' ;
11
- import { CurrentOption , Dropdown , OptionList , Option } from './styles' ;
16
+ import { CurrentOption , Dropdown , OptionList , Option , WPCheckoutCheckIcon } from './styles' ;
12
17
import { ItemVariantDropDownPrice } from './variant-dropdown-price' ;
13
18
import type { ItemVariationPickerProps , WPCOMProductVariant } from './types' ;
14
19
import type { ResponseCartProduct } from '@automattic/shopping-cart' ;
@@ -27,15 +32,32 @@ export const ItemVariationDropDown: FunctionComponent< ItemVariationPickerProps
27
32
} ) => {
28
33
const translate = useTranslate ( ) ;
29
34
const [ highlightedVariantIndex , setHighlightedVariantIndex ] = useState < number | null > ( null ) ;
35
+ const [ , streamlinedPriceExperimentAssignment ] = useStreamlinedPriceExperiment ( ) ;
36
+ const isStreamlinedPrice =
37
+ isStreamlinedPriceDropdownTreatment ( streamlinedPriceExperimentAssignment ) &&
38
+ isWpComPlan ( selectedItem . product_slug ) ;
39
+
40
+ const [ optimisticSelectedItem , setOptimisticSelectedItem ] = useState < string | null > ( null ) ;
41
+
42
+ useEffect ( ( ) => {
43
+ if ( isStreamlinedPrice ) {
44
+ setOptimisticSelectedItem ( selectedItem . product_slug ) ;
45
+ }
46
+ } , [ selectedItem . product_slug , isStreamlinedPrice ] ) ;
30
47
31
48
// Multi-year domain products must be compared by volume because they have the same product id.
32
- const selectedVariantIndexRaw = variants . findIndex ( ( variant ) =>
33
- isMultiYearDomainProduct ( selectedItem )
34
- ? selectedItem . volume === variant . volume
35
- : selectedItem . product_id === variant . productId
36
- ) ;
37
- // findIndex returns -1 if it fails and we want null.
38
- const selectedVariantIndex = selectedVariantIndexRaw > - 1 ? selectedVariantIndexRaw : null ;
49
+ const selectedVariantIndex = useMemo ( ( ) => {
50
+ const rawIndex = variants . findIndex ( ( variant ) => {
51
+ if ( isStreamlinedPrice && optimisticSelectedItem ) {
52
+ return variant . productSlug === optimisticSelectedItem ;
53
+ }
54
+ // If not optimistic, or optimisticSelectedItem is not set, use the original logic
55
+ return isMultiYearDomainProduct ( selectedItem )
56
+ ? selectedItem . volume === variant . volume && variant . productId === selectedItem . product_id
57
+ : selectedItem . product_id === variant . productId ;
58
+ } ) ;
59
+ return rawIndex > - 1 ? rawIndex : null ;
60
+ } , [ variants , isStreamlinedPrice , optimisticSelectedItem , selectedItem ] ) ;
39
61
40
62
// reset the dropdown highlight when the selected product changes
41
63
useEffect ( ( ) => {
@@ -45,10 +67,13 @@ export const ItemVariationDropDown: FunctionComponent< ItemVariationPickerProps
45
67
// wrapper around onChangeItemVariant to close up dropdown on change
46
68
const handleChange = useCallback (
47
69
( uuid : string , productSlug : string , productId : number , volume ?: number ) => {
70
+ if ( isStreamlinedPrice ) {
71
+ setOptimisticSelectedItem ( productSlug ) ;
72
+ }
48
73
onChangeItemVariant ( uuid , productSlug , productId , volume ) ;
49
74
toggle ( null ) ;
50
75
} ,
51
- [ onChangeItemVariant , toggle ]
76
+ [ onChangeItemVariant , toggle , isStreamlinedPrice ]
52
77
) ;
53
78
54
79
const selectNextVariant = useCallback ( ( ) => {
@@ -121,13 +146,22 @@ export const ItemVariationDropDown: FunctionComponent< ItemVariationPickerProps
121
146
return null ;
122
147
}
123
148
149
+ let compareTo = undefined ;
150
+ if ( isStreamlinedPrice ) {
151
+ compareTo = variants . find ( ( variant ) => variant . termIntervalInMonths === 1 ) ;
152
+ }
124
153
const ItemVariantDropDownPriceWrapper : FunctionComponent < { variant : WPCOMProductVariant } > = (
125
154
props
126
155
) =>
127
156
isJetpack ( props . variant ) ? (
128
157
< JetpackItemVariantDropDownPrice { ...props } allVariants = { variants } />
129
158
) : (
130
- < ItemVariantDropDownPrice { ...props } product = { selectedItem } />
159
+ < ItemVariantDropDownPrice
160
+ { ...props }
161
+ product = { selectedItem }
162
+ isStreamlinedPrice = { isStreamlinedPrice }
163
+ compareTo = { compareTo }
164
+ />
131
165
) ;
132
166
133
167
return (
@@ -143,6 +177,7 @@ export const ItemVariationDropDown: FunctionComponent< ItemVariationPickerProps
143
177
onClick = { ( ) => toggle ( id ) }
144
178
open = { isOpen }
145
179
role = "button"
180
+ detached = { isStreamlinedPrice }
146
181
>
147
182
{ selectedVariantIndex !== null ? (
148
183
< ItemVariantDropDownPriceWrapper variant = { variants [ selectedVariantIndex ] } />
@@ -157,6 +192,7 @@ export const ItemVariationDropDown: FunctionComponent< ItemVariationPickerProps
157
192
highlightedVariantIndex = { highlightedVariantIndex }
158
193
selectedItem = { selectedItem }
159
194
handleChange = { handleChange }
195
+ isStreamlinedPrice = { isStreamlinedPrice }
160
196
/>
161
197
) }
162
198
</ Dropdown >
@@ -168,15 +204,19 @@ function ItemVariantOptionList( {
168
204
highlightedVariantIndex,
169
205
selectedItem,
170
206
handleChange,
207
+ isStreamlinedPrice,
171
208
} : {
172
209
variants : WPCOMProductVariant [ ] ;
173
210
highlightedVariantIndex : number | null ;
174
211
selectedItem : ResponseCartProduct ;
175
212
handleChange : ( uuid : string , productSlug : string , productId : number , volume ?: number ) => void ;
213
+ isStreamlinedPrice : boolean ;
176
214
} ) {
177
- const compareTo = variants . find ( ( variant ) => variant . productId === selectedItem . product_id ) ;
215
+ const compareTo = isStreamlinedPrice
216
+ ? variants . find ( ( variant ) => variant . termIntervalInMonths === 1 )
217
+ : variants . find ( ( variant ) => variant . productId === selectedItem . product_id ) ;
178
218
return (
179
- < OptionList role = "listbox" tabIndex = { - 1 } >
219
+ < OptionList role = "listbox" tabIndex = { - 1 } detached = { isStreamlinedPrice } >
180
220
{ variants . map ( ( variant , index ) => (
181
221
< ItemVariantOption
182
222
key = { variant . productSlug + variant . variantLabel . noun }
@@ -193,6 +233,7 @@ function ItemVariantOptionList( {
193
233
variant = { variant }
194
234
allVariants = { variants }
195
235
selectedItem = { selectedItem }
236
+ isStreamlinedPrice = { isStreamlinedPrice }
196
237
/>
197
238
) ) }
198
239
</ OptionList >
@@ -206,13 +247,15 @@ function ItemVariantOption( {
206
247
variant,
207
248
allVariants,
208
249
selectedItem,
250
+ isStreamlinedPrice,
209
251
} : {
210
252
isSelected : boolean ;
211
253
onSelect : ( ) => void ;
212
254
compareTo ?: WPCOMProductVariant ;
213
255
variant : WPCOMProductVariant ;
214
256
allVariants : WPCOMProductVariant [ ] ;
215
257
selectedItem : ResponseCartProduct ;
258
+ isStreamlinedPrice : boolean ;
216
259
} ) {
217
260
const { variantLabel, productId, productSlug } = variant ;
218
261
return (
@@ -224,6 +267,7 @@ function ItemVariantOption( {
224
267
role = "option"
225
268
onClick = { onSelect }
226
269
selected = { isSelected }
270
+ detached = { isStreamlinedPrice }
227
271
>
228
272
{ isJetpack ( variant ) ? (
229
273
< JetpackItemVariantDropDownPrice variant = { variant } allVariants = { allVariants } />
@@ -232,8 +276,10 @@ function ItemVariantOption( {
232
276
variant = { variant }
233
277
compareTo = { compareTo }
234
278
product = { selectedItem }
279
+ isStreamlinedPrice = { isStreamlinedPrice }
235
280
/>
236
281
) }
282
+ { isStreamlinedPrice && isSelected && < WPCheckoutCheckIcon /> }
237
283
</ Option >
238
284
) ;
239
285
}
0 commit comments