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