2019-01-28 20:25:59 +05:30
|
|
|
import React, { Component } from 'react';
|
2018-06-07 23:13:33 +01:00
|
|
|
import PropTypes from 'prop-types';
|
2019-02-07 19:03:18 +05:30
|
|
|
import { connect } from 'react-redux';
|
|
|
|
import { createSelector } from 'reselect';
|
2019-11-06 19:02:20 +05:30
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
Tabs,
|
|
|
|
Tab,
|
|
|
|
Row,
|
|
|
|
Col,
|
|
|
|
ToggleButtonGroup,
|
|
|
|
ToggleButton,
|
|
|
|
Radio
|
|
|
|
} from '@freecodecamp/react-bootstrap';
|
2019-11-05 19:23:36 +05:30
|
|
|
import { StripeProvider, Elements } from 'react-stripe-elements';
|
|
|
|
import { apiLocation } from '../../../../config/env.json';
|
2019-11-06 19:02:20 +05:30
|
|
|
import Spacer from '../../helpers/Spacer';
|
2019-11-05 19:23:36 +05:30
|
|
|
import DonateFormChildViewForHOC from './DonateFormChildViewForHOC';
|
2019-01-31 23:40:23 +05:30
|
|
|
import {
|
2019-11-05 19:23:36 +05:30
|
|
|
userSelector,
|
|
|
|
isSignedInSelector,
|
|
|
|
signInLoadingSelector,
|
|
|
|
hardGoTo as navigate
|
|
|
|
} from '../../../redux';
|
2019-01-31 23:40:23 +05:30
|
|
|
|
2019-11-05 19:23:36 +05:30
|
|
|
import '../Donation.css';
|
2019-11-06 19:02:20 +05:30
|
|
|
import DonateCompletion from './DonateCompletion.js';
|
|
|
|
|
|
|
|
const numToCommas = num =>
|
|
|
|
num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
|
2018-06-07 23:13:33 +01:00
|
|
|
|
|
|
|
const propTypes = {
|
2019-11-13 19:40:49 +05:30
|
|
|
enableDonationSettingsPage: PropTypes.func.isRequired,
|
2019-11-06 19:02:20 +05:30
|
|
|
isDonating: PropTypes.bool,
|
2019-02-16 08:20:53 +00:00
|
|
|
isSignedIn: PropTypes.bool,
|
2019-11-05 19:23:36 +05:30
|
|
|
navigate: PropTypes.func.isRequired,
|
|
|
|
showLoading: PropTypes.bool.isRequired,
|
2018-06-07 23:13:33 +01:00
|
|
|
stripe: PropTypes.shape({
|
|
|
|
createToken: PropTypes.func.isRequired
|
2019-11-05 19:23:36 +05:30
|
|
|
})
|
2018-06-07 23:13:33 +01:00
|
|
|
};
|
|
|
|
|
2019-02-07 19:03:18 +05:30
|
|
|
const mapStateToProps = createSelector(
|
|
|
|
userSelector,
|
2019-11-05 19:23:36 +05:30
|
|
|
signInLoadingSelector,
|
2019-02-07 19:03:18 +05:30
|
|
|
isSignedInSelector,
|
2019-11-06 19:02:20 +05:30
|
|
|
({ isDonating }, showLoading, isSignedIn) => ({
|
|
|
|
isDonating,
|
|
|
|
isSignedIn,
|
|
|
|
showLoading
|
2019-11-05 19:23:36 +05:30
|
|
|
})
|
2019-02-07 19:03:18 +05:30
|
|
|
);
|
|
|
|
|
2019-11-05 19:23:36 +05:30
|
|
|
const mapDispatchToProps = {
|
|
|
|
navigate
|
|
|
|
};
|
|
|
|
|
|
|
|
const createOnClick = navigate => e => {
|
|
|
|
e.preventDefault();
|
|
|
|
return navigate(`${apiLocation}/signin?returnTo=donate`);
|
|
|
|
};
|
2019-11-06 19:02:20 +05:30
|
|
|
|
2018-11-07 18:16:50 +00:00
|
|
|
class DonateForm extends Component {
|
2018-06-07 23:13:33 +01:00
|
|
|
constructor(...args) {
|
|
|
|
super(...args);
|
|
|
|
|
|
|
|
this.state = {
|
2019-11-06 19:02:20 +05:30
|
|
|
processing: false,
|
|
|
|
isDonating: this.props.isDonating,
|
|
|
|
donationAmount: 5000,
|
|
|
|
donationDuration: 'month',
|
|
|
|
paymentType: 'Card'
|
|
|
|
};
|
|
|
|
|
|
|
|
this.durations = {
|
|
|
|
year: 'yearly',
|
|
|
|
month: 'monthly',
|
|
|
|
onetime: 'one-time'
|
2018-06-07 23:13:33 +01:00
|
|
|
};
|
2019-11-06 19:02:20 +05:30
|
|
|
this.amounts = {
|
|
|
|
year: [100000, 25000, 3500],
|
|
|
|
month: [5000, 3500, 500],
|
|
|
|
onetime: [100000, 25000, 3500]
|
|
|
|
};
|
|
|
|
|
|
|
|
this.getActiveDonationAmount = this.getActiveDonationAmount.bind(this);
|
|
|
|
this.getDonationButtonLabel = this.getDonationButtonLabel.bind(this);
|
|
|
|
this.handleSelectAmount = this.handleSelectAmount.bind(this);
|
|
|
|
this.handleSelectDuration = this.handleSelectDuration.bind(this);
|
|
|
|
this.handleSelectPaymentType = this.handleSelectPaymentType.bind(this);
|
|
|
|
this.hideAmountOptionsCB = this.hideAmountOptionsCB.bind(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
getActiveDonationAmount(durationSelected, amountSelected) {
|
|
|
|
return this.amounts[durationSelected].includes(amountSelected)
|
|
|
|
? amountSelected
|
|
|
|
: this.amounts[durationSelected][0];
|
|
|
|
}
|
|
|
|
|
2019-11-19 14:39:56 +05:30
|
|
|
convertToTimeContributed(amount, duration) {
|
|
|
|
const timeContributed =
|
|
|
|
duration === 'month'
|
|
|
|
? Math.round(((amount / 100) * 50) / 12)
|
|
|
|
: (amount / 100) * 50;
|
|
|
|
return `${numToCommas(timeContributed)} hours`;
|
2019-11-06 19:02:20 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
getFormatedAmountLabel(amount) {
|
|
|
|
return `$${numToCommas(amount / 100)}`;
|
|
|
|
}
|
2018-06-07 23:13:33 +01:00
|
|
|
|
2019-11-06 19:02:20 +05:30
|
|
|
getDonationButtonLabel() {
|
|
|
|
const { donationAmount, donationDuration } = this.state;
|
|
|
|
let donationBtnLabel = `Confirm your donation`;
|
|
|
|
if (donationDuration === 'onetime') {
|
|
|
|
donationBtnLabel = `Confirm your one-time donation of ${this.getFormatedAmountLabel(
|
|
|
|
donationAmount
|
|
|
|
)}`;
|
|
|
|
} else {
|
|
|
|
donationBtnLabel = `Confirm your donation of ${this.getFormatedAmountLabel(
|
|
|
|
donationAmount
|
|
|
|
)} ${donationDuration === 'month' ? 'per month' : 'per year'}`;
|
|
|
|
}
|
|
|
|
return donationBtnLabel;
|
|
|
|
}
|
|
|
|
|
|
|
|
handleSelectDuration(donationDuration) {
|
|
|
|
const donationAmount = this.getActiveDonationAmount(donationDuration, 0);
|
|
|
|
this.setState({ donationDuration, donationAmount });
|
|
|
|
}
|
2019-01-31 23:40:23 +05:30
|
|
|
|
2019-11-06 19:02:20 +05:30
|
|
|
handleSelectAmount(donationAmount) {
|
|
|
|
this.setState({ donationAmount });
|
2019-01-31 23:40:23 +05:30
|
|
|
}
|
|
|
|
|
2019-11-06 19:02:20 +05:30
|
|
|
handleSelectPaymentType(e) {
|
|
|
|
this.setState({
|
|
|
|
paymentType: e.currentTarget.value
|
|
|
|
});
|
2018-06-07 23:13:33 +01:00
|
|
|
}
|
|
|
|
|
2019-11-06 19:02:20 +05:30
|
|
|
renderAmountButtons(duration) {
|
|
|
|
return this.amounts[duration].map(amount => (
|
|
|
|
<ToggleButton
|
|
|
|
className='amount-value'
|
|
|
|
id={`${this.durations[duration]}-donation-${amount}`}
|
|
|
|
key={`${this.durations[duration]}-donation-${amount}`}
|
|
|
|
value={amount}
|
2019-11-05 19:23:36 +05:30
|
|
|
>
|
2019-11-06 19:02:20 +05:30
|
|
|
{this.getFormatedAmountLabel(amount)}
|
|
|
|
</ToggleButton>
|
2019-11-05 19:23:36 +05:30
|
|
|
));
|
2018-06-07 23:13:33 +01:00
|
|
|
}
|
|
|
|
|
2019-11-06 19:02:20 +05:30
|
|
|
renderDurationAmountOptions() {
|
|
|
|
const { donationAmount, donationDuration, processing } = this.state;
|
|
|
|
return !processing ? (
|
|
|
|
<div>
|
|
|
|
<h3>Duration and amount:</h3>
|
|
|
|
<Tabs
|
|
|
|
activeKey={donationDuration}
|
|
|
|
animation={false}
|
|
|
|
bsStyle='pills'
|
|
|
|
className='donate-tabs'
|
|
|
|
id='Duration'
|
|
|
|
onSelect={this.handleSelectDuration}
|
|
|
|
>
|
|
|
|
{Object.keys(this.durations).map(duration => (
|
|
|
|
<Tab
|
|
|
|
eventKey={duration}
|
|
|
|
key={duration}
|
|
|
|
title={this.durations[duration]}
|
|
|
|
>
|
|
|
|
<Spacer />
|
|
|
|
<div>
|
|
|
|
<ToggleButtonGroup
|
|
|
|
animation={`false`}
|
|
|
|
className='amount-values'
|
|
|
|
name='amounts'
|
|
|
|
onChange={this.handleSelectAmount}
|
|
|
|
type='radio'
|
|
|
|
value={this.getActiveDonationAmount(duration, donationAmount)}
|
|
|
|
>
|
|
|
|
{this.renderAmountButtons(duration)}
|
|
|
|
</ToggleButtonGroup>
|
|
|
|
<Spacer />
|
|
|
|
<p>
|
|
|
|
{`Your `}
|
|
|
|
{this.getFormatedAmountLabel(donationAmount)}
|
|
|
|
{` donation will provide `}
|
2019-11-19 14:39:56 +05:30
|
|
|
{this.convertToTimeContributed(donationAmount, duration)}
|
|
|
|
{` of learning to people around the world`}
|
|
|
|
{duration === 'onetime' ? `.` : ` each ${duration}.`}
|
2019-11-06 19:02:20 +05:30
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
</Tab>
|
|
|
|
))}
|
|
|
|
</Tabs>
|
|
|
|
</div>
|
|
|
|
) : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
hideAmountOptionsCB(hide) {
|
|
|
|
this.setState({ processing: hide });
|
|
|
|
}
|
|
|
|
|
|
|
|
renderDonationOptions() {
|
2019-11-13 19:40:49 +05:30
|
|
|
const { stripe, enableDonationSettingsPage } = this.props;
|
2019-11-06 19:02:20 +05:30
|
|
|
const {
|
|
|
|
donationAmount,
|
|
|
|
donationDuration,
|
|
|
|
paymentType,
|
|
|
|
processing
|
|
|
|
} = this.state;
|
|
|
|
return (
|
|
|
|
<div>
|
|
|
|
{!processing ? (
|
|
|
|
<div>
|
|
|
|
<Radio
|
|
|
|
checked={paymentType === 'Card'}
|
|
|
|
name='payment-method'
|
|
|
|
onChange={this.handleSelectPaymentType}
|
|
|
|
value='Card'
|
|
|
|
>
|
|
|
|
Donate using a Credit/Debit Card.
|
|
|
|
</Radio>
|
|
|
|
<Radio
|
|
|
|
checked={paymentType === 'PayPal'}
|
|
|
|
// disable the paypal integration for now
|
|
|
|
disabled={true}
|
|
|
|
name='payment-method'
|
|
|
|
onChange={this.handleSelectPaymentType}
|
|
|
|
value='PayPal'
|
|
|
|
>
|
|
|
|
Donate using PayPal. (Coming soon)
|
|
|
|
</Radio>
|
|
|
|
<Spacer />
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{paymentType === 'Card' ? (
|
|
|
|
<StripeProvider stripe={stripe}>
|
|
|
|
<Elements>
|
|
|
|
<DonateFormChildViewForHOC
|
|
|
|
donationAmount={donationAmount}
|
|
|
|
donationDuration={donationDuration}
|
2019-11-13 19:40:49 +05:30
|
|
|
enableDonationSettingsPage={enableDonationSettingsPage}
|
2019-11-06 19:02:20 +05:30
|
|
|
getDonationButtonLabel={this.getDonationButtonLabel}
|
|
|
|
hideAmountOptionsCB={this.hideAmountOptionsCB}
|
|
|
|
/>
|
|
|
|
</Elements>
|
|
|
|
</StripeProvider>
|
|
|
|
) : (
|
|
|
|
<p>
|
|
|
|
PayPal is currently unavailable. Please use a Credit/Debit card
|
|
|
|
instead.
|
|
|
|
</p>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-11-05 19:23:36 +05:30
|
|
|
render() {
|
2019-11-06 19:02:20 +05:30
|
|
|
const { isSignedIn, navigate, showLoading, isDonating } = this.props;
|
2019-11-05 19:23:36 +05:30
|
|
|
|
2019-11-06 19:02:20 +05:30
|
|
|
if (isDonating) {
|
2019-11-05 19:23:36 +05:30
|
|
|
return (
|
2019-11-06 19:02:20 +05:30
|
|
|
<Row>
|
|
|
|
<Col sm={10} smOffset={1} xs={12}>
|
|
|
|
<DonateCompletion success={true} />
|
|
|
|
</Col>
|
|
|
|
</Row>
|
2019-11-05 19:23:36 +05:30
|
|
|
);
|
2018-06-07 23:13:33 +01:00
|
|
|
}
|
2019-02-07 19:03:18 +05:30
|
|
|
|
2018-06-07 23:13:33 +01:00
|
|
|
return (
|
2019-11-06 19:02:20 +05:30
|
|
|
<Row>
|
|
|
|
<Col sm={10} smOffset={1} xs={12}>
|
|
|
|
{this.renderDurationAmountOptions()}
|
|
|
|
</Col>
|
|
|
|
<Col sm={10} smOffset={1} xs={12}>
|
|
|
|
{!showLoading && !isSignedIn ? (
|
|
|
|
<Button
|
|
|
|
bsStyle='default'
|
|
|
|
className='btn btn-block'
|
|
|
|
onClick={createOnClick(navigate)}
|
|
|
|
>
|
|
|
|
Become a supporter
|
|
|
|
</Button>
|
|
|
|
) : (
|
|
|
|
this.renderDonationOptions()
|
|
|
|
)}
|
|
|
|
</Col>
|
|
|
|
</Row>
|
2018-06-07 23:13:33 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DonateForm.displayName = 'DonateForm';
|
|
|
|
DonateForm.propTypes = propTypes;
|
|
|
|
|
2019-11-05 19:23:36 +05:30
|
|
|
export default connect(
|
|
|
|
mapStateToProps,
|
|
|
|
mapDispatchToProps
|
|
|
|
)(DonateForm);
|