@@ -20,7 +20,8 @@ import { PageWithSubMenu } from "../components/PageWithSubMenu";
20
20
import settingsMenu from "./settings-menu" ;
21
21
22
22
type PlanWithOriginalPrice = Plan & { originalPrice ?: number } ;
23
- type PendingPlan = PlanWithOriginalPrice & { pendingSince : number } ;
23
+ type Pending = { pendingSince : number } ;
24
+ type PendingPlan = PlanWithOriginalPrice & Pending ;
24
25
25
26
type TeamClaimModal = {
26
27
errorText : string ;
@@ -183,11 +184,38 @@ export default function () {
183
184
}
184
185
}
185
186
187
+ const [ pendingDowngradeCancellation , setPendingDowngradeCancellation ] = useState < Pending | undefined > ( getLocalStorageObject ( 'pendingDowngradeCancellation' ) ) ;
188
+ const setPendingCancelDowngrade = ( cancellation : Pending ) => {
189
+ clearTimeout ( pollAccountStatementTimeout ! ) ;
190
+ setLocalStorageObject ( 'pendingDowngradeCancellation' , cancellation ) ;
191
+ setPendingDowngradeCancellation ( cancellation ) ;
192
+ } ;
193
+ const removePendingCancelDowngrade = ( ) => {
194
+ clearTimeout ( pollAccountStatementTimeout ! ) ;
195
+ removeLocalStorageObject ( 'pendingDowngradeCancellation' ) ;
196
+ setPendingDowngradeCancellation ( undefined ) ;
197
+ }
198
+ if ( ! ! pendingDowngradeCancellation ) {
199
+ if ( ! scheduledDowngradePlanId ) {
200
+ // The downgrade cancellation worked
201
+ removePendingCancelDowngrade ( ) ;
202
+ } else if ( ( pendingDowngradeCancellation . pendingSince + 1000 * 60 * 5 ) < Date . now ( ) ) {
203
+ // Pending downgrade cancellations expire after 5 minutes
204
+ removePendingCancelDowngrade ( ) ;
205
+ } else if ( ! pollAccountStatementTimeout ) {
206
+ // Refresh account statement in 10 seconds in orer to poll for downgrade cancelled
207
+ pollAccountStatementTimeout = setTimeout ( async ( ) => {
208
+ const statement = await server . getAccountStatement ( { } ) ;
209
+ setAccountStatement ( statement ) ;
210
+ } , 10000 ) ;
211
+ }
212
+ }
213
+
186
214
const [ confirmUpgradeToPlan , setConfirmUpgradeToPlan ] = useState < Plan > ( ) ;
187
215
const [ confirmDowngradeToPlan , setConfirmDowngradeToPlan ] = useState < Plan > ( ) ;
188
216
const [ isConfirmCancelDowngrade , setIsConfirmCancelDowngrade ] = useState < boolean > ( false ) ;
189
217
const confirmUpgrade = ( to : Plan ) => {
190
- if ( pendingUpgradePlan || pendingDowngradePlan ) {
218
+ if ( pendingUpgradePlan || pendingDowngradePlan || pendingDowngradeCancellation ) {
191
219
// Don't upgrade if we're still waiting for a Chargebee callback
192
220
return ;
193
221
}
@@ -229,7 +257,7 @@ export default function () {
229
257
}
230
258
}
231
259
const confirmDowngrade = ( to : Plan ) => {
232
- if ( pendingUpgradePlan || pendingDowngradePlan ) {
260
+ if ( pendingUpgradePlan || pendingDowngradePlan || pendingDowngradeCancellation ) {
233
261
// Don't downgrade if we're still waiting for a Chargebee callback
234
262
return ;
235
263
}
@@ -269,6 +297,10 @@ export default function () {
269
297
}
270
298
}
271
299
const confirmCancelDowngrade = ( ) => {
300
+ if ( pendingUpgradePlan || pendingDowngradePlan || pendingDowngradeCancellation ) {
301
+ // Don't cancel downgrade if we're still waiting for a Chargebee callback
302
+ return ;
303
+ }
272
304
if ( ! scheduledDowngradePlanId ) {
273
305
// No scheduled downgrade to be cancelled?
274
306
return ;
@@ -284,7 +316,9 @@ export default function () {
284
316
}
285
317
try {
286
318
await server . subscriptionCancelDowngrade ( paidSubscription . uid ) ;
287
- // TODO: Update state somehow?
319
+ setPendingCancelDowngrade ( {
320
+ pendingSince : Date . now ( ) ,
321
+ } )
288
322
} catch ( error ) {
289
323
console . error ( 'Cancel Downgrade Error' , error ) ;
290
324
} finally {
@@ -305,7 +339,7 @@ export default function () {
305
339
} else {
306
340
const targetPlan = freePlan ;
307
341
let bottomLabel ;
308
- if ( scheduledDowngradePlanId === targetPlan . chargebeeId ) {
342
+ if ( scheduledDowngradePlanId === targetPlan . chargebeeId && ! pendingDowngradeCancellation ) {
309
343
bottomLabel = < p className = "text-green-600" > Downgrade scheduled< br /> < a className = "text-blue-light leading-6" href = "javascript:void(0)" onClick = { ( ) => confirmCancelDowngrade ( ) } > Cancel</ a > </ p > ;
310
344
} else if ( pendingDowngradePlan ?. chargebeeId === targetPlan . chargebeeId ) {
311
345
bottomLabel = < p className = "text-green-600 animate-pulse" > Downgrade scheduled</ p > ;
@@ -328,7 +362,7 @@ export default function () {
328
362
} else {
329
363
const targetPlan = applyCoupons ( personalPlan , availableCoupons ) ;
330
364
let bottomLabel ;
331
- if ( scheduledDowngradePlanId === targetPlan . chargebeeId ) {
365
+ if ( scheduledDowngradePlanId === targetPlan . chargebeeId && ! pendingDowngradeCancellation ) {
332
366
bottomLabel = < p className = "text-green-600" > Downgrade scheduled< br /> < a className = "text-blue-light leading-6" href = "javascript:void(0)" onClick = { ( ) => confirmCancelDowngrade ( ) } > Cancel</ a > </ p > ;
333
367
} else if ( pendingDowngradePlan ?. chargebeeId === targetPlan . chargebeeId ) {
334
368
bottomLabel = < p className = "text-green-600" > Downgrade scheduled</ p > ;
@@ -354,7 +388,7 @@ export default function () {
354
388
} else {
355
389
const targetPlan = applyCoupons ( professionalPlan , availableCoupons ) ;
356
390
let bottomLabel ;
357
- if ( scheduledDowngradePlanId === targetPlan . chargebeeId ) {
391
+ if ( scheduledDowngradePlanId === targetPlan . chargebeeId && ! pendingDowngradeCancellation ) {
358
392
bottomLabel = < p className = "text-green-600" > Downgrade scheduled< br /> < a className = "text-blue-light leading-6" href = "javascript:void(0)" onClick = { ( ) => confirmCancelDowngrade ( ) } > Cancel</ a > </ p > ;
359
393
} else if ( pendingDowngradePlan ?. chargebeeId === targetPlan . chargebeeId ) {
360
394
bottomLabel = < p className = "text-green-600" > Downgrade scheduled</ p > ;
0 commit comments