aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/subscription/SubscriptionForm.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/subscription/SubscriptionForm.js')
-rw-r--r--src/components/subscription/SubscriptionForm.js238
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 @@
1import React, { Component, Fragment } from 'react'; 1import React, { Component } from 'react';
2import PropTypes from 'prop-types'; 2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; 3import { observer } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl'; 4import { defineMessages, intlShape } from 'react-intl';
5import injectSheet from 'react-jss';
5 6
6import Form from '../../lib/Form'; 7import { H3 } from '@meetfranz/ui';
7import Radio from '../ui/Radio';
8import Button from '../ui/Button';
9import Loader from '../ui/Loader';
10 8
11import { required } from '../../helpers/validation-helpers'; 9import { Button } from '@meetfranz/forms';
10import { FeatureList } from '../ui/FeatureList';
11import { FeatureItem } from '../ui/FeatureItem';
12 12
13const messages = defineMessages({ 13const 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!', 36const 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
72export default @observer class SubscriptionForm extends Component { 45export 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}