Skip to content

Commit 556b114

Browse files
emyllerclaude
andauthored
feat(Billing): Reintroduce the Scale-Up plan (#7216)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a7242c2 commit 556b114

9 files changed

Lines changed: 198 additions & 27 deletions

File tree

frontend/common/utils/utils.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,17 +397,20 @@ const Utils = Object.assign({}, BaseUtils, {
397397
return EnvironmentPermissionDescriptions.UPDATE_FEATURE_STATE
398398
},
399399

400-
getNextPlan: (skipFree?: boolean) => {
400+
getNextPlan: () => {
401401
const currentPlan = Utils.getPlanName(AccountStore.getActiveOrgPlan())
402402
if (currentPlan !== planNames.enterprise && !Utils.isSaas()) {
403403
return planNames.enterprise
404404
}
405405
switch (currentPlan) {
406406
case planNames.free: {
407-
return skipFree ? planNames.startup : planNames.scaleUp
407+
return planNames.startup
408408
}
409409
case planNames.startup: {
410-
return planNames.startup
410+
return planNames.scaleUp
411+
}
412+
case planNames.scaleUp: {
413+
return planNames.enterprise
411414
}
412415
default: {
413416
return planNames.enterprise

frontend/env/project_dev.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const Project = {
1717
// This is used for Sentry tracking
1818
maintenance: false,
1919
plans: {
20-
scaleUp: { annual: 'scale-up-annual-v2', monthly: 'scale-up-v2' },
20+
scaleUp: { annual: 'Scale-Up-v4-USD-Yearly', monthly: 'Scale-Up-v4-USD-Monthly' },
2121
startup: { annual: 'startup-annual-v2', monthly: 'startup-v2' },
2222
},
2323
useSecureCookies: true,

frontend/env/project_local.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const Project = {
1717
// This is used for Sentry tracking
1818
maintenance: false,
1919
plans: {
20-
scaleUp: { annual: 'scale-up-annual-v2', monthly: 'scale-up-v2' },
20+
scaleUp: { annual: 'Scale-Up-v4-USD-Yearly', monthly: 'Scale-Up-v4-USD-Monthly' },
2121
startup: { annual: 'startup-annual-v2', monthly: 'startup-v2' },
2222
},
2323
useSecureCookies: false,

frontend/env/project_prod.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const Project = {
2727
// This is used for Sentry tracking
2828
maintenance: false,
2929
plans: {
30-
scaleUp: { annual: 'scale-up-12-months-v2', monthly: 'scale-up-v2' },
30+
scaleUp: { annual: 'Scale-Up-v4-USD-Yearly', monthly: 'Scale-Up-v4-USD-Monthly' },
3131
startup: { annual: 'start-up-12-months-v2', monthly: 'startup-v2' },
3232
},
3333
useSecureCookies: true,

frontend/web/components/modals/Payment.js

Lines changed: 113 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,118 @@ const Payment = class extends Component {
268268
</div>
269269
</div>
270270
</Flex>
271+
<Flex className='pricing-panel p-2'>
272+
<div className='panel panel-default'>
273+
<div
274+
className='panel-content p-3 pt-4 d-flex flex-column justify-content-between'
275+
style={{
276+
backgroundColor: 'rgba(39, 171, 149, 0.08)',
277+
minHeight: '250px',
278+
}}
279+
>
280+
<span className='fw-bold text-primary fs-small'>
281+
Most Popular
282+
</span>
283+
<Row className='pt-4 justify-content-center'>
284+
<Icon name='flash' width={32} />
285+
<h4 className='mb-0 ml-2'>Scale-Up</h4>
286+
</Row>
287+
<Row className='pt-3 justify-content-center'>
288+
<h5 className='mb-0 align-self-start'>$</h5>
289+
<h1 className='mb-0 d-flex align-items-end'>
290+
{this.state.yearly ? '270' : '300'}{' '}
291+
<h5 className='fs-lg mb-0'>/mo</h5>
292+
</h1>
293+
</Row>
294+
<div className='pricing-type pt-1 text-muted'>
295+
+ ${this.state.yearly ? '50' : '60'}/seat
296+
</div>
297+
{!viewOnly ? (
298+
<>
299+
<PaymentButton
300+
data-cb-plan-id={Project.plans?.scaleUp?.annual}
301+
className={classNames(
302+
'btn btn-primary btn-lg full-width mt-3',
303+
{ 'd-none': !this.state.yearly },
304+
)}
305+
isDisableAccount={this.props.isDisableAccountText}
306+
>
307+
{plan.includes('scale-up')
308+
? 'Purchased'
309+
: '14 Day Free Trial'}
310+
</PaymentButton>
311+
<PaymentButton
312+
data-cb-plan-id={Project.plans?.scaleUp?.monthly}
313+
className={classNames(
314+
'btn btn-primary btn-lg full-width mt-3',
315+
{ 'd-none': this.state.yearly },
316+
)}
317+
isDisableAccount={this.props.isDisableAccountText}
318+
>
319+
{plan.includes('scale-up')
320+
? 'Purchased'
321+
: '14 Day Free Trial'}
322+
</PaymentButton>
323+
</>
324+
) : null}
325+
</div>
326+
<div className='panel-footer mt-3'>
327+
<h5 className='m-2 mb-4'>
328+
All from{' '}
329+
<span className='text-primary'>Start-Up,</span> plus
330+
</h5>
331+
<ul className='pricing-features mb-0 px-2'>
332+
<li>
333+
<Row className='mb-3 pricing-features-item'>
334+
<span>
335+
<Icon name='checkmark-circle' fill='#27AB95' />
336+
</span>
337+
<div className='ml-2'>
338+
Up to
339+
<strong> 5,000,000</strong> Requests per month
340+
</div>
341+
</Row>
342+
</li>
343+
<li>
344+
<Row className='mb-3 pricing-features-item'>
345+
<span>
346+
<Icon name='checkmark-circle' fill='#27AB95' />
347+
</span>
348+
<div className='ml-2'>
349+
Up to <strong>20</strong> Team members
350+
</div>
351+
</Row>
352+
</li>
353+
<li>
354+
<Row className='mb-3 pricing-features-item'>
355+
<span>
356+
<Icon name='checkmark-circle' fill='#27AB95' />
357+
</span>
358+
<div className='ml-2'>
359+
User roles and permissions
360+
</div>
361+
</Row>
362+
</li>
363+
<li>
364+
<Row className='mb-3 pricing-features-item'>
365+
<span>
366+
<Icon name='checkmark-circle' fill='#27AB95' />
367+
</span>
368+
<div className='ml-2'>Change requests</div>
369+
</Row>
370+
</li>
371+
<li>
372+
<Row className='mb-3 pricing-features-item'>
373+
<span>
374+
<Icon name='checkmark-circle' fill='#27AB95' />
375+
</span>
376+
<div className='ml-2'>Audit logs</div>
377+
</Row>
378+
</li>
379+
</ul>
380+
</div>
381+
</div>
382+
</Flex>
271383
<Flex className='pricing-panel bg-primary900 text-white p-2'>
272384
<div className='panel panel-default'>
273385
<div
@@ -320,7 +432,7 @@ const Payment = class extends Component {
320432
<div className='panel-footer mt-3'>
321433
<h5 className='text-white m-2 mb-4'>
322434
All from{' '}
323-
<span className='text-secondary'>Start-Up,</span> plus
435+
<span className='text-secondary'>Scale-Up,</span> plus
324436
</h5>
325437
<ul className='pricing-features mb-0 px-2'>
326438
<li>
@@ -410,16 +522,6 @@ const Payment = class extends Component {
410522
</div>
411523
</Flex>
412524
</Row>
413-
<div className='text-center mt-4'>
414-
*Need something in-between our Enterprise plan for users or
415-
API limits?
416-
<div>
417-
<a href={'https://www.flagsmith.com/contact-us'}>
418-
Reach out
419-
</a>{' '}
420-
to us and we'll help you out
421-
</div>
422-
</div>
423525
</div>
424526
)
425527
}}

frontend/web/components/modals/payment/Payment.tsx

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import BlockedOrgInfo from 'components/BlockedOrgInfo'
55
import { Organisation } from 'common/types/responses'
66
import { PricingToggle } from './PricingToggle'
77
import { PricingPanel } from './PricingPanel'
8-
import { STARTUP_FEATURES, ENTERPRISE_FEATURES } from './pricingFeatures'
8+
import {
9+
STARTUP_FEATURES,
10+
SCALE_UP_FEATURES,
11+
ENTERPRISE_FEATURES,
12+
} from './pricingFeatures'
913
import {
1014
CHARGEBEE_SCRIPT_URL,
1115
CONTACT_US_URL,
@@ -102,6 +106,28 @@ export const Payment: FC<PaymentProps> = ({
102106
features={STARTUP_FEATURES}
103107
hasActiveSubscription={hasActiveSubscription}
104108
organisationId={organisation.id}
109+
includesFrom='Free'
110+
/>
111+
112+
<PricingPanel
113+
title='Scale-Up'
114+
priceYearly='270'
115+
priceMonthly='300'
116+
seatPriceYearly='50'
117+
seatPriceMonthly='60'
118+
isYearly={yearly}
119+
isFeatured
120+
chargebeePlanId={
121+
yearly
122+
? Project.plans?.scaleUp?.annual
123+
: Project.plans?.scaleUp?.monthly
124+
}
125+
isPurchased={plan.includes('scale-up')}
126+
isDisableAccount={isDisableAccountText}
127+
features={SCALE_UP_FEATURES}
128+
hasActiveSubscription={hasActiveSubscription}
129+
organisationId={organisation.id}
130+
includesFrom='Start-Up'
105131
/>
106132

107133
<PricingPanel
@@ -111,6 +137,7 @@ export const Payment: FC<PaymentProps> = ({
111137
features={ENTERPRISE_FEATURES}
112138
hasActiveSubscription={hasActiveSubscription}
113139
organisationId={organisation.id}
140+
includesFrom='Scale-Up'
114141
headerContent={
115142
<>
116143
Optional{' '}
@@ -136,13 +163,6 @@ export const Payment: FC<PaymentProps> = ({
136163
}
137164
/>
138165
</Row>
139-
<div className='text-center mt-4'>
140-
*Need something in-between our Enterprise plan for users or API
141-
limits?
142-
<div>
143-
<a href={CONTACT_US_URL}>Reach out</a> to us and we'll help you out
144-
</div>
145-
</div>
146166
</div>
147167
</div>
148168
)

frontend/web/components/modals/payment/PricingPanel.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ export type PricingPanelProps = {
1111
title: string
1212
priceMonthly?: string
1313
priceYearly?: string
14+
seatPriceMonthly?: string
15+
seatPriceYearly?: string
16+
includesFrom: string
17+
isFeatured?: boolean
1418
isYearly: boolean
1519
chargebeePlanId?: string
1620
isPurchased?: boolean
@@ -27,13 +31,17 @@ export const PricingPanel = ({
2731
features,
2832
hasActiveSubscription,
2933
headerContent,
34+
includesFrom,
3035
isDisableAccount,
3136
isEnterprise,
37+
isFeatured,
3238
isPurchased,
3339
isYearly,
3440
organisationId,
3541
priceMonthly,
3642
priceYearly,
43+
seatPriceMonthly,
44+
seatPriceYearly,
3745
title,
3846
}: PricingPanelProps) => {
3947
return (
@@ -46,6 +54,11 @@ export const PricingPanel = ({
4654
<div className='p-3 pt-4 pricing-panel-content'>
4755
<div className='pricing-panel-layout'>
4856
<div>
57+
{isFeatured && (
58+
<span className='fw-bold text-primary fs-small'>
59+
Most Popular
60+
</span>
61+
)}
4962
{headerContent && (
5063
<span
5164
className={classNames('featured', {
@@ -81,6 +94,12 @@ export const PricingPanel = ({
8194
</Row>
8295
)}
8396

97+
{(seatPriceMonthly || seatPriceYearly) && (
98+
<div className='pricing-type pt-1 text-muted'>
99+
+ ${isYearly ? seatPriceYearly : seatPriceMonthly}/seat
100+
</div>
101+
)}
102+
84103
{isEnterprise && (
85104
<Row className='pt-3 justify-content-center'>
86105
<div className='pricing-type text-secondary'>
@@ -125,7 +144,7 @@ export const PricingPanel = ({
125144
>
126145
All from{' '}
127146
<span className={isEnterprise ? 'text-secondary' : 'text-primary'}>
128-
{isEnterprise ? 'Start-Up,' : 'Free,'}
147+
{includesFrom},
129148
</span>{' '}
130149
plus
131150
</h5>

frontend/web/components/modals/payment/pricingFeatures.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,33 @@ export const STARTUP_FEATURES: PricingFeature[] = [
3030
},
3131
]
3232

33+
export const SCALE_UP_FEATURES: PricingFeature[] = [
34+
{
35+
text: (
36+
<>
37+
Up to
38+
<strong> 5,000,000</strong> Requests per month
39+
</>
40+
),
41+
},
42+
{
43+
text: (
44+
<>
45+
Up to <strong>20</strong> Team members
46+
</>
47+
),
48+
},
49+
{
50+
text: 'User roles and permissions',
51+
},
52+
{
53+
text: 'Change requests',
54+
},
55+
{
56+
text: 'Audit logs',
57+
},
58+
]
59+
3360
export const ENTERPRISE_FEATURES: PricingFeature[] = [
3461
{
3562
text: (

frontend/web/components/pages/UsersAndPermissionsPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ const UsersAndPermissionsInner: FC<UsersAndPermissionsInnerType> = ({
280280
) : (
281281
<strong>
282282
You will automatically be charged
283-
$20/month for each additional member that
283+
$60/month for each additional member that
284284
joins your organisation.
285285
</strong>
286286
)}

0 commit comments

Comments
 (0)