Skip to content

Instantly share code, notes, and snippets.

@197291
Last active October 26, 2017 06:59
Show Gist options
  • Save 197291/b72c56a578bae34216b945bd0228b54b to your computer and use it in GitHub Desktop.
Save 197291/b72c56a578bae34216b945bd0228b54b to your computer and use it in GitHub Desktop.
Payments container
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import config from 'config';
import Helmet from 'react-helmet';
import { connect } from 'react-redux';
import { injectIntl, intlShape } from 'react-intl';
import CircularProgress from 'material-ui/CircularProgress';
import { SelectPlan, PaymentForm } from 'components/payment';
import { Step, Stepper, StepLabel } from 'material-ui/Stepper';
import * as menuActions from 'redux/modules/menu';
import * as workflowActions from 'redux/modules/workflows';
import * as paymentActions from 'redux/modules/payment';
import * as authActions from 'redux/modules/auth';
import styles from './PaymentStyles';
@injectIntl
@connect(
state => ({
...state.payment,
user: state.auth.user,
etagWorkflows: state.workflows.etagSimple,
}),
{
changePlan: paymentActions.changePlan,
changePlanItem: paymentActions.changePlanItem,
loadPlans: paymentActions.loadPlans,
changeViwe: paymentActions.changeViwe,
errorCreateToken: paymentActions.errorCreateToken,
startCreateToken: paymentActions.startCreateToken,
create: paymentActions.create,
cleanup: paymentActions.cleanup,
cancel: paymentActions.showCancelConfirm,
upgrade: paymentActions.upgrade,
loadUser: authActions.load,
loadSimple: workflowActions.loadSimple,
loadStarted: menuActions.loadStarted,
loadRecent: menuActions.loadRecent,
})
export default class Payment extends Component {
static propTypes = {
intl: intlShape.isRequired,
user: PropTypes.object.isRequired,
planId: PropTypes.string.isRequired,
planItemId: PropTypes.string.isRequired,
plans: PropTypes.array.isRequired,
etagPlans: PropTypes.string.isRequired,
viewIndex: PropTypes.number.isRequired,
loadingCreate: PropTypes.bool.isRequired,
loadingCancel: PropTypes.bool.isRequired,
loadingUpgrade: PropTypes.bool.isRequired,
errorCreate: PropTypes.any,
errorCancel: PropTypes.any,
errorToken: PropTypes.any,
errorUpgrade: PropTypes.any,
etagWorkflows: PropTypes.string,
changePlan: PropTypes.func.isRequired,
changePlanItem: PropTypes.func.isRequired,
loadPlans: PropTypes.func.isRequired,
changeViwe: PropTypes.func.isRequired,
errorCreateToken: PropTypes.func.isRequired,
startCreateToken: PropTypes.func.isRequired,
create: PropTypes.func.isRequired,
cleanup: PropTypes.func.isRequired,
cancel: PropTypes.func.isRequired,
upgrade: PropTypes.func.isRequired,
loadUser: PropTypes.func.isRequired,
loadSimple: PropTypes.func.isRequired,
loadStarted: PropTypes.func.isRequired,
loadRecent: PropTypes.func.isRequired,
};
componentDidMount() {
this.props.loadPlans(this.props.etagPlans);
window.Stripe.setPublishableKey(config.stripeKey);
}
componentWillReceiveProps(nextProps) {
const { loadingCreate, loadingCancel, loadingUpgrade, cleanup, loadUser, loadSimple, etagWorkflows, loadStarted, loadRecent } = this.props;
if (loadingCreate && !nextProps.loadingCreate && !nextProps.errorCreate) {
loadUser(); // subscription created reload to initial state
loadSimple({etag: etagWorkflows});
loadStarted();
loadRecent();
cleanup();
}
if (loadingCancel && !nextProps.loadingCancel && !nextProps.errorCancel) {
loadUser(); // subscription canceled reload to initial state
loadSimple({etag: etagWorkflows});
cleanup();
}
if (loadingUpgrade && !nextProps.loadingUpgrade && !nextProps.errorUpgrade) {
loadUser(); // subscription canceled reload to initial state
cleanup();
}
}
componentWillUnmount() {
this.props.cleanup();
}
_handelSelectPaymentMethodView = () => {
const { user, planItemId, upgrade, changeViwe } = this.props;
const isSubscriber = user.isSubscriber && user.plan !== 'trial';
if (isSubscriber) {
upgrade(planItemId);
return;
}
changeViwe(1);
};
_handelSelectPlanMethod = () => {
this.props.changeViwe(0);
};
_handelSubscription = (data) => {
const { startCreateToken, errorCreateToken, create, planItemId } = this.props;
const card = {};
Object.keys(data).forEach((key) => {
card[key] = data[key].replace(/[^\d]/g, '');
});
startCreateToken();
window.Stripe.createToken( card, (status, response) => {
if (response.error) {
return errorCreateToken(response.error.message);
}
create({
token: response.id,
planIn: planItemId
});
});
};
render() {
const { viewIndex, planId, planItemId, intl: { formatMessage }, changePlan, changePlanItem, user, plans, errorToken, cancel,
loadingCreate, loadingCancel, loadingUpgrade, changeViwe } = this.props;
const isSubscriber = user.isSubscriber && user.plan !== 'trial';
return (
<div style={styles.wrapper}>
<Helmet title={formatMessage({ id: 'billing.page.title' })}/>
{ !user.isTeamOwner &&
<h2>
{formatMessage({id: 'billing.page.onlyTeamOwnerMessage'})}
</h2>
}
{ !loadingCancel && !loadingUpgrade && isSubscriber &&
<h2>
{formatMessage({id: 'billing.plan.manageSubscriptionLabel'})}
</h2>
}
{ !loadingCancel && !loadingUpgrade && !isSubscriber &&
<Stepper activeStep={viewIndex}>
<Step>
<StepLabel>
{formatMessage({ id: 'billing.plan.selectPlanLabel' })}
</StepLabel>
</Step>
<Step active={!isSubscriber}>
<StepLabel>
{formatMessage({ id: 'billing.form.title' })}
</StepLabel>
</Step>
</Stepper>
}
{ user.plan === 'trial' &&
<p style={styles.trialLabel}>
{formatMessage({ id: 'billing.plan.trialLabel' })}
</p>
}
{ viewIndex === 0 && !loadingCancel && !loadingUpgrade && user.isTeamOwner &&
<SelectPlan
formatMessage={formatMessage}
plans={plans}
planId={planId}
planItemId={planItemId}
handelChangePlan={changePlan}
handelChangePlanItem={changePlanItem}
cancel={cancel}
changeView={this._handelSelectPaymentMethodView}
user={user}/>
}
{ viewIndex === 1 && !loadingCreate && user.isTeamOwner &&
<PaymentForm
onSubmit={this._handelSubscription}
errorToken={errorToken}
formatMessage={formatMessage}
viewIndex={viewIndex}
handlePrev={() => { changeViwe(0); }}/>
}
{( loadingCreate || loadingCancel || loadingUpgrade ) && user.isTeamOwner &&
<div style={styles.circularWrapper}>
<div style={styles.circular}>
<CircularProgress size={1.4}/>
</div>
</div>
}
</div>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment