Allow capture of name during adding of card (#1657)
* allow someone to save name during card signup * regexp to not allow numbers or special characters * add i8n string * various touchups
This commit is contained in:
parent
4ffec69f25
commit
e6a563443e
3 changed files with 95 additions and 8 deletions
|
@ -2015,8 +2015,10 @@
|
|||
"Getting your bank account connection status...": "Getting your bank account connection status...",
|
||||
"Connect your bank account to Odysee to receive donations directly from users": "Connect your bank account to Odysee to receive donations directly from users",
|
||||
"Connect your bank account": "Connect your bank account",
|
||||
"Please enter the name on the card": "Please enter the name on the card",
|
||||
"Name on card": "Name on card",
|
||||
"Manage Card": "Manage Card",
|
||||
"Card Details": "Card Details",
|
||||
"Card details": "Card details",
|
||||
"Remove Card": "Remove Card",
|
||||
"Currency To Use": "Currency To Use",
|
||||
"Sorry, there was an error in processing your payment!": "Sorry, there was an error in processing your payment!",
|
||||
|
|
|
@ -63,6 +63,10 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
componentDidMount() {
|
||||
let that = this;
|
||||
|
||||
that.setState({
|
||||
cardNameValue: '',
|
||||
});
|
||||
|
||||
const { preferredCurrency, locale } = this.props;
|
||||
|
||||
// use preferredCurrency if it's set on client, otherwise use USD, unless in Europe then use EUR
|
||||
|
@ -134,11 +138,14 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
bottomOfDisplay: bottomOfDisplay,
|
||||
};
|
||||
|
||||
const formattedEmailName = cardDetails.topOfDisplay + ' ' + cardDetails.bottomOfDisplay;
|
||||
|
||||
that.setState({
|
||||
currentFlowStage: 'cardConfirmed',
|
||||
pageTitle: 'Payment Methods',
|
||||
userCardDetails: cardDetails,
|
||||
paymentMethodId: customerStatusResponse.PaymentMethods[0].id,
|
||||
cardName: customerStatusResponse.PaymentMethods[0].billing_details.name || formattedEmailName,
|
||||
});
|
||||
|
||||
// otherwise, prompt them to save a card
|
||||
|
@ -250,7 +257,8 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
});
|
||||
|
||||
card.on('ready', function () {
|
||||
card.focus();
|
||||
// focus on the name input
|
||||
document.querySelector('#card-name').focus();
|
||||
});
|
||||
|
||||
var email = that.props.email;
|
||||
|
@ -258,6 +266,11 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
function submitForm(event) {
|
||||
event.preventDefault();
|
||||
|
||||
const cardUserName = document.querySelector('#card-name').value;
|
||||
if (!cardUserName) {
|
||||
return (document.querySelector('.sr-field-error').innerHTML = __('Please enter the name on the card'));
|
||||
}
|
||||
|
||||
// if client secret wasn't loaded properly
|
||||
if (!clientSecret) {
|
||||
var displayErrorText = 'There was an error in generating your payment method. Please contact a developer';
|
||||
|
@ -269,11 +282,16 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
|
||||
changeLoadingState(true);
|
||||
|
||||
const name = document.querySelector('#card-name').value;
|
||||
|
||||
stripe
|
||||
.confirmCardSetup(clientSecret, {
|
||||
payment_method: {
|
||||
card: card,
|
||||
billing_details: { email: email },
|
||||
billing_details: {
|
||||
email,
|
||||
name,
|
||||
},
|
||||
},
|
||||
})
|
||||
.then(function (result) {
|
||||
|
@ -353,11 +371,14 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
bottomOfDisplay,
|
||||
};
|
||||
|
||||
const formattedEmailName = cardDetails.topOfDisplay + ' ' + cardDetails.bottomOfDisplay;
|
||||
|
||||
that.setState({
|
||||
currentFlowStage: 'cardConfirmed',
|
||||
pageTitle: 'Payment Methods',
|
||||
userCardDetails: cardDetails,
|
||||
paymentMethodId: customerStatusResponse.PaymentMethods[0].id,
|
||||
cardName: customerStatusResponse.PaymentMethods[0].billing_details.name || formattedEmailName,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -382,6 +403,12 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
|
||||
const { setPreferredCurrency } = this.props;
|
||||
|
||||
function clearErrorMessage() {
|
||||
const errorElement = document.querySelector('.sr-field-error');
|
||||
|
||||
errorElement.innerHTML = '';
|
||||
}
|
||||
|
||||
// when user changes currency in selector
|
||||
function onCurrencyChange(event) {
|
||||
const { value } = event.target;
|
||||
|
@ -395,9 +422,37 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
setPreferredCurrency(value);
|
||||
}
|
||||
|
||||
function onChangeCardName(event) {
|
||||
const { value } = event.target;
|
||||
|
||||
const numberOrSpecialCharacter = /[0-9!@#$%^&*()_+=[\]{};:"\\|,<>?~]/;
|
||||
|
||||
const errorElement = document.querySelector('.sr-field-error');
|
||||
|
||||
if (numberOrSpecialCharacter.test(value)) {
|
||||
errorElement.innerHTML = __('Special characters and numbers are not allowed');
|
||||
} else if (value.length > 48) {
|
||||
errorElement.innerHTML = __('Name must be less than 48 characters long');
|
||||
} else {
|
||||
errorElement.innerHTML = '';
|
||||
|
||||
that.setState({
|
||||
cardNameValue: value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const { scriptFailedToLoad, openModal } = this.props;
|
||||
|
||||
const { currentFlowStage, pageTitle, userCardDetails, paymentMethodId, preferredCurrency } = this.state;
|
||||
const {
|
||||
currentFlowStage,
|
||||
pageTitle,
|
||||
userCardDetails,
|
||||
paymentMethodId,
|
||||
preferredCurrency,
|
||||
cardName,
|
||||
cardNameValue,
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<Page noFooter noSideNavigation className="card-stack" backout={{ title: __(pageTitle), backLabel: __('Back') }}>
|
||||
|
@ -410,7 +465,7 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
|
||||
{/* initial markup to show while getting information */}
|
||||
{currentFlowStage === 'loading' && (
|
||||
<div className="headerCard toConfirmCard">
|
||||
<div className="getting-card-status">
|
||||
<Card title={__('Connect your card with Odysee')} subtitle={__('Getting your card connection status...')} />
|
||||
</div>
|
||||
)}
|
||||
|
@ -419,9 +474,19 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
{currentFlowStage === 'confirmingCard' && (
|
||||
<div className="sr-root">
|
||||
<div className="sr-main">
|
||||
<div className="sr-payment-form card cardInput">
|
||||
<div className="">
|
||||
<div className="sr-form-row">
|
||||
<label className="payment-details">Card Details</label>
|
||||
<label className="payment-details">{__('Name on card')}</label>
|
||||
<input
|
||||
type="text"
|
||||
id="card-name"
|
||||
onChange={onChangeCardName}
|
||||
value={cardNameValue}
|
||||
onBlur={clearErrorMessage}
|
||||
/>
|
||||
</div>
|
||||
<div className="sr-form-row">
|
||||
<label className="payment-details">{__('Card details')}</label>
|
||||
<div className="sr-input sr-element sr-card-element" id="card-element" />
|
||||
</div>
|
||||
<div className="sr-field-error" id="card-errors" role="alert" />
|
||||
|
@ -454,7 +519,7 @@ class SettingsStripeCard extends React.Component<Props, State> {
|
|||
<>
|
||||
<Plastic
|
||||
type={userCardDetails.brand}
|
||||
name={userCardDetails.topOfDisplay + ' ' + userCardDetails.bottomOfDisplay}
|
||||
name={cardName}
|
||||
expiry={userCardDetails.expiryMonth + '/' + userCardDetails.expiryYear}
|
||||
number={'____________' + userCardDetails.lastFour}
|
||||
/>
|
||||
|
|
|
@ -423,3 +423,23 @@ pre {
|
|||
.currency-to-use-selector {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
// center loading div
|
||||
.getting-card-status .card__header--between {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#card-name {
|
||||
width: 284px;
|
||||
box-shadow: unset;
|
||||
color: #32325d;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.payment-details {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sr-field-error {
|
||||
color: var(--color-text-error);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue