diff options
author | Stefan Malzner <stefan@adlk.io> | 2019-08-08 19:50:17 +0200 |
---|---|---|
committer | Stefan Malzner <stefan@adlk.io> | 2019-08-08 19:50:17 +0200 |
commit | 524d55f46e3834a84db17945eaa1c65891f06547 (patch) | |
tree | e7b1e5dcd77d1b094fd5bc911e75bf40c47862cc /src/components/subscription | |
parent | Fix service restriction on pro plan (diff) | |
download | ferdium-app-524d55f46e3834a84db17945eaa1c65891f06547.tar.gz ferdium-app-524d55f46e3834a84db17945eaa1c65891f06547.tar.zst ferdium-app-524d55f46e3834a84db17945eaa1c65891f06547.zip |
Add option to subscribe to trial via account dashboard
Diffstat (limited to 'src/components/subscription')
-rw-r--r-- | src/components/subscription/SubscriptionForm.js | 238 |
1 files changed, 59 insertions, 179 deletions
diff --git a/src/components/subscription/SubscriptionForm.js b/src/components/subscription/SubscriptionForm.js index 50f1e0522..0c630f047 100644 --- a/src/components/subscription/SubscriptionForm.js +++ b/src/components/subscription/SubscriptionForm.js | |||
@@ -1,214 +1,94 @@ | |||
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 } 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'; | ||
11 | import { FeatureItem } from '../ui/FeatureItem'; | ||
12 | 12 | ||
13 | const messages = defineMessages({ | 13 | const messages = defineMessages({ |
14 | submitButtonLabel: { | 14 | submitButtonLabel: { |
15 | id: 'subscription.submit.label', | 15 | id: 'subscription.cta.activateTrial', |
16 | defaultMessage: '!!!Support the development of Franz', | 16 | defaultMessage: '!!!Yes, upgrade my account to Franz Professional', |
17 | }, | ||
18 | paymentSessionError: { | ||
19 | id: 'subscription.paymentSessionError', | ||
20 | defaultMessage: '!!!Could not initialize payment form', | ||
21 | }, | ||
22 | typeFree: { | ||
23 | id: 'subscription.type.free', | ||
24 | defaultMessage: '!!!free', | ||
25 | }, | ||
26 | typeMonthly: { | ||
27 | id: 'subscription.type.month', | ||
28 | defaultMessage: '!!!month', | ||
29 | }, | ||
30 | typeYearly: { | ||
31 | id: 'subscription.type.year', | ||
32 | defaultMessage: '!!!year', | ||
33 | }, | 17 | }, |
34 | includedFeatures: { | 18 | includedFeatures: { |
35 | id: 'subscription.includedFeatures', | 19 | id: 'subscription.includedProFeatures', |
36 | defaultMessage: '!!!The Franz Premium Supporter Account includes', | 20 | defaultMessage: '!!!The Franz Professional Plan includes:', |
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 | }, | 21 | }, |
46 | proxy: { | 22 | noStringsAttachedHeadline: { |
47 | id: 'subscription.features.proxy', | 23 | id: 'pricing.trial.terms.headline', |
48 | defaultMessage: '!!!Proxy support for services', | 24 | defaultMessage: '!!!No strings attached', |
49 | }, | 25 | }, |
50 | spellchecker: { | 26 | noCreditCard: { |
51 | id: 'subscription.features.spellchecker', | 27 | id: 'pricing.trial.terms.noCreditCard', |
52 | defaultMessage: '!!!Support for Spellchecker', | 28 | defaultMessage: '!!!No credit card required', |
53 | }, | 29 | }, |
54 | workspaces: { | 30 | automaticTrialEnd: { |
55 | id: 'subscription.features.workspaces', | 31 | id: 'pricing.trial.terms.automaticTrialEnd', |
56 | defaultMessage: '!!!Organize your services in workspaces', | 32 | defaultMessage: '!!!Your free trial ends automatically after 14 days', |
57 | }, | 33 | }, |
58 | ads: { | 34 | }); |
59 | id: 'subscription.features.ads', | 35 | |
60 | defaultMessage: '!!!No ads, ever!', | 36 | const styles = () => ({ |
61 | }, | 37 | activateTrialButton: { |
62 | comingSoon: { | 38 | margin: [40, 0, 50], |
63 | id: 'subscription.features.comingSoon', | ||
64 | defaultMessage: '!!!coming soon', | ||
65 | }, | 39 | }, |
66 | euTaxInfo: { | 40 | keyTerms: { |
67 | id: 'subscription.euTaxInfo', | 41 | marginTop: 20, |
68 | defaultMessage: '!!!EU residents: local sales tax may apply', | ||
69 | }, | 42 | }, |
70 | }); | 43 | }); |
71 | 44 | ||
72 | export default @observer class SubscriptionForm extends Component { | 45 | export default @observer @injectSheet(styles) class SubscriptionForm extends Component { |
73 | static propTypes = { | 46 | static propTypes = { |
74 | plan: MobxPropTypes.objectOrObservableObject.isRequired, | 47 | activateTrial: PropTypes.func.isRequired, |
75 | isLoading: PropTypes.bool.isRequired, | 48 | isActivatingTrial: PropTypes.bool.isRequired, |
76 | handlePayment: PropTypes.func.isRequired, | 49 | 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 | }; | 50 | }; |
91 | 51 | ||
92 | static contextTypes = { | 52 | static contextTypes = { |
93 | intl: intlShape, | 53 | intl: intlShape, |
94 | }; | 54 | }; |
95 | 55 | ||
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() { | 56 | render() { |
134 | const { | 57 | const { |
135 | isLoading, | 58 | isActivatingTrial, |
136 | isCreatingHostedPage, | 59 | activateTrial, |
137 | handlePayment, | 60 | classes, |
138 | retryPlanRequest, | ||
139 | error, | ||
140 | showSkipOption, | ||
141 | skipAction, | ||
142 | skipButtonLabel, | ||
143 | hideInfo, | ||
144 | } = this.props; | 61 | } = this.props; |
145 | const { intl } = this.context; | 62 | const { intl } = this.context; |
146 | 63 | ||
147 | if (error) { | 64 | console.log('isActivatingTrial', isActivatingTrial); |
148 | return ( | ||
149 | <Button | ||
150 | label="Reload" | ||
151 | onClick={retryPlanRequest} | ||
152 | isLoaded={!isLoading} | ||
153 | /> | ||
154 | ); | ||
155 | } | ||
156 | 65 | ||
157 | return ( | 66 | return ( |
158 | <Loader loaded={!isLoading}> | 67 | <> |
159 | <Radio field={this.form.$('paymentTier')} showLabel={false} className="paymentTiers" /> | 68 | <H3 className={classes.keyTerms}> |
160 | {!hideInfo && ( | 69 | {intl.formatMessage(messages.noStringsAttachedHeadline)} |
161 | <div className="subscription__premium-info"> | 70 | </H3> |
162 | <p> | 71 | <ul> |
163 | <strong>{intl.formatMessage(messages.includedFeatures)}</strong> | 72 | <FeatureItem icon="👉" name={intl.formatMessage(messages.noCreditCard)} /> |
164 | </p> | 73 | <FeatureItem icon="👉" name={intl.formatMessage(messages.automaticTrialEnd)} /> |
165 | <div className="subscription"> | 74 | </ul> |
166 | <ul className="subscription__premium-features"> | 75 | |
167 | <li>{intl.formatMessage(messages.onpremise)}</li> | 76 | <Button |
168 | <li> | 77 | label={intl.formatMessage(messages.submitButtonLabel)} |
169 | {intl.formatMessage(messages.noInterruptions)} | 78 | className={classes.activateTrialButton} |
170 | </li> | 79 | busy={isActivatingTrial} |
171 | <li> | 80 | onClick={activateTrial} |
172 | {intl.formatMessage(messages.spellchecker)} | 81 | stretch |
173 | </li> | 82 | /> |
174 | <li> | 83 | <div className="subscription__premium-info"> |
175 | {intl.formatMessage(messages.proxy)} | 84 | <H3> |
176 | </li> | 85 | {intl.formatMessage(messages.includedFeatures)} |
177 | <li> | 86 | </H3> |
178 | {intl.formatMessage(messages.workspaces)} | 87 | <div className="subscription"> |
179 | </li> | 88 | <FeatureList /> |
180 | <li> | ||
181 | {intl.formatMessage(messages.ads)} | ||
182 | </li> | ||
183 | </ul> | ||
184 | </div> | ||
185 | </div> | 89 | </div> |
186 | )} | 90 | </div> |
187 | <Fragment> | 91 | </> |
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 | ); | 92 | ); |
213 | } | 93 | } |
214 | } | 94 | } |