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