diff --git a/api-server/server/boot/donate.js b/api-server/server/boot/donate.js
index 365fc716ab..f63a4ac4de 100644
--- a/api-server/server/boot/donate.js
+++ b/api-server/server/boot/donate.js
@@ -170,16 +170,6 @@ export default function donateBoot(app, done) {
};
return Promise.resolve(user)
- .then(nonDonatingUser => {
- const { isDonating } = nonDonatingUser;
- if (isDonating) {
- throw {
- message: `User already has active donation(s).`,
- type: 'AlreadyDonatingError'
- };
- }
- return nonDonatingUser;
- })
.then(createCustomer)
.then(customer => {
return duration === 'onetime'
@@ -194,10 +184,7 @@ export default function donateBoot(app, done) {
})
.then(createAsyncUserDonation)
.catch(err => {
- if (
- err.type === 'StripeCardError' ||
- err.type === 'AlreadyDonatingError'
- ) {
+ if (err.type === 'StripeCardError') {
return res.status(402).send({ error: err.message });
}
return res
diff --git a/client/src/client-only-routes/ShowCertification.js b/client/src/client-only-routes/ShowCertification.js
index 7fd0e6b24a..04b35718bb 100644
--- a/client/src/client-only-routes/ShowCertification.js
+++ b/client/src/client-only-routes/ShowCertification.js
@@ -7,7 +7,7 @@ import { createSelector } from 'reselect';
import { Grid, Row, Col, Image, Button } from '@freecodecamp/react-bootstrap';
import FreeCodeCampLogo from '../assets/icons/freeCodeCampLogo';
// eslint-disable-next-line max-len
-import MinimalDonateForm from '../components/Donation/components/MinimalDonateForm';
+import MinimalDonateForm from '../components/Donation/MinimalDonateForm';
import {
showCertSelector,
diff --git a/client/src/components/Donation/components/DonateCompletion.js b/client/src/components/Donation/DonateCompletion.js
similarity index 98%
rename from client/src/components/Donation/components/DonateCompletion.js
rename to client/src/components/Donation/DonateCompletion.js
index 7cfb3a4434..28d6367a0b 100644
--- a/client/src/components/Donation/components/DonateCompletion.js
+++ b/client/src/components/Donation/DonateCompletion.js
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { Alert, Button } from '@freecodecamp/react-bootstrap';
import Spinner from 'react-spinkit';
-import '../Donation.css';
+import './Donation.css';
const propTypes = {
error: PropTypes.string,
diff --git a/client/src/components/Donation/components/DonateForm.js b/client/src/components/Donation/DonateForm.js
similarity index 91%
rename from client/src/components/Donation/components/DonateForm.js
rename to client/src/components/Donation/DonateForm.js
index 573756fd3a..a0cd1fe5b0 100644
--- a/client/src/components/Donation/components/DonateForm.js
+++ b/client/src/components/Donation/DonateForm.js
@@ -18,19 +18,17 @@ import {
durationsConfig,
defaultAmount,
defaultStateConfig
-} from '../../../../../config/donation-settings';
+} from '../../../../config/donation-settings';
import { apiLocation } from '../../../../config/env.json';
-import Spacer from '../../helpers/Spacer';
+import Spacer from '../helpers/Spacer';
import DonateFormChildViewForHOC from './DonateFormChildViewForHOC';
import {
- userSelector,
isSignedInSelector,
signInLoadingSelector,
hardGoTo as navigate
-} from '../../../redux';
+} from '../../redux';
-import '../Donation.css';
-import DonateCompletion from './DonateCompletion.js';
+import './Donation.css';
const numToCommas = num =>
num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
@@ -46,11 +44,9 @@ const propTypes = {
};
const mapStateToProps = createSelector(
- userSelector,
signInLoadingSelector,
isSignedInSelector,
- ({ isDonating }, showLoading, isSignedIn) => ({
- isDonating,
+ (showLoading, isSignedIn) => ({
isSignedIn,
showLoading
})
@@ -74,8 +70,7 @@ class DonateForm extends Component {
this.state = {
...defaultStateConfig,
- processing: false,
- isDonating: this.props.isDonating
+ processing: false
};
this.getActiveDonationAmount = this.getActiveDonationAmount.bind(this);
@@ -222,17 +217,7 @@ class DonateForm extends Component {
}
render() {
- const { isSignedIn, navigate, showLoading, isDonating } = this.props;
-
- if (isDonating) {
- return (
-
-
-
-
-
- );
- }
+ const { isSignedIn, navigate, showLoading } = this.props;
return (
diff --git a/client/src/components/Donation/components/DonateFormChildViewForHOC.js b/client/src/components/Donation/DonateFormChildViewForHOC.js
similarity index 98%
rename from client/src/components/Donation/components/DonateFormChildViewForHOC.js
rename to client/src/components/Donation/DonateFormChildViewForHOC.js
index 7e58e97dae..6a7545644a 100644
--- a/client/src/components/Donation/components/DonateFormChildViewForHOC.js
+++ b/client/src/components/Donation/DonateFormChildViewForHOC.js
@@ -15,8 +15,8 @@ import { injectStripe } from 'react-stripe-elements';
import StripeCardForm from './StripeCardForm';
import DonateCompletion from './DonateCompletion';
-import { postChargeStripe } from '../../../utils/ajax';
-import { userSelector } from '../../../redux';
+import { postChargeStripe } from '../../utils/ajax';
+import { userSelector } from '../../redux';
const propTypes = {
showCloseBtn: PropTypes.func,
diff --git a/client/src/components/Donation/DonateText.js b/client/src/components/Donation/DonateText.js
new file mode 100644
index 0000000000..6898a2c942
--- /dev/null
+++ b/client/src/components/Donation/DonateText.js
@@ -0,0 +1,39 @@
+import React from 'react';
+import { Row, Col } from '@freecodecamp/react-bootstrap';
+
+const DonateText = () => {
+ return (
+
+
+
freeCodeCamp is a highly efficient education nonprofit.
+
+ In 2019 alone, we provided 18 million hours of free education to
+ people around the world.
+
+
+ Since freeCodeCamp's total budget is only $373,000, that means every
+ dollar you donate to freeCodeCamp translates into 50 hours worth of
+ technology education.
+
+
+ When you donate to freeCodeCamp, you help people learn new skills and
+ provide for their families.
+
+
+ You also help us create new resources for you to use to expand your
+ own technology skills.
+
+
+
+ Need help with your existing or past donations?
+
+
+ Send an email to team@freeCodeCamp.org with a copy of your donation
+ receipt and we will be happy to resolve your query.
+
+
+
+ );
+};
+DonateText.displayName = 'DonateText';
+export default DonateText;
diff --git a/client/src/components/Donation/components/DonationModal.js b/client/src/components/Donation/DonationModal.js
similarity index 89%
rename from client/src/components/Donation/components/DonationModal.js
rename to client/src/components/Donation/DonationModal.js
index be69eb997b..ae12ac7981 100644
--- a/client/src/components/Donation/components/DonationModal.js
+++ b/client/src/components/Donation/DonationModal.js
@@ -5,22 +5,22 @@ import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { Modal, Button, Col, Row } from '@freecodecamp/react-bootstrap';
-import { Spacer } from '../../../components/helpers';
-import { blockNameify } from '../../../../utils/blockNameify';
-import Heart from '../../../assets/icons/Heart';
-import Cup from '../../../assets/icons/Cup';
+import { Spacer } from '../helpers';
+import { blockNameify } from '../../../utils/blockNameify';
+import Heart from '../../assets/icons/Heart';
+import Cup from '../../assets/icons/Cup';
import MinimalDonateForm from './MinimalDonateForm';
-import ga from '../../../analytics';
+import ga from '../../analytics';
import {
closeDonationModal,
isDonationModalOpenSelector,
isBlockDonationModalSelector
-} from '../../../redux';
+} from '../../redux';
-import { challengeMetaSelector } from '../../../templates/Challenges/redux';
+import { challengeMetaSelector } from '../../templates/Challenges/redux';
-import '../Donation.css';
+import './Donation.css';
const mapStateToProps = createSelector(
isDonationModalOpenSelector,
diff --git a/client/src/components/Donation/components/MinimalDonateForm.js b/client/src/components/Donation/MinimalDonateForm.js
similarity index 50%
rename from client/src/components/Donation/components/MinimalDonateForm.js
rename to client/src/components/Donation/MinimalDonateForm.js
index 56d9368de2..1b32441f73 100644
--- a/client/src/components/Donation/components/MinimalDonateForm.js
+++ b/client/src/components/Donation/MinimalDonateForm.js
@@ -1,5 +1,3 @@
-/* eslint-disable react/sort-prop-types */
-/* eslint-disable react/jsx-sort-props */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
@@ -10,23 +8,19 @@ import { StripeProvider, Elements } from 'react-stripe-elements';
import {
amountsConfig,
durationsConfig,
- defaultStateConfig
-} from '../../../../../config/donation-settings';
+ modalDefaultStateConfig
+} from '../../../../config/donation-settings';
+import { stripePublicKey } from '../../../../config/env.json';
+import { stripeScriptLoader } from '../../utils/scriptLoaders';
import DonateFormChildViewForHOC from './DonateFormChildViewForHOC';
-import { userSelector } from '../../../redux';
+import { userSelector } from '../../redux';
-import '../Donation.css';
-import DonateCompletion from './DonateCompletion.js';
-import { stripePublicKey } from '../../../../../config/env.json';
-import { stripeScriptLoader } from '../../../utils/scriptLoaders';
-
-const numToCommas = num =>
- num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
+import './Donation.css';
const propTypes = {
- showCloseBtn: PropTypes.func,
defaultTheme: PropTypes.string,
isDonating: PropTypes.bool,
+ showCloseBtn: PropTypes.func,
stripe: PropTypes.shape({
createToken: PropTypes.func.isRequired
})
@@ -39,7 +33,7 @@ const mapStateToProps = createSelector(
})
);
-class ModalDonateForm extends Component {
+class MinimalDonateForm extends Component {
constructor(...args) {
super(...args);
@@ -47,13 +41,11 @@ class ModalDonateForm extends Component {
this.amounts = amountsConfig;
this.state = {
- ...defaultStateConfig,
+ ...modalDefaultStateConfig,
isDonating: this.props.isDonating,
stripe: null
};
- this.handleSelectPaymentType = this.handleSelectPaymentType.bind(this);
this.handleStripeLoad = this.handleStripeLoad.bind(this);
- this.getDonationButtonLabel = this.getDonationButtonLabel.bind(this);
}
componentDidMount() {
@@ -85,91 +77,36 @@ class ModalDonateForm extends Component {
}
}
- handleSelectPaymentType(e) {
- this.setState({
- paymentType: e.currentTarget.value
- });
- }
-
- getFormatedAmountLabel(amount) {
- return `$${numToCommas(amount / 100)}`;
- }
-
- 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;
- }
-
- renderDonationOptions() {
- const {
- donationAmount,
- donationDuration,
- paymentType,
- stripe
- } = this.state;
-
- const { showCloseBtn, defaultTheme } = this.props;
- return (
-
- {paymentType === 'Card' ? (
-
-
-
-
-
- ) : (
-
- PayPal is currently unavailable. Please use a Credit/Debit card
- instead.
-
- {this.renderDonationOptions()}
+
+
+
+ `Confirm your donation of $5 per month`
+ }
+ showCloseBtn={showCloseBtn}
+ />
+
+
);
}
}
-ModalDonateForm.displayName = 'ModalDonateForm';
-ModalDonateForm.propTypes = propTypes;
+MinimalDonateForm.displayName = 'MinimalDonateForm';
+MinimalDonateForm.propTypes = propTypes;
export default connect(
mapStateToProps,
null
-)(ModalDonateForm);
+)(MinimalDonateForm);
diff --git a/client/src/components/Donation/components/StripeCardForm.js b/client/src/components/Donation/StripeCardForm.js
similarity index 100%
rename from client/src/components/Donation/components/StripeCardForm.js
rename to client/src/components/Donation/StripeCardForm.js
diff --git a/client/src/components/Donation/components/DonateText.js b/client/src/components/Donation/components/DonateText.js
deleted file mode 100644
index a42da163b6..0000000000
--- a/client/src/components/Donation/components/DonateText.js
+++ /dev/null
@@ -1,66 +0,0 @@
-import React from 'react';
-
-import { Spacer, Link } from '../../../components/helpers';
-
-const DonateText = () => {
- return (
-
-
-
How to donate to freeCodeCamp.org
-
-
freeCodeCamp is a tax-exempt 501(c)(3) public charity.
-
-
- We get almost all of our budget from our supporters, who donate $5 per
- month to our nonprofit.
-
-
-
- To become a supporter, just{' '}
- start going through the curriculum and you will
- see a prompt to donate.
-
-
-
- If you want to make a larger one-time donation, set up employer
- matching, or support us in other ways, email team@freecodecamp.org and
- we can help make that happen.
-
-
-
-
How does freeCodeCamp use these donations?
-
-
- 100% of donations go to pay for servers, and to pay teachers and
- developers who help build our learning resources.
-
-
-
- We earned the 2019 Platinum Seal of Transparency from Guidestar.org. You
- can view all our nonprofit's details and download our accounting
- documents{' '}
- there.
-
-
-
-
How do I stop my monthly recurring donation.
-
-
- Easy. Just forward a donation receipt to team@freecodecamp.org and we'll
- stop it.
-
-
-
-
How do I restart my monthly recurring donation?
-
-
- Email one of your old donation receipts to team@freecodecamp.org and
- we'll restart it for you.
-