Commit 45691907 authored by Stephanie Kirtiadi's avatar Stephanie Kirtiadi
Browse files

Make the credit card error not confusing.

Credit card errors now appear at the same time as
the other errors, which is during form submission.

Issue #47847
parent 1ee7488e
......@@ -27,6 +27,11 @@ export function _GivingForm(props) {
const [mailingListOptIn, setMailingListOptIn] = useState(false);
const [loading, setLoading] = useState(false);
const [errors, setErrors] = useState([]);
const [stripeErrors, setStripeErrors] = useState({
'cardNumber': new NamedError('cardNumber', "Your card number is incomplete."),
'cardExpiry': new NamedError('cardExpiry', "Your card's expiration date is incomplete."),
'cardCvc': new NamedError('cardCvc', "Your card's security code is incomplete."),
});
const [fitsAndSizes, setFitsAndSizes] = useState({
'shirt1Fit': null,
'shirt2Fit': null,
......@@ -227,6 +232,9 @@ export function _GivingForm(props) {
newErrors.push(new NamedError(fieldName, fieldName + ' must be filled out'));
}
}
for (const stripeField in stripeErrors) {
newErrors.push(stripeErrors[stripeField]);
}
return newErrors;
}
......@@ -380,9 +388,15 @@ export function _GivingForm(props) {
}
const onStripeFieldChange = (event) => {
const field = event.elementType;
const newState = {...stripeErrors};
if (event.error != undefined) {
const newError = new NamedError('stripeError', event.error.message);
setErrors([...errors, newError]);
const newError = new NamedError(field, event.error.message);
newState[field] = newError;
setStripeErrors(newState);
} else {
delete newState[field];
setStripeErrors(newState);
}
}
......
......@@ -55,7 +55,7 @@ export function GivingInfoForm(props) {
let creditCardFields = null;
if (paymentMethod == 'credit-card') {
creditCardFields = (
<StripeCreditCardForm onStripeFieldChange={onStripeFieldChange} />
<StripeCreditCardForm onStripeFieldChange={onStripeFieldChange} errors={errors} />
);
};
......@@ -81,7 +81,9 @@ export function GivingInfoForm(props) {
<RegionDropdown regions={regions}
selectedCountry={formData['country']}
onChange={regionChanged}
required={requiredFields.includes('region')}/>
required={requiredFields.includes('region')}
errors={errors}
/>
{getInputTextField('postalCode')}
</div>
<div className="field-row">
......
import React from 'react';
import {findErrorByName} from './named_error';
export function RegionDropdown(props) {
const {regions, selectedCountry, required, onChange} = props;
const {regions, selectedCountry, required, onChange, errors} = props;
let classes=['field'];
if (required) {
if (findErrorByName(errors, 'region') != undefined) {
classes.push('error');
} else {
classes.push('required');
}
......
import React, {useState} from 'react';
import {NamedError} from './named_error';
import {NamedError, findErrorByName} from './named_error';
import {CardNumberElement, CardExpiryElement, CardCVCElement} from 'react-stripe-elements';
const createOptions = (placeholder, fieldName) => {
const createOptions = (placeholder, fieldName, errors) => {
let classes = ['field', fieldName];
const fieldMapping = {
'card-number': 'cardNumber',
'exp-date': 'cardExpiry',
'cvc': 'cardCvc'
};
if (findErrorByName(errors, fieldMapping[fieldName]) != undefined) {
classes.push('error');
}
return {
placeholder: placeholder,
classes: {
base: `field ${fieldName}`,
invalid: 'field error',
base: classes.join(" "),
},
style: {
base: {
......@@ -20,32 +31,32 @@ const createOptions = (placeholder, fieldName) => {
fontFamily: '"Source Sans Pro", sans-serif'
},
invalid: {
color: 'red',
color: '#484848',
},
},
};
};
export function StripeCreditCardForm(props) {
const {onStripeFieldChange} = props;
const {onStripeFieldChange, errors} = props;
return (
<React.Fragment>
<div className="split-form stripe-elements">
<div className="field-row">
<CardNumberElement
{...createOptions('Card Number', 'card-number')}
{...createOptions('Card Number', 'card-number', errors)}
onChange={onStripeFieldChange}
/>
<img className='credit-cards' src='/static/images/donate/credit-cards.png'/>
</div>
<div className="field-row">
<CardExpiryElement
{...createOptions('MM/YY', 'exp-date')}
{...createOptions('MM/YY', 'exp-date', errors)}
onChange={onStripeFieldChange}
/>
<CardCVCElement
{...createOptions('CVC', 'cvc')}
{...createOptions('CVC', 'cvc', errors)}
onChange={onStripeFieldChange}
/>
</div>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment