From 1d855b75b4016ab64c249e91020c8032affd2d53 Mon Sep 17 00:00:00 2001 From: Ahmad Abdolsaheb Date: Mon, 30 Dec 2019 18:40:46 +0300 Subject: [PATCH] fix: add paypal image and donate form verification (#37978) Co-Authored-By: mrugesh <1884376+raisedadead@users.noreply.github.com> --- client/src/assets/icons/DonateWithPayPal.js | 58 ++++++++++++++ client/src/assets/icons/Payapl.js | 50 ------------ .../Donation/DonateFormChildViewForHOC.js | 76 ++++++++++++++++--- client/src/components/Donation/Donation.css | 28 ++++++- .../YearEndGift/YearEndDonationForm.js | 13 ++-- client/src/pages/certification.css | 8 +- 6 files changed, 160 insertions(+), 73 deletions(-) create mode 100644 client/src/assets/icons/DonateWithPayPal.js delete mode 100644 client/src/assets/icons/Payapl.js diff --git a/client/src/assets/icons/DonateWithPayPal.js b/client/src/assets/icons/DonateWithPayPal.js new file mode 100644 index 0000000000..657550c7ae --- /dev/null +++ b/client/src/assets/icons/DonateWithPayPal.js @@ -0,0 +1,58 @@ +/* eslint-disable max-len */ +import React, { Fragment } from 'react'; + +const propTypes = {}; + +function DonateWithPayPal(props) { + return ( + + Donate with PayPal + + + + + + + + + + + Donate with PayPal + + + + + + ); +} + +DonateWithPayPal.displayName = 'DonateWithPayPal'; +DonateWithPayPal.propTypes = propTypes; + +export default DonateWithPayPal; diff --git a/client/src/assets/icons/Payapl.js b/client/src/assets/icons/Payapl.js deleted file mode 100644 index be51879a70..0000000000 --- a/client/src/assets/icons/Payapl.js +++ /dev/null @@ -1,50 +0,0 @@ -/* eslint-disable max-len */ -import React, { Fragment } from 'react'; - -const propTypes = {}; - -function Paypal(props) { - return ( - - Paypal - - - - - - - - - - ); -} - -Paypal.displayName = 'Paypal'; -Paypal.propTypes = propTypes; - -export default Paypal; diff --git a/client/src/components/Donation/DonateFormChildViewForHOC.js b/client/src/components/Donation/DonateFormChildViewForHOC.js index 6a7545644a..54c2de93ea 100644 --- a/client/src/components/Donation/DonateFormChildViewForHOC.js +++ b/client/src/components/Donation/DonateFormChildViewForHOC.js @@ -1,4 +1,3 @@ -/* eslint-disable react/sort-prop-types */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; @@ -9,7 +8,8 @@ import { ControlLabel, Form, FormControl, - FormGroup + FormGroup, + Alert } from '@freecodecamp/react-bootstrap'; import { injectStripe } from 'react-stripe-elements'; @@ -19,13 +19,13 @@ import { postChargeStripe } from '../../utils/ajax'; import { userSelector } from '../../redux'; const propTypes = { - showCloseBtn: PropTypes.func, defaultTheme: PropTypes.string, donationAmount: PropTypes.number.isRequired, donationDuration: PropTypes.string.isRequired, email: PropTypes.string, getDonationButtonLabel: PropTypes.func.isRequired, isSignedIn: PropTypes.bool, + showCloseBtn: PropTypes.func, stripe: PropTypes.shape({ createToken: PropTypes.func.isRequired }), @@ -53,16 +53,18 @@ class DonateFormChildViewForHOC extends Component { ...initialState, donationAmount: this.props.donationAmount, donationDuration: this.props.donationDuration, + isSubmitionValid: null, email: null, + isEmailValid: true, isFormValid: false }; - this.getUserEmail = this.getUserEmail.bind(this); this.getValidationState = this.getValidationState.bind(this); this.handleEmailChange = this.handleEmailChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.postDonation = this.postDonation.bind(this); this.resetDonation = this.resetDonation.bind(this); + this.handleEmailBlur = this.handleEmailBlur.bind(this); } getUserEmail() { @@ -80,14 +82,28 @@ class DonateFormChildViewForHOC extends Component { handleEmailChange(e) { const newValue = e.target.value; - return this.setState(state => ({ - ...state, - email: newValue - })); + return this.setState({ + email: newValue, + // reset validation + isEmailValid: true + }); } handleSubmit(e) { e.preventDefault(); + + const { isEmailValid, isFormValid } = this.state; + + if ((!isEmailValid, !isFormValid)) { + return this.setState({ + isSubmitionValid: false + }); + } + + this.setState({ + isSubmitionValid: null + }); + const email = this.getUserEmail(); if (!email || !isEmail(email)) { return this.setState(state => ({ @@ -181,21 +197,54 @@ class DonateFormChildViewForHOC extends Component { return ; } + handleEmailBlur() { + const emailValue = this.state.email; + const newValidation = isEmail(emailValue); + return this.setState({ + isEmailValid: newValidation + }); + } + + renderErrorMessage() { + const { isEmailValid, isFormValid } = this.state; + let message = ''; + if (!isEmailValid && !isFormValid) + message = ( +

+ Please enter valid email address, credit card number, and expiration + date. +

+ ); + else if (!isEmailValid) + message =

