1- import React , { useCallback , useEffect , useMemo , useState } from 'react'
1+ import React , { useCallback , useMemo } from 'react'
22
33import classnames from 'classnames'
44import type { FreeTierOverride , PlanState } from '#/account/plans/plan.component'
55import styles from '#/account/plans/plan.module.scss'
66import { PlanButton } from '#/account/plans/planButton.component'
77import { useDisplayPrice } from '#/account/plans/useDisplayPrice.hook'
88import type { Price , SinglePricedProduct , SubscriptionInfo } from '#/account/stripe.types'
9- import {
10- getAdjustedQuantityForPrice ,
11- getSubscriptionsForProductId ,
12- isChangeScheduled ,
13- isDowngrade ,
14- } from '#/account/stripe.utils'
9+ import { getSubscriptionsForProductId , isChangeScheduled , isDowngrade } from '#/account/stripe.utils'
1510import Icon from '#/components/common/icon'
16- import KoboSelect , { type KoboSelectOption } from '#/components/common/koboSelect'
1711import { recordKeys } from '#/utils'
1812
1913interface PlanContainerProps {
2014 product : SinglePricedProduct
2115 isDisabled : boolean
22- isSubscribedProduct : ( product : SinglePricedProduct , quantity : number ) => boolean
16+ isSubscribedProduct : ( product : SinglePricedProduct ) => boolean
2317 freeTierOverride : FreeTierOverride | null
2418 expandComparison : boolean
2519 state : PlanState
2620 filteredPriceProducts : SinglePricedProduct [ ]
2721 setIsBusy : ( isBusy : boolean ) => void
2822 hasManageableStatus : ( sub : SubscriptionInfo ) => boolean
29- buySubscription : ( price : Price , quantity ?: number ) => void
23+ buySubscription : ( price : Price ) => void
3024 activeSubscriptions : SubscriptionInfo [ ]
3125}
3226
@@ -43,9 +37,8 @@ export const PlanContainer = ({
4337 buySubscription,
4438 activeSubscriptions,
4539} : PlanContainerProps ) => {
46- const [ submissionQuantity , setSubmissionQuantity ] = useState ( 1 )
47- // display price for the plan/price/quantity we're currently displaying
48- const displayPrice = useDisplayPrice ( product . price , submissionQuantity )
40+ // display price for the plan/price we're currently displaying
41+ const displayPrice = useDisplayPrice ( product . price )
4942 const shouldShowManage = useCallback (
5043 ( product : SinglePricedProduct ) => {
5144 const subscriptions = getSubscriptionsForProductId ( product . id , state . subscribedProduct )
@@ -65,34 +58,7 @@ export const PlanContainer = ({
6558 [ hasManageableStatus , state . subscribedProduct ] ,
6659 )
6760
68- const isDowngrading = useMemo (
69- ( ) => isDowngrade ( activeSubscriptions , product . price , submissionQuantity ) ,
70- [ activeSubscriptions , product , submissionQuantity ] ,
71- )
72-
73- // The adjusted quantity is the number we multiply the price by to get the total price
74- const adjustedQuantity = useMemo (
75- ( ) => getAdjustedQuantityForPrice ( submissionQuantity , product . price . transform_quantity ) ,
76- [ product , submissionQuantity ] ,
77- )
78-
79- // Populate submission dropdown with the submission quantity from the customer's plan
80- // Default to this price's base submission quantity, if applicable
81- useEffect ( ( ) => {
82- const subscribedQuantity = activeSubscriptions . length && activeSubscriptions ?. [ 0 ] . items [ 0 ] . quantity
83- if ( subscribedQuantity && isSubscribedProduct ( product , subscribedQuantity ) ) {
84- setSubmissionQuantity ( subscribedQuantity )
85- } else if (
86- // if there's no active subscription, check if this price has a default quantity
87- product . price . transform_quantity &&
88- Boolean ( Number ( product . metadata ?. submission_limit ) || Number ( product . price . metadata ?. submission_limit ) )
89- ) {
90- // prioritize the submission limit from the price over the submission limit from the product
91- setSubmissionQuantity (
92- Number . parseInt ( product . price . metadata . submission_limit ) || Number . parseInt ( product . metadata . submission_limit ) ,
93- )
94- }
95- } , [ isSubscribedProduct , activeSubscriptions , product ] )
61+ const isDowngrading = useMemo ( ( ) => isDowngrade ( activeSubscriptions , product . price ) , [ activeSubscriptions , product ] )
9662
9763 const getFeatureMetadata = ( product : SinglePricedProduct , featureItem : string ) => {
9864 if ( product . price . unit_amount === 0 && freeTierOverride && freeTierOverride . hasOwnProperty ( featureItem ) ) {
@@ -171,57 +137,12 @@ export const PlanContainer = ({
171137 return renderFeaturesList ( items , featureTitle )
172138 }
173139
174- const submissionOptions = useMemo ( ( ) : KoboSelectOption [ ] => {
175- const options = [ ]
176- const submissionsPerUnit = product . price . metadata ?. submission_limit || product . metadata ?. submission_limit
177- const maxPlanQuantity = Number . parseInt ( product . price . metadata ?. max_purchase_quantity || '1' )
178- if ( submissionsPerUnit ) {
179- for ( let i = 1 ; i <= maxPlanQuantity ; i ++ ) {
180- const submissionCount = Number . parseInt ( submissionsPerUnit ) * i
181- options . push ( {
182- label : '##submissions## submissions /month' . replace ( '##submissions##' , submissionCount . toLocaleString ( ) ) ,
183- value : submissionCount . toString ( ) ,
184- } )
185- }
186- }
187- return options
188- } , [ product ] )
189-
190- const onSubmissionsChange = ( value : string | null ) => {
191- if ( value === null ) {
192- return
193- }
194- const submissions = Number . parseInt ( value )
195- if ( submissions ) {
196- setSubmissionQuantity ( submissions )
197- }
198- }
199-
200- const asrMinutes = useMemo (
201- ( ) =>
202- ( adjustedQuantity *
203- ( Number . parseInt ( product . metadata ?. asr_seconds_limit || '0' ) ||
204- Number . parseInt ( product . price . metadata ?. asr_seconds_limit || '0' ) ) ) /
205- 60 ,
206- [ adjustedQuantity , product ] ,
207- )
208-
209- const mtCharacters = useMemo (
210- ( ) =>
211- adjustedQuantity *
212- ( Number . parseInt ( product . metadata ?. mt_characters_limit || '0' ) ||
213- Number . parseInt ( product . price . metadata ?. mt_characters_limit || '0' ) ) ,
214- [ adjustedQuantity , product ] ,
215- )
216-
217140 return (
218141 < >
219- { isSubscribedProduct ( product , submissionQuantity ) ? (
220- < div className = { styles . currentPlan } > { t ( 'Your plan' ) } </ div >
221- ) : null }
142+ { isSubscribedProduct ( product ) ? < div className = { styles . currentPlan } > { t ( 'Your plan' ) } </ div > : null }
222143 < div
223144 className = { classnames ( {
224- [ styles . planContainerWithBadge ] : isSubscribedProduct ( product , submissionQuantity ) ,
145+ [ styles . planContainerWithBadge ] : isSubscribedProduct ( product ) ,
225146 [ styles . planContainer ] : true ,
226147 } ) }
227148 >
@@ -231,37 +152,6 @@ export const PlanContainer = ({
231152 </ h1 >
232153 < div className = { styles . priceTitle } > { displayPrice } </ div >
233154 < ul className = { styles . featureContainer } >
234- { product . price . transform_quantity && (
235- < >
236- < li className = { styles . selectableFeature } >
237- < Icon name = 'check' size = 'm' color = 'teal' />
238- < KoboSelect
239- name = { t ( 'Total Submissions per Month' ) }
240- options = { submissionOptions }
241- size = { 's' }
242- type = { 'outline' }
243- onChange = { onSubmissionsChange }
244- selectedOption = { submissionQuantity . toString ( ) }
245- />
246- </ li >
247- < li >
248- < div className = { styles . iconContainer } >
249- < Icon name = 'check' size = 'm' color = { product . price . unit_amount ? 'teal' : 'storm' } />
250- </ div >
251- { t ( '##asr_minutes## minutes of automated transcription /##plan_interval##' )
252- . replace ( '##asr_minutes##' , asrMinutes . toLocaleString ( ) )
253- . replace ( '##plan_interval##' , product . price . recurring ! . interval ) }
254- </ li >
255- < li >
256- < div className = { styles . iconContainer } >
257- < Icon name = 'check' size = 'm' color = { product . price . unit_amount ? 'teal' : 'storm' } />
258- </ div >
259- { t ( '##mt_characters## characters of machine translation /##plan_interval##' )
260- . replace ( '##mt_characters##' , mtCharacters . toLocaleString ( ) )
261- . replace ( '##plan_interval##' , product . price . recurring ! . interval ) }
262- </ li >
263- </ >
264- ) }
265155 { recordKeys ( product . metadata ) . map (
266156 ( featureItem : string ) =>
267157 featureItem . includes ( 'feature_list_' ) && (
@@ -293,8 +183,7 @@ export const PlanContainer = ({
293183 < PlanButton
294184 product = { product }
295185 downgrading = { isDowngrading }
296- quantity = { submissionQuantity }
297- isSubscribedToPlan = { isSubscribedProduct ( product , submissionQuantity ) }
186+ isSubscribedToPlan = { isSubscribedProduct ( product ) }
298187 buySubscription = { buySubscription }
299188 showManage = { shouldShowManage ( product ) }
300189 isBusy = { isDisabled }
0 commit comments