@@ -25,6 +25,7 @@ import { UserContext } from "../user-context";
25
25
import Tooltip from "../components/Tooltip" ;
26
26
import { PaymentContext } from "../payment-context" ;
27
27
import { PageWithSettingsSubMenu } from "./PageWithSettingsSubMenu" ;
28
+ import { FeatureFlagContext } from "../contexts/FeatureFlagContext" ;
28
29
29
30
type PlanWithOriginalPrice = Plan & { originalPrice ?: number } ;
30
31
type Pending = { pendingSince : number } ;
@@ -45,6 +46,7 @@ type TeamClaimModal =
45
46
export default function ( ) {
46
47
const { user, userBillingMode } = useContext ( UserContext ) ;
47
48
const { currency, setCurrency, isStudent, isChargebeeCustomer } = useContext ( PaymentContext ) ;
49
+ const { isUsageBasedBillingEnabled } = useContext ( FeatureFlagContext ) ;
48
50
const [ accountStatement , setAccountStatement ] = useState < AccountStatement > ( ) ;
49
51
const [ availableCoupons , setAvailableCoupons ] = useState < PlanCoupon [ ] > ( ) ;
50
52
const [ appliedCoupons , setAppliedCoupons ] = useState < PlanCoupon [ ] > ( ) ;
@@ -356,6 +358,7 @@ export default function () {
356
358
} ;
357
359
358
360
const planCards = [ ] ;
361
+ const canUpgradeToChargebee = ! isUsageBasedBillingEnabled ;
359
362
360
363
// Plan card: Free a.k.a. Open Source (or Professional Open Source)
361
364
const openSourceFeatures = (
@@ -374,7 +377,7 @@ export default function () {
374
377
if ( currentPlan . chargebeeId === freePlan . chargebeeId ) {
375
378
planCards . push (
376
379
< PlanCard
377
- isDisabled = { ! ! assignedTs || pendingChargebeeCallback }
380
+ isDisabled = { ! canUpgradeToChargebee || ! ! assignedTs || pendingChargebeeCallback }
378
381
plan = { freePlan }
379
382
isCurrent = { ! ! accountStatement }
380
383
>
@@ -409,7 +412,7 @@ export default function () {
409
412
}
410
413
planCards . push (
411
414
< PlanCard
412
- isDisabled = { ! ! assignedTs || pendingChargebeeCallback }
415
+ isDisabled = { ! canUpgradeToChargebee || ! ! assignedTs || pendingChargebeeCallback }
413
416
plan = { targetPlan }
414
417
isCurrent = { false }
415
418
onDowngrade = { onDowngrade }
@@ -435,7 +438,7 @@ export default function () {
435
438
) : undefined ;
436
439
planCards . push (
437
440
< PlanCard
438
- isDisabled = { ! ! assignedTs || pendingChargebeeCallback }
441
+ isDisabled = { ! canUpgradeToChargebee || ! ! assignedTs || pendingChargebeeCallback }
439
442
plan = { applyCoupons ( personalPlan , appliedCoupons ) }
440
443
isCurrent = { true }
441
444
bottomLabel = { bottomLabel }
@@ -474,7 +477,7 @@ export default function () {
474
477
}
475
478
planCards . push (
476
479
< PlanCard
477
- isDisabled = { ! ! assignedTs || pendingChargebeeCallback }
480
+ isDisabled = { ! canUpgradeToChargebee || ! ! assignedTs || pendingChargebeeCallback }
478
481
plan = { targetPlan }
479
482
isCurrent = { false }
480
483
onUpgrade = { onUpgrade }
@@ -505,7 +508,7 @@ export default function () {
505
508
) : undefined ;
506
509
planCards . push (
507
510
< PlanCard
508
- isDisabled = { ! ! assignedTs || pendingChargebeeCallback }
511
+ isDisabled = { ! canUpgradeToChargebee || ! ! assignedTs || pendingChargebeeCallback }
509
512
plan = { applyCoupons ( professionalPlan , appliedCoupons ) }
510
513
isCurrent = { true }
511
514
bottomLabel = { bottomLabel }
@@ -545,7 +548,7 @@ export default function () {
545
548
}
546
549
planCards . push (
547
550
< PlanCard
548
- isDisabled = { ! ! assignedTs || pendingChargebeeCallback }
551
+ isDisabled = { ! canUpgradeToChargebee || ! ! assignedTs || pendingChargebeeCallback }
549
552
plan = { targetPlan }
550
553
isCurrent = { ! ! assignedProfessionalTs }
551
554
onUpgrade = { onUpgrade }
@@ -583,7 +586,7 @@ export default function () {
583
586
) : undefined ;
584
587
planCards . push (
585
588
< PlanCard
586
- isDisabled = { ! ! assignedTs || pendingChargebeeCallback }
589
+ isDisabled = { ! canUpgradeToChargebee || ! ! assignedTs || pendingChargebeeCallback }
587
590
plan = { applyCoupons ( studentUnleashedPlan , appliedCoupons ) }
588
591
isCurrent = { true }
589
592
bottomLabel = { bottomLabel }
@@ -599,7 +602,7 @@ export default function () {
599
602
) : undefined ;
600
603
planCards . push (
601
604
< PlanCard
602
- isDisabled = { ! ! assignedTs || pendingChargebeeCallback }
605
+ isDisabled = { ! canUpgradeToChargebee || ! ! assignedTs || pendingChargebeeCallback }
603
606
plan = { applyCoupons ( unleashedPlan , appliedCoupons ) }
604
607
isCurrent = { true }
605
608
bottomLabel = { bottomLabel }
@@ -618,7 +621,7 @@ export default function () {
618
621
}
619
622
planCards . push (
620
623
< PlanCard
621
- isDisabled = { ! ! assignedTs || pendingChargebeeCallback }
624
+ isDisabled = { ! canUpgradeToChargebee || ! ! assignedTs || pendingChargebeeCallback }
622
625
plan = { targetPlan }
623
626
isCurrent = { ! ! isUnleashedTsAssigned }
624
627
onUpgrade = { onUpgrade }
@@ -629,101 +632,87 @@ export default function () {
629
632
) ;
630
633
}
631
634
632
- const showPlans = userBillingMode && userBillingMode . mode === "chargebee" ;
633
635
return (
634
636
< div >
635
637
< PageWithSettingsSubMenu title = "Plans" subtitle = "Manage account usage and billing." >
636
- { showPlans && (
637
- < div className = "w-full text-center" >
638
- < p className = "text-xl text-gray-500" >
639
- You are currently using the{ " " }
640
- < span className = "font-bold" >
641
- { Plans . getById ( assignedTs ?. planId ) ?. name || currentPlan . name }
642
- </ span > { " " }
643
- plan.
638
+ < div className = "w-full text-center" >
639
+ < p className = "text-xl text-gray-500" >
640
+ You are currently using the{ " " }
641
+ < span className = "font-bold" > { Plans . getById ( assignedTs ?. planId ) ?. name || currentPlan . name } </ span > { " " }
642
+ plan.
643
+ </ p >
644
+ { canUpgradeToChargebee && ! assignedTs && (
645
+ < p className = "text-base w-96 m-auto" >
646
+ Upgrade your plan to get more hours and more parallel workspaces.
644
647
</ p >
645
- { ! assignedTs && (
646
- < p className = "text-base w-96 m-auto" >
647
- Upgrade your plan to get more hours and more parallel workspaces.
648
- </ p >
649
- ) }
650
- < Tooltip
651
- content = { `Current billing cycle: ${ guessCurrentBillingCycle ( currentPlan , accountStatement )
652
- . map ( ( d ) => d . toLocaleDateString ( ) )
653
- . join ( " - " ) } `}
648
+ ) }
649
+ < Tooltip
650
+ content = { `Current billing cycle: ${ guessCurrentBillingCycle ( currentPlan , accountStatement )
651
+ . map ( ( d ) => d . toLocaleDateString ( ) )
652
+ . join ( " - " ) } `}
653
+ >
654
+ < p className = "mt-2 font-semibold text-gray-500" >
655
+ Remaining hours:{ " " }
656
+ { typeof accountStatement ?. remainingHours === "number"
657
+ ? Math . floor ( accountStatement . remainingHours * 10 ) / 10
658
+ : accountStatement ?. remainingHours }
659
+ </ p >
660
+ </ Tooltip >
661
+ { typeof accountStatement ?. remainingHours === "number" &&
662
+ typeof currentPlan . hoursPerMonth === "number" ? (
663
+ < progress
664
+ value = { currentPlan . hoursPerMonth - accountStatement . remainingHours }
665
+ max = { currentPlan . hoursPerMonth }
666
+ />
667
+ ) : (
668
+ < progress value = "0" max = "100" />
669
+ ) }
670
+ < p className = "text-sm" >
671
+ < a
672
+ className = { `gp-link ${ isChargebeeCustomer ? "" : "invisible" } ` }
673
+ href = "javascript:void(0)"
674
+ onClick = { ( ) => {
675
+ ChargebeeClient . getOrCreate ( ) . then ( ( chargebeeClient ) => chargebeeClient . openPortal ( ) ) ;
676
+ } }
654
677
>
655
- < p className = "mt-2 font-semibold text-gray-500" >
656
- Remaining hours:{ " " }
657
- { typeof accountStatement ?. remainingHours === "number"
658
- ? Math . floor ( accountStatement . remainingHours * 10 ) / 10
659
- : accountStatement ?. remainingHours }
660
- </ p >
661
- </ Tooltip >
662
- { typeof accountStatement ?. remainingHours === "number" &&
663
- typeof currentPlan . hoursPerMonth === "number" ? (
664
- < progress
665
- value = { currentPlan . hoursPerMonth - accountStatement . remainingHours }
666
- max = { currentPlan . hoursPerMonth }
667
- />
668
- ) : (
669
- < progress value = "0" max = "100" />
678
+ Billing
679
+ </ a >
680
+ { ! ! accountStatement && Plans . isFreePlan ( currentPlan . chargebeeId ) && (
681
+ < span className = "pl-6" >
682
+ { currency === "EUR" ? (
683
+ < >
684
+ € /{ " " }
685
+ < a
686
+ className = "text-blue-light hover:underline"
687
+ href = "javascript:void(0)"
688
+ onClick = { ( ) => setCurrency ( "USD" ) }
689
+ >
690
+ $
691
+ </ a >
692
+ </ >
693
+ ) : (
694
+ < >
695
+ < a
696
+ className = "text-blue-light hover:underline"
697
+ href = "javascript:void(0)"
698
+ onClick = { ( ) => setCurrency ( "EUR" ) }
699
+ >
700
+ €
701
+ </ a > { " " }
702
+ / $
703
+ </ >
704
+ ) }
705
+ </ span >
670
706
) }
671
- < p className = "text-sm" >
672
- < a
673
- className = { `gp-link ${ isChargebeeCustomer ? "" : "invisible" } ` }
674
- href = "javascript:void(0)"
675
- onClick = { ( ) => {
676
- ChargebeeClient . getOrCreate ( ) . then ( ( chargebeeClient ) =>
677
- chargebeeClient . openPortal ( ) ,
678
- ) ;
679
- } }
680
- >
681
- Billing
682
- </ a >
683
- { ! ! accountStatement && Plans . isFreePlan ( currentPlan . chargebeeId ) && (
684
- < span className = "pl-6" >
685
- { currency === "EUR" ? (
686
- < >
687
- € /{ " " }
688
- < a
689
- className = "text-blue-light hover:underline"
690
- href = "javascript:void(0)"
691
- onClick = { ( ) => setCurrency ( "USD" ) }
692
- >
693
- $
694
- </ a >
695
- </ >
696
- ) : (
697
- < >
698
- < a
699
- className = "text-blue-light hover:underline"
700
- href = "javascript:void(0)"
701
- onClick = { ( ) => setCurrency ( "EUR" ) }
702
- >
703
- €
704
- </ a > { " " }
705
- / $
706
- </ >
707
- ) }
708
- </ span >
709
- ) }
710
- </ p >
711
- </ div >
712
- ) }
707
+ </ p >
708
+ </ div >
713
709
< div className = "mt-4 flex justify-center space-x-3 2xl:space-x-7" > { planCards } </ div >
714
710
{ assignedTs && userBillingMode ?. mode === "chargebee" && ! ! userBillingMode . teamNames && (
715
711
< Alert type = "info" className = "mt-10 mx-auto" >
716
712
< p > Assigned Team Seats</ p >
717
713
< ul > { userBillingMode . teamNames . join ( ", " ) } </ ul >
718
714
</ Alert >
719
715
) }
720
- < InfoBox className = "w-2/3 mt-14 mx-auto" >
721
- If you are interested in purchasing a plan for a team, purchase a Team plan with one centralized
722
- billing.{ " " }
723
- < a className = "underline" href = "https://www.gitpod.io/docs/teams/" >
724
- Learn more
725
- </ a >
726
- </ InfoBox >
727
716
{ ! ! confirmUpgradeToPlan && (
728
717
// TODO: Use title and buttons props
729
718
< Modal visible = { true } onClose = { ( ) => setConfirmUpgradeToPlan ( undefined ) } >
0 commit comments