Skip to content

Instantly share code, notes, and snippets.

@ldco2016
Created September 12, 2018 23:35
Show Gist options
  • Save ldco2016/f37c81ab15d6ec3bbe4cfeaf6d697057 to your computer and use it in GitHub Desktop.
Save ldco2016/f37c81ab15d6ec3bbe4cfeaf6d697057 to your computer and use it in GitHub Desktop.
conflict puke
import React from 'react';
import Tooltip from "../Widgets/Tooltip";
import BackupPaymentBlurb from "./BackupPaymentBlurb";
import CardPayment from "./CardPayment";
import {normalizeCreditCard} from '../../lib/Format';
import errorStrings from '../../assets/strings/errors.json';
import store from '../../store';
import PaymentMethodsFromWallet from './PaymentMethodsFromWallet';
import config from '../../config';
import Actions from '../../actions';
import TextFloatInput from '../SinglePageCheckout/AddressForm/TextFloatInput';
import ctoHandler from '../../lib/Cto';
class GiftCard extends React.Component{
constructor(props){
super(props);
this.wasUpdated = false;
this.handleInputChange = this.handleInputChange.bind(this);
this.handleInputBlur = this.handleInputBlur.bind(this);
this.handleCardNumberChanged = this.handleCardNumberChanged.bind(this);
this.handleRequiredInputBlur = this.handleRequiredInputBlur.bind(this);
this.handleBackupUpdated = this.handleBackupUpdated.bind(this);
this.hasExternalErrors = this.hasExternalErrors.bind(this);
this.hasRequired = this.hasRequired.bind(this);
this.hasErrors = this.hasErrors.bind(this);
this.errorMessage = this.errorMessage.bind(this);
this.errorCssClass = this.errorCssClass.bind(this);
this.errorExists = this.errorExists.bind(this);
this.setErrors = this.setErrors.bind(this);
this.validateField_giftCardNumber = this.validateField_giftCardNumber.bind(this);
this.validateAll = this.validateAll.bind(this);
this.renderFormContent = this.renderFormContent.bind(this);
this.renderGC = this.renderGC.bind(this);
this.renderSinglePageCheckoutGC = this.renderSinglePageCheckoutGC.bind(this);
let lastState = store.getState();
lastState = lastState.form || {};
lastState = lastState.paymentType || {};
this.state = {
giftCardNumber: lastState.giftCardNumber || '',
formattedGiftCardNumber: lastState.formattedGiftCardNumber || '',
giftCardBrand: lastState.giftCardBrand || '',
backupInfo : lastState.backupInfo || '',
errors: {}
};
}
errorMessage(fieldName) {
if (!! this.state.errors[fieldName] && 'string' === typeof this.state.errors[fieldName]) {
return this.state.errors[fieldName];
}
let errKey = 'MHPFD.paymentType.' + fieldName;
return errorStrings[errKey] || errorStrings["MHPFD.GENERAL_MISSING"];
}
errorCssClass(fieldName, baseStyle = '') {
if (!! this.state.errors[fieldName]) {
return 'validation-error ' + baseStyle;
}
return baseStyle;
}
errorExists(fieldName) {
return !! this.state.errors[fieldName];
}
renderFormContent() {
// Conditionally display a user's saved cards or an empty form to enter card details
let {displayStoredCards} = this.props;
return displayStoredCards
? (
<PaymentMethodsFromWallet
paymentCardTypes={this.props.paymentCardTypes}
onFormCompleted={this.handleBackupUpdated}
revalidate={this.props.revalidate}
onFormInvalid={this.handleBackupUpdated}
onRevalidateComplete={()=>{}}
/>
)
: <CardPayment
paymentCardTypes={this.props.paymentCardTypes}
includeSaveForLater={this.props.includeSaveForLater}
checkAndDisableSaveForLater={this.props.checkAndDisableSaveForLater}
existingPayment={this.state.backupInfo}
onFormCompleted={this.handleBackupUpdated}
onFormInvalid={this.handleBackupUpdated}
revalidate={this.props.revalidate}
onRevalidateComplete={()=>{}}
externalErrors={this.errors}/>
}
// Renders the Accordion Single Page Checkout epic version of the GC Number input.
renderSinglePageCheckoutGC() {
return (
<div className="col-1 cc-wrapper">
<TextFloatInput
labelText="Gift Card Number"
name="giftCardNumber"
id="giftCardNumber"
errorMessage={() => this.errorExists('giftCardNumber')
? this.errorMessage('accordion.giftCardNumber')
: null}
value={this.state.formattedGiftCardNumber || ''}
onBlur={this.handleRequiredInputBlur}
onChange={this.handleCardNumberChanged}
data-cc-type={this.state.giftCardBrand}
required
/>
<a className="gc-card-balance"
href={config.checkGiftCardBalance}
target="_blank">Check Card Balance</a>
</div>
);
}
// Renders the legacy version of the GC Number input.
renderGC() {
return (
<div className="col-1 cc-wrapper">
<label htmlFor="giftCardNumber">
<span className="font-bold">Gift Card Number</span>
<Tooltip error={true}
hasError={this.errorExists('giftCardNumber')}
message={this.errorMessage('giftCardNumber')}
/>
</label>
<div className="cc-input-wrapper">
<span className="cc-input-bg" data-cc-type={this.state.giftCardBrand}/>
<input type="text"
name="giftCardNumber"
id="giftCardNumber"
value={this.state.formattedGiftCardNumber}
onChange={this.handleCardNumberChanged}
onBlur={this.handleRequiredInputBlur}
className={this.errorCssClass('giftCardNumber')}
data-cc-type={this.state.giftCardBrand}
/>
</div>
<a className="gc-card-balance"
href={config.checkGiftCardBalance}
target="_blank">Check Card Balance</a>
</div>
);
}
render() {
// Conditionally display the Accordion SinglePageCheckout version of the GC
// number input field or the legacy version.
const { isSinglePageCheckout } = this.props;
const giftCardNumber = isSinglePageCheckout
? this.renderSinglePageCheckoutGC()
: this.renderGC();
return (
<div className="card-payment col-container">
{giftCardNumber}
<div className="col-1">
<div className="col-1 cc-wrapper">
<label htmlFor="giftCardNumber">
<span className="font-bold">Gift Card Number</span>
<Tooltip error={true}
hasError={this.errorExists('giftCardNumber')}
message={this.errorMessage('giftCardNumber')}
/>
</label>
<div className="cc-input-wrapper">
<span className="cc-input-bg" data-cc-type={this.state.giftCardBrand}/>
<input type="text"
name="giftCardNumber"
id="giftCardNumber"
value={this.state.formattedGiftCardNumber}
onChange={this.handleCardNumberChanged}
onBlur={this.handleRequiredInputBlur}
className={this.errorCssClass('giftCardNumber')}
data-cc-type={this.state.giftCardBrand}
/>
</div>
<a className="gc-card-balance"
href={config.checkGiftCardBalance}
target="_blank">Check Card Balance</a>
</div>
<div className="col-1" ref={(giftCard) => {
this.giftCard = giftCard;
}} tabIndex="-1">
<BackupPaymentBlurb cardType="Disney Gift Card"/>
{this.renderFormContent()}
</div>
</div>
);
}
handleBackupUpdated(backupInfo){
this.wasUpdated = true;
this.setState({
backupInfo: backupInfo
});
}
hasErrors(errObj) {
let checkErrors = errObj || this.state.errors;
if (! checkErrors) {
return false;
}
for (let curr in checkErrors) {
// if has any error return true immediately
if (!! checkErrors[curr]) {
return true;
}
}
return false;
}
hasRequired() {
if (! this.state.giftCardNumber
|| ! this.state.backupInfo) {
return false
}
return true;
}
setErrors(errFields = [], errVal) {
this.wasUpdated = true;
let nextErrors = {};
let resolvedErrors = {};
Object.assign(nextErrors, this.state.errors);
for (let i = 0; i < errFields.length; i++) {
if (!! errVal) {
nextErrors[ errFields[i] ] = errVal;
}
else {
delete nextErrors[ errFields[i] ];
resolvedErrors[ errFields[i] ] = true;
}
}
let nextState = {
errors: nextErrors
};
this.setState(nextState);
if (this.props.onFormInvalid && this.hasErrors(nextErrors)) {
let formValues = {};
Object.assign(formValues, this.state, nextState, {
canProceed: false
});
this.props.onFormInvalid(formValues);
}
if (this.props.onExternalErrorsResolved && this.hasErrors(resolvedErrors)) {
this.props.onExternalErrorsResolved(resolvedErrors);
}
}
validateField_giftCardNumber(fieldName) {
let val = this.state.giftCardNumber.trim();
if (val.length !== 16){
return [fieldName];
}
return [];
}
validateAll(){
let fieldAry = this.props.fieldsToValidate ? Object.keys(this.props.fieldsToValidate) : ['giftCardNumber'];
let problemFields = new Set();
const self = this;
fieldAry.forEach(curr => {
const validateFn = self['validateField_' + curr] || self.validateField;
if (validateFn) {
validateFn(curr).forEach(curr => problemFields.add(curr));
}
});
if (problemFields.size > 0) {
this.setErrors(Array.from(problemFields), true);
let errorField = ctoHandler.generateErrorEvents(problemFields);
ctoHandler.eventTrackForCTO(null, errorField, true);
store.dispatch(Actions.uiError(errorStrings.formError.key, errorStrings.formError.message));
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.revalidate && this.props.onRevalidateComplete && this.validateAll) {
this.validateAll();
this.props.onRevalidateComplete();
}
}
hasExternalErrors() {
let lastState = store.getState();
lastState = lastState.form || {};
lastState = lastState.paymentType || {};
return (lastState.errors
&& Object.keys(lastState.errors).length > 0
&& !!lastState.errors.giftCardNumber);
}
componentDidUpdate(prevProps, prevState) {
let formValues = {
canProceed: true
};
if (! this.hasErrors() && this.hasRequired() && !this.hasExternalErrors()) {
Object.assign(formValues, this.state);
if (this.props.onFormCompleted && this.wasUpdated) {
this.props.onFormCompleted(formValues);
this.wasUpdated = false;
}
}
}
handleCardNumberChanged(event) {
this.wasUpdated = true;
const target = event.target;
const value = target.value;
const ccNum = normalizeCreditCard(value);
this.setState({
giftCardNumber: ccNum.cardNumber,
formattedGiftCardNumber: ccNum.formattedCardNumber,
giftCardBrand: ccNum.formattedCardNumber.length > 0 ? "GC" : ""
});
}
handleInputChange(event) {
this.wasUpdated = true;
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleInputBlur(event) {
this.wasUpdated = true;
}
handleRequiredInputBlur(event) {
this.wasUpdated = true;
const target = event.target;
const name = target.name;
let val = this.state[name].trim();
if (val === '') {
this.setErrors([name], true);
}
else {
this.setErrors([name], false);
}
}
}
GiftCard.defaultProps = {
displayStoredCards: false
};
export default GiftCard;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment