diff options
Diffstat (limited to 'src/components/subscription/SubscriptionForm.js')
-rw-r--r-- | src/components/subscription/SubscriptionForm.js | 226 |
1 files changed, 45 insertions, 181 deletions
diff --git a/src/components/subscription/SubscriptionForm.js b/src/components/subscription/SubscriptionForm.js index 8c7dceece..cdfbbe60d 100644 --- a/src/components/subscription/SubscriptionForm.js +++ b/src/components/subscription/SubscriptionForm.js | |||
@@ -1,214 +1,78 @@ | |||
1 | import React, { Component, Fragment } from 'react'; | 1 | import React, { Component } from 'react'; |
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; | 3 | import { observer } from 'mobx-react'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
5 | import injectSheet from 'react-jss'; | ||
5 | 6 | ||
6 | import Form from '../../lib/Form'; | 7 | import { H3, H2 } from '@meetfranz/ui'; |
7 | import Radio from '../ui/Radio'; | ||
8 | import Button from '../ui/Button'; | ||
9 | import Loader from '../ui/Loader'; | ||
10 | 8 | ||
11 | import { required } from '../../helpers/validation-helpers'; | 9 | import { Button } from '@meetfranz/forms'; |
10 | import { FeatureList } from '../ui/FeatureList'; | ||
12 | 11 | ||
13 | const messages = defineMessages({ | 12 | const messages = defineMessages({ |
14 | submitButtonLabel: { | 13 | submitButtonLabel: { |
15 | id: 'subscription.submit.label', | 14 | id: 'subscription.cta.choosePlan', |
16 | defaultMessage: '!!!Support the development of Franz', | 15 | defaultMessage: '!!!Choose your plan', |
17 | }, | 16 | }, |
18 | paymentSessionError: { | 17 | teaserHeadline: { |
19 | id: 'subscription.paymentSessionError', | 18 | id: 'settings.account.headlineUpgradeAccount', |
20 | defaultMessage: '!!!Could not initialize payment form', | 19 | defaultMessage: '!!!Upgrade your account and get the full Franz experience', |
21 | }, | 20 | }, |
22 | typeFree: { | 21 | teaserText: { |
23 | id: 'subscription.type.free', | 22 | id: 'subscription.teaser.intro', |
24 | defaultMessage: '!!!free', | 23 | defaultMessage: '!!!Franz 5 comes with a wide range of new features to boost up your everyday communication - batteries included. Check out our new plans and find out which one suits you most!', |
25 | }, | ||
26 | typeMonthly: { | ||
27 | id: 'subscription.type.month', | ||
28 | defaultMessage: '!!!month', | ||
29 | }, | ||
30 | typeYearly: { | ||
31 | id: 'subscription.type.year', | ||
32 | defaultMessage: '!!!year', | ||
33 | }, | 24 | }, |
34 | includedFeatures: { | 25 | includedFeatures: { |
35 | id: 'subscription.includedFeatures', | 26 | id: 'subscription.teaser.includedFeatures', |
36 | defaultMessage: '!!!The Ferdi Premium Supporter Account includes', | 27 | defaultMessage: '!!!Paid Franz Plans include:', |
37 | }, | ||
38 | onpremise: { | ||
39 | id: 'subscription.features.onpremise.mattermost', | ||
40 | defaultMessage: '!!!Add on-premise/hosted services like Mattermost', | ||
41 | }, | ||
42 | noInterruptions: { | ||
43 | id: 'subscription.features.noInterruptions', | ||
44 | defaultMessage: '!!!No app delays & nagging to upgrade license', | ||
45 | }, | ||
46 | proxy: { | ||
47 | id: 'subscription.features.proxy', | ||
48 | defaultMessage: '!!!Proxy support for services', | ||
49 | }, | ||
50 | spellchecker: { | ||
51 | id: 'subscription.features.spellchecker', | ||
52 | defaultMessage: '!!!Support for Spellchecker', | ||
53 | }, | 28 | }, |
54 | workspaces: { | 29 | }); |
55 | id: 'subscription.features.workspaces', | 30 | |
56 | defaultMessage: '!!!Organize your services in workspaces', | 31 | const styles = () => ({ |
57 | }, | 32 | activateTrialButton: { |
58 | ads: { | 33 | margin: [40, 0, 50], |
59 | id: 'subscription.features.ads', | ||
60 | defaultMessage: '!!!No ads, ever!', | ||
61 | }, | ||
62 | comingSoon: { | ||
63 | id: 'subscription.features.comingSoon', | ||
64 | defaultMessage: '!!!coming soon', | ||
65 | }, | ||
66 | euTaxInfo: { | ||
67 | id: 'subscription.euTaxInfo', | ||
68 | defaultMessage: '!!!EU residents: local sales tax may apply', | ||
69 | }, | 34 | }, |
70 | }); | 35 | }); |
71 | 36 | ||
72 | export default @observer class SubscriptionForm extends Component { | 37 | export default @observer @injectSheet(styles) class SubscriptionForm extends Component { |
73 | static propTypes = { | 38 | static propTypes = { |
74 | plan: MobxPropTypes.objectOrObservableObject.isRequired, | 39 | selectPlan: PropTypes.func.isRequired, |
75 | isLoading: PropTypes.bool.isRequired, | 40 | isActivatingTrial: PropTypes.bool.isRequired, |
76 | handlePayment: PropTypes.func.isRequired, | 41 | classes: PropTypes.object.isRequired, |
77 | retryPlanRequest: PropTypes.func.isRequired, | ||
78 | isCreatingHostedPage: PropTypes.bool.isRequired, | ||
79 | error: PropTypes.bool.isRequired, | ||
80 | showSkipOption: PropTypes.bool, | ||
81 | skipAction: PropTypes.func, | ||
82 | skipButtonLabel: PropTypes.string, | ||
83 | hideInfo: PropTypes.bool.isRequired, | ||
84 | }; | ||
85 | |||
86 | static defaultProps = { | ||
87 | showSkipOption: false, | ||
88 | skipAction: () => null, | ||
89 | skipButtonLabel: '', | ||
90 | }; | 42 | }; |
91 | 43 | ||
92 | static contextTypes = { | 44 | static contextTypes = { |
93 | intl: intlShape, | 45 | intl: intlShape, |
94 | }; | 46 | }; |
95 | 47 | ||
96 | componentWillMount() { | ||
97 | this.form = this.prepareForm(); | ||
98 | } | ||
99 | |||
100 | prepareForm() { | ||
101 | const { intl } = this.context; | ||
102 | |||
103 | const form = { | ||
104 | fields: { | ||
105 | paymentTier: { | ||
106 | value: 'year', | ||
107 | validators: [required], | ||
108 | options: [{ | ||
109 | value: 'month', | ||
110 | label: `€ ${Object.hasOwnProperty.call(this.props.plan, 'month') | ||
111 | ? `${this.props.plan.month.price} / ${intl.formatMessage(messages.typeMonthly)}` | ||
112 | : 'monthly'}`, | ||
113 | }, { | ||
114 | value: 'year', | ||
115 | label: `€ ${Object.hasOwnProperty.call(this.props.plan, 'year') | ||
116 | ? `${this.props.plan.year.price} / ${intl.formatMessage(messages.typeYearly)}` | ||
117 | : 'yearly'}`, | ||
118 | }], | ||
119 | }, | ||
120 | }, | ||
121 | }; | ||
122 | |||
123 | if (this.props.showSkipOption) { | ||
124 | form.fields.paymentTier.options.unshift({ | ||
125 | value: 'skip', | ||
126 | label: `€ 0 / ${intl.formatMessage(messages.typeFree)}`, | ||
127 | }); | ||
128 | } | ||
129 | |||
130 | return new Form(form, this.context.intl); | ||
131 | } | ||
132 | |||
133 | render() { | 48 | render() { |
134 | const { | 49 | const { |
135 | isLoading, | 50 | isActivatingTrial, |
136 | isCreatingHostedPage, | 51 | selectPlan, |
137 | handlePayment, | 52 | classes, |
138 | retryPlanRequest, | ||
139 | error, | ||
140 | showSkipOption, | ||
141 | skipAction, | ||
142 | skipButtonLabel, | ||
143 | hideInfo, | ||
144 | } = this.props; | 53 | } = this.props; |
145 | const { intl } = this.context; | 54 | const { intl } = this.context; |
146 | 55 | ||
147 | if (error) { | 56 | return ( |
148 | return ( | 57 | <> |
58 | <H2>{intl.formatMessage(messages.teaserHeadline)}</H2> | ||
59 | <p>{intl.formatMessage(messages.teaserText)}</p> | ||
149 | <Button | 60 | <Button |
150 | label="Reload" | 61 | label={intl.formatMessage(messages.submitButtonLabel)} |
151 | onClick={retryPlanRequest} | 62 | className={classes.activateTrialButton} |
152 | isLoaded={!isLoading} | 63 | busy={isActivatingTrial} |
64 | onClick={selectPlan} | ||
65 | stretch | ||
153 | /> | 66 | /> |
154 | ); | 67 | <div className="subscription__premium-info"> |
155 | } | 68 | <H3> |
156 | 69 | {intl.formatMessage(messages.includedFeatures)} | |
157 | return ( | 70 | </H3> |
158 | <Loader loaded={!isLoading}> | 71 | <div className="subscription"> |
159 | <Radio field={this.form.$('paymentTier')} showLabel={false} className="paymentTiers" /> | 72 | <FeatureList /> |
160 | {!hideInfo && ( | ||
161 | <div className="subscription__premium-info"> | ||
162 | <p> | ||
163 | <strong>{intl.formatMessage(messages.includedFeatures)}</strong> | ||
164 | </p> | ||
165 | <div className="subscription"> | ||
166 | <ul className="subscription__premium-features"> | ||
167 | <li>{intl.formatMessage(messages.onpremise)}</li> | ||
168 | <li> | ||
169 | {intl.formatMessage(messages.noInterruptions)} | ||
170 | </li> | ||
171 | <li> | ||
172 | {intl.formatMessage(messages.spellchecker)} | ||
173 | </li> | ||
174 | <li> | ||
175 | {intl.formatMessage(messages.proxy)} | ||
176 | </li> | ||
177 | <li> | ||
178 | {intl.formatMessage(messages.workspaces)} | ||
179 | </li> | ||
180 | <li> | ||
181 | {intl.formatMessage(messages.ads)} | ||
182 | </li> | ||
183 | </ul> | ||
184 | </div> | ||
185 | </div> | 73 | </div> |
186 | )} | 74 | </div> |
187 | <Fragment> | 75 | </> |
188 | {error.code === 'no-payment-session' && ( | ||
189 | <p className="error-message center">{intl.formatMessage(messages.paymentSessionError)}</p> | ||
190 | )} | ||
191 | </Fragment> | ||
192 | {showSkipOption && this.form.$('paymentTier').value === 'skip' ? ( | ||
193 | <Button | ||
194 | label={skipButtonLabel} | ||
195 | className="auth__button" | ||
196 | onClick={skipAction} | ||
197 | /> | ||
198 | ) : ( | ||
199 | <Button | ||
200 | label={intl.formatMessage(messages.submitButtonLabel)} | ||
201 | className="auth__button" | ||
202 | loaded={!isCreatingHostedPage} | ||
203 | onClick={() => handlePayment(this.form.$('paymentTier').value)} | ||
204 | /> | ||
205 | )} | ||
206 | {this.form.$('paymentTier').value !== 'skip' && ( | ||
207 | <p className="legal"> | ||
208 | {intl.formatMessage(messages.euTaxInfo)} | ||
209 | </p> | ||
210 | )} | ||
211 | </Loader> | ||
212 | ); | 76 | ); |
213 | } | 77 | } |
214 | } | 78 | } |