Please enter a valid email address.

; + else + message = ( +

Please enter valid credit card number and expiration date.

+ ); + + return {message}; + } + renderDonateForm() { - const { isFormValid } = this.state; + const { isEmailValid, isSubmitionValid, email } = this.state; const { getDonationButtonLabel, theme, defaultTheme } = this.props; + return (
+
{isSubmitionValid !== null ? this.renderErrorMessage() : ''}
Email (we'll send you a tax-deductible donation receipt): @@ -215,8 +264,11 @@ class DonateFormChildViewForHOC extends Component { ); } - componentWillReceiveProps({ donationAmount, donationDuration }) { + componentWillReceiveProps({ donationAmount, donationDuration, email }) { this.setState({ donationAmount, donationDuration }); + if (this.state.email === null && email) { + this.setState({ email }); + } } render() { diff --git a/client/src/components/Donation/Donation.css b/client/src/components/Donation/Donation.css index 584a11b82d..356daca465 100644 --- a/client/src/components/Donation/Donation.css +++ b/client/src/components/Donation/Donation.css @@ -41,14 +41,22 @@ font-weight: normal; } -.donation-form .btn { +.donation-form .btn-cta, +.btn-cta.paypal-button { white-space: normal; + font-size: 1rem; + font-weight: 700; } .donate-input-element { padding-top: 8px; } +.donation-form .form-control::placeholder { + color: #707070; +} + +.donation-form .form-control:focus, .StripeElement--focus { border-color: #66afe9; outline: 0; @@ -56,6 +64,13 @@ 0 0 8px rgba(102, 175, 233, 0.6); } +.donation-form .email--invalid.form-control:focus, +.donation-form .email--invalid, +.donation-form .StripeElement--invalid { + border-color: #eb1c26; + color: #eb1c26; +} + .wallet { word-break: break-all; } @@ -236,6 +251,17 @@ li.disabled > a { width: 200px; } +.paypal-button { + display: flex; + align-items: center; + justify-content: center; +} + +.paypal-button svg { + margin-top: 5px; + height: 22px; +} + @media screen and (min-width: 355px) { .form-payment-methods { height: 30px; diff --git a/client/src/components/YearEndGift/YearEndDonationForm.js b/client/src/components/YearEndGift/YearEndDonationForm.js index d60f5ebf74..53fefdad19 100644 --- a/client/src/components/YearEndGift/YearEndDonationForm.js +++ b/client/src/components/YearEndGift/YearEndDonationForm.js @@ -20,6 +20,7 @@ import './YearEndGift.css'; import '../Donation/Donation.css'; import { stripePublicKey } from '../../../../config/env.json'; import { stripeScriptLoader } from '../../utils/scriptLoaders'; +import DonateWithPayPal from '../../assets/icons/DonateWithPayPal'; const numToCommas = num => num.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,'); @@ -187,14 +188,14 @@ class YearEndDonationForm extends Component { > - + className='btn btn-block btn-cta paypal-button' + alt='donate with paypal' + > + + ); } diff --git a/client/src/pages/certification.css b/client/src/pages/certification.css index 8515534f14..c175c4fdef 100644 --- a/client/src/pages/certification.css +++ b/client/src/pages/certification.css @@ -42,20 +42,20 @@ padding: 20px 0px; } -.certificate-outer-wrapper .btn { +.certificate-outer-wrapper .donation-completion .btn { background-color: var(--gray-15); border-color: var(--gray-85); color: var(--gray-85); } -.certificate-outer-wrapper .btn:hover { +.certificate-outer-wrapper .donation-completion .btn:hover { border-color: var(--gray-85); background-color: var(--gray-85); color: var(--gray-05); } -.certificate-outer-wrapper .btn[disabled], -.certificate-outer-wrapper .btn[disabled]:hover { +.certificate-outer-wrapper .donation-completion .btn[disabled], +.certificate-outer-wrapper .donation-completion .btn[disabled]:hover { background-color: var(--gray-15); border-color: var(--quaternary-color); color: var(--quaternary-color);