diff options
Diffstat (limited to 'src/features/planSelection/components/PlanSelection.js')
-rw-r--r-- | src/features/planSelection/components/PlanSelection.js | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/src/features/planSelection/components/PlanSelection.js b/src/features/planSelection/components/PlanSelection.js new file mode 100644 index 000000000..b6bb9d32d --- /dev/null +++ b/src/features/planSelection/components/PlanSelection.js | |||
@@ -0,0 +1,281 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import PropTypes from 'prop-types'; | ||
3 | import { observer } from 'mobx-react'; | ||
4 | import injectSheet from 'react-jss'; | ||
5 | import { defineMessages, intlShape } from 'react-intl'; | ||
6 | import { H1, H2, Icon } from '@meetfranz/ui'; | ||
7 | import color from 'color'; | ||
8 | |||
9 | import { mdiRocket, mdiArrowRight } from '@mdi/js'; | ||
10 | import PlanItem from './PlanItem'; | ||
11 | import { i18nPlanName } from '../../../helpers/plan-helpers'; | ||
12 | import { PLANS } from '../../../config'; | ||
13 | import { FeatureList } from '../../../components/ui/FeatureList'; | ||
14 | import Appear from '../../../components/ui/effects/Appear'; | ||
15 | import { gaPage } from '../../../lib/analytics'; | ||
16 | |||
17 | const messages = defineMessages({ | ||
18 | welcome: { | ||
19 | id: 'feature.planSelection.fullscreen.welcome', | ||
20 | defaultMessage: '!!!Are you ready to choose, {name}', | ||
21 | }, | ||
22 | subheadline: { | ||
23 | id: 'feature.planSelection.fullscreen.subheadline', | ||
24 | defaultMessage: '!!!It\'s time to make a choice. Franz works best on our Personal and Professional plans. Please have a look and choose the best one for you.', | ||
25 | }, | ||
26 | textFree: { | ||
27 | id: 'feature.planSelection.free.text', | ||
28 | defaultMessage: '!!!Basic functionality', | ||
29 | }, | ||
30 | textPersonal: { | ||
31 | id: 'feature.planSelection.personal.text', | ||
32 | defaultMessage: '!!!More services, no waiting - ideal for personal use.', | ||
33 | }, | ||
34 | textProfessional: { | ||
35 | id: 'feature.planSelection.pro.text', | ||
36 | defaultMessage: '!!!Unlimited services and professional features for you - and your team.', | ||
37 | }, | ||
38 | ctaStayOnFree: { | ||
39 | id: 'feature.planSelection.cta.stayOnFree', | ||
40 | defaultMessage: '!!!Stay on Free', | ||
41 | }, | ||
42 | ctaDowngradeFree: { | ||
43 | id: 'feature.planSelection.cta.ctaDowngradeFree', | ||
44 | defaultMessage: '!!!Downgrade to Free', | ||
45 | }, | ||
46 | actionTrial: { | ||
47 | id: 'feature.planSelection.cta.trial', | ||
48 | defaultMessage: '!!!Start my free 14-days Trial', | ||
49 | }, | ||
50 | shortActionPersonal: { | ||
51 | id: 'feature.planSelection.cta.upgradePersonal', | ||
52 | defaultMessage: '!!!Choose Personal', | ||
53 | }, | ||
54 | shortActionPro: { | ||
55 | id: 'feature.planSelection.cta.upgradePro', | ||
56 | defaultMessage: '!!!Choose Professional', | ||
57 | }, | ||
58 | fullFeatureList: { | ||
59 | id: 'feature.planSelection.fullFeatureList', | ||
60 | defaultMessage: '!!!Complete comparison of all plans', | ||
61 | }, | ||
62 | pricesBasedOnAnnualPayment: { | ||
63 | id: 'feature.planSelection.pricesBasedOnAnnualPayment', | ||
64 | defaultMessage: '!!!All prices based on yearly payment', | ||
65 | }, | ||
66 | }); | ||
67 | |||
68 | const styles = theme => ({ | ||
69 | root: { | ||
70 | background: theme.colorModalOverlayBackground, | ||
71 | width: '100%', | ||
72 | height: '100%', | ||
73 | position: 'absolute', | ||
74 | top: 0, | ||
75 | left: 0, | ||
76 | display: 'flex', | ||
77 | justifyContent: 'center', | ||
78 | alignItems: 'center', | ||
79 | zIndex: 999999, | ||
80 | overflowY: 'scroll', | ||
81 | }, | ||
82 | container: { | ||
83 | width: '80%', | ||
84 | height: 'auto', | ||
85 | background: theme.styleTypes.primary.accent, | ||
86 | padding: 40, | ||
87 | borderRadius: theme.borderRadius, | ||
88 | maxWidth: 1000, | ||
89 | |||
90 | '& h1, & h2': { | ||
91 | textAlign: 'center', | ||
92 | color: theme.styleTypes.primary.contrast, | ||
93 | }, | ||
94 | }, | ||
95 | plans: { | ||
96 | display: 'flex', | ||
97 | margin: [40, 0, 0], | ||
98 | height: 'auto', | ||
99 | |||
100 | '& > div': { | ||
101 | margin: [0, 15], | ||
102 | flex: 1, | ||
103 | height: 'auto', | ||
104 | background: theme.styleTypes.primary.contrast, | ||
105 | boxShadow: [0, 2, 30, color('#000').alpha(0.1).rgb().string()], | ||
106 | }, | ||
107 | }, | ||
108 | bigIcon: { | ||
109 | background: theme.styleTypes.danger.accent, | ||
110 | width: 120, | ||
111 | height: 120, | ||
112 | display: 'flex', | ||
113 | alignItems: 'center', | ||
114 | borderRadius: '100%', | ||
115 | justifyContent: 'center', | ||
116 | margin: [-100, 'auto', 20], | ||
117 | |||
118 | '& svg': { | ||
119 | width: '80px !important', | ||
120 | height: '80px !important', | ||
121 | filter: 'drop-shadow( 0px 2px 3px rgba(0, 0, 0, 0.3))', | ||
122 | fill: theme.styleTypes.danger.contrast, | ||
123 | }, | ||
124 | }, | ||
125 | headline: { | ||
126 | fontSize: 40, | ||
127 | }, | ||
128 | subheadline: { | ||
129 | maxWidth: 660, | ||
130 | fontSize: 22, | ||
131 | lineHeight: 1.1, | ||
132 | margin: [0, 'auto'], | ||
133 | }, | ||
134 | featureList: { | ||
135 | '& li': { | ||
136 | borderBottom: [1, 'solid', '#CECECE'], | ||
137 | }, | ||
138 | }, | ||
139 | footer: { | ||
140 | display: 'flex', | ||
141 | color: theme.styleTypes.primary.contrast, | ||
142 | marginTop: 20, | ||
143 | padding: [0, 15], | ||
144 | }, | ||
145 | fullFeatureList: { | ||
146 | marginRight: 'auto', | ||
147 | textAlign: 'center', | ||
148 | display: 'flex', | ||
149 | justifyContent: 'center', | ||
150 | alignItems: 'center', | ||
151 | color: `${theme.styleTypes.primary.contrast} !important`, | ||
152 | |||
153 | '& svg': { | ||
154 | marginRight: 5, | ||
155 | }, | ||
156 | }, | ||
157 | scrollContainer: { | ||
158 | border: '1px solid red', | ||
159 | overflow: 'scroll-x', | ||
160 | }, | ||
161 | featuredPlan: { | ||
162 | transform: 'scale(1.05)', | ||
163 | }, | ||
164 | disclaimer: { | ||
165 | textAlign: 'right', | ||
166 | margin: [10, 15, 0, 0], | ||
167 | }, | ||
168 | }); | ||
169 | |||
170 | @injectSheet(styles) @observer | ||
171 | class PlanSelection extends Component { | ||
172 | static propTypes = { | ||
173 | classes: PropTypes.object.isRequired, | ||
174 | firstname: PropTypes.string.isRequired, | ||
175 | plans: PropTypes.object.isRequired, | ||
176 | currency: PropTypes.string.isRequired, | ||
177 | subscriptionExpired: PropTypes.bool.isRequired, | ||
178 | upgradeAccount: PropTypes.func.isRequired, | ||
179 | stayOnFree: PropTypes.func.isRequired, | ||
180 | hadSubscription: PropTypes.bool.isRequired, | ||
181 | }; | ||
182 | |||
183 | static contextTypes = { | ||
184 | intl: intlShape, | ||
185 | }; | ||
186 | |||
187 | componentDidMount() { | ||
188 | gaPage('/select-plan'); | ||
189 | } | ||
190 | |||
191 | render() { | ||
192 | const { | ||
193 | classes, | ||
194 | firstname, | ||
195 | plans, | ||
196 | currency, | ||
197 | subscriptionExpired, | ||
198 | upgradeAccount, | ||
199 | stayOnFree, | ||
200 | hadSubscription, | ||
201 | } = this.props; | ||
202 | |||
203 | const { intl } = this.context; | ||
204 | |||
205 | return ( | ||
206 | <Appear> | ||
207 | <div | ||
208 | className={classes.root} | ||
209 | > | ||
210 | <div className={classes.container}> | ||
211 | <div className={classes.bigIcon}> | ||
212 | <Icon icon={mdiRocket} /> | ||
213 | </div> | ||
214 | <H1 className={classes.headline}>{intl.formatMessage(messages.welcome, { name: firstname })}</H1> | ||
215 | <H2 className={classes.subheadline}>{intl.formatMessage(messages.subheadline)}</H2> | ||
216 | <div className={classes.plans}> | ||
217 | <PlanItem | ||
218 | name={i18nPlanName(PLANS.FREE, intl)} | ||
219 | text={intl.formatMessage(messages.textFree)} | ||
220 | price={0} | ||
221 | currency={currency} | ||
222 | ctaLabel={intl.formatMessage(subscriptionExpired ? messages.ctaDowngradeFree : messages.ctaStayOnFree)} | ||
223 | upgrade={() => stayOnFree()} | ||
224 | simpleCTA | ||
225 | > | ||
226 | <FeatureList | ||
227 | plan={PLANS.FREE} | ||
228 | className={classes.featureList} | ||
229 | /> | ||
230 | </PlanItem> | ||
231 | <PlanItem | ||
232 | name={i18nPlanName(plans.pro.yearly.id, intl)} | ||
233 | text={intl.formatMessage(messages.textProfessional)} | ||
234 | price={plans.pro.yearly.price} | ||
235 | currency={currency} | ||
236 | ctaLabel={intl.formatMessage(hadSubscription ? messages.shortActionPro : messages.actionTrial)} | ||
237 | upgrade={() => upgradeAccount(plans.pro.yearly.id)} | ||
238 | className={classes.featuredPlan} | ||
239 | perUser | ||
240 | bestValue | ||
241 | > | ||
242 | <FeatureList | ||
243 | plan={PLANS.PRO} | ||
244 | className={classes.featureList} | ||
245 | /> | ||
246 | </PlanItem> | ||
247 | <PlanItem | ||
248 | name={i18nPlanName(plans.personal.yearly.id, intl)} | ||
249 | text={intl.formatMessage(messages.textPersonal)} | ||
250 | price={plans.personal.yearly.price} | ||
251 | currency={currency} | ||
252 | ctaLabel={intl.formatMessage(hadSubscription ? messages.shortActionPersonal : messages.actionTrial)} | ||
253 | upgrade={() => upgradeAccount(plans.personal.yearly.id)} | ||
254 | > | ||
255 | <FeatureList | ||
256 | plan={PLANS.PERSONAL} | ||
257 | className={classes.featureList} | ||
258 | /> | ||
259 | </PlanItem> | ||
260 | </div> | ||
261 | <div className={classes.footer}> | ||
262 | <a | ||
263 | href="https://meetfranz.com/pricing" | ||
264 | target="_blank" | ||
265 | className={classes.fullFeatureList} | ||
266 | > | ||
267 | <Icon icon={mdiArrowRight} /> | ||
268 | {intl.formatMessage(messages.fullFeatureList)} | ||
269 | </a> | ||
270 | {/* <p className={classes.disclaimer}> */} | ||
271 | {intl.formatMessage(messages.pricesBasedOnAnnualPayment)} | ||
272 | {/* </p> */} | ||
273 | </div> | ||
274 | </div> | ||
275 | </div> | ||
276 | </Appear> | ||
277 | ); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | export default PlanSelection; | ||