Skip to content

Commit

Permalink
Merge pull request #339 from Adyen/feature/mbway-remove-email-field
Browse files Browse the repository at this point in the history
Update MBWay component
  • Loading branch information
pabloai authored Sep 28, 2020
2 parents fd48d42 + 6830658 commit 390985e
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 128 deletions.
25 changes: 13 additions & 12 deletions packages/lib/src/components/MBWay/MBWay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,28 @@ export class MBWayElement extends UIElement {
private static type = 'mbway';

formatProps(props) {
if (props.data) {
props.data.email = props.data.shopperEmail || props.data.email;
props.data.phoneNumber = props.data.telephoneNumber || props.data.phoneNumber;
}
const { data = {}, placeholders = {} } = props;

return {
...props
...props,
data: {
telephoneNumber: data.telephoneNumber || data.phoneNumber || ''
},
placeholders: {
telephoneNumber: placeholders.telephoneNumber || placeholders.phoneNumber || '+351 932 123 456'
}
};
}

/**
* Formats the component data output
*/
formatData(): object {
const paymentMethod: object = {
type: MBWayElement.type,
shopperEmail: this.state.data ? this.state.data.email : '',
telephoneNumber: this.state.data ? this.state.data.phoneNumber : ''
};

return {
paymentMethod
paymentMethod: {
type: MBWayElement.type,
...(this.state.data?.telephoneNumber && { telephoneNumber: this.state.data.telephoneNumber })
}
};
}

Expand Down

This file was deleted.

124 changes: 26 additions & 98 deletions packages/lib/src/components/MBWay/components/MBWayInput/MBWayInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,22 @@ import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import classNames from 'classnames';
import useCoreContext from '../../../../core/Context/useCoreContext';
import styles from './MBWayInput.module.scss';
import './MBWayInput.scss';
import Field from '../../../internal/FormFields/Field';
import { renderFormField } from '../../../internal/FormFields';
import { mbwayValidationRules } from './validate';
import Validator from '../../../../utils/Validator';
import { UIElementProps } from '../../../UIElement';

type RtnTypeFnWithEvent = (e: Event) => void;

interface MBWayInputProps extends UIElementProps {
data?: any;
placeholders?: any;
onChange: (e, component) => void;
}

interface MBWayDataObject {
email: string;
phoneNumber: string;
}

interface MBWayErrorsObject {
email: boolean;
phoneNumber: boolean;
}

interface MBWayValidObject {
email: boolean;
phoneNumber: boolean;
}

interface ValidationObj {
value: string;
isValid: boolean;
}
import { MBWayDataState, MBWayErrorsState, MBWayInputProps, MBWayValidState, ValidationObj } from './types';
import './MBWayInput.scss';

function MBWayInput(props: MBWayInputProps) {
const { i18n } = useCoreContext();

const validator: Validator = new Validator(mbwayValidationRules);

const [errors, setErrors] = useState(({} as any) as MBWayErrorsObject);
const [valid, setValid] = useState(({} as any) as MBWayValidObject);
const [data, setData] = useState(({ ...props.data } as any) as MBWayDataObject);

const getIsValidEmail = (): boolean => validator.validate('email', 'blur')(data['email']).isValid;
const getIsValidPhoneNumber = (): boolean => validator.validate('phoneNumber', 'blur')(data['phoneNumber']).isValid;
const [data, setData] = useState<MBWayDataState>(props.data);
const [errors, setErrors] = useState<MBWayErrorsState>({});
const [valid, setValid] = useState<MBWayValidState>({
...(props.data.telephoneNumber && { telephoneNumber: validator.validate('telephoneNumber', 'input')(props.data.telephoneNumber).isValid })
});

const [status, setStatus] = useState('ready');

Expand All @@ -57,90 +26,49 @@ function MBWayInput(props: MBWayInputProps) {
};

this.showValidation = (): void => {
setErrors({ ...errors, email: !getIsValidEmail(), phoneNumber: !getIsValidPhoneNumber() });
const hasError = !validator.validate('telephoneNumber', 'input')(props.data.telephoneNumber).isValid;
setErrors({ ...errors, telephoneNumber: hasError });
};

const handleEventFor = (key, type): RtnTypeFnWithEvent => (e: Event): void => {
e.preventDefault();

const handleEventFor = (key: string, mode: string) => (e: Event): void => {
const val: string = (e.target as HTMLInputElement).value;
const { value, isValid }: ValidationObj = validator.validate('telephoneNumber', mode)(val);

const { value, isValid }: ValidationObj = validator.validate(key, type)(val);

if (type === 'input') {
setData({ ...data, [key]: value });
setErrors({ ...errors, [key]: false });
}

if (type === 'blur') {
// Length check, below, avoids bug where field, if in error state and then cleared, goes back to being in error state when it loses focus
// If field is empty it can never be in error - else take the opposite of the isValid value
const isInError: boolean = value.length === 0 ? false : !isValid;
setErrors({ ...errors, [key]: isInError });
}

setValid({ ...valid, [key]: isValid });
setData({ ...data, telephoneNumber: value });
setErrors({ ...errors, telephoneNumber: !isValid });
setValid({ ...valid, telephoneNumber: isValid });
};

useEffect(() => {
// If data has been passed - validate
if (data.email || data.phoneNumber) {
setValid({ ...valid, email: getIsValidEmail(), phoneNumber: getIsValidPhoneNumber() });
}
}, []);

// Run when state.data, -errors or -valid change
useEffect(() => {
props.onChange({ data, isValid: valid.email && valid.phoneNumber }, this);
}, [data, valid, errors]);
props.onChange({ data, isValid: valid.telephoneNumber });
}, [data, valid]);

return (
<div className="adyen-checkout__ach">
<div className="adyen-checkout__mb-way">
<Field
errorMessage={!!errors.email && i18n.get('shopperEmail.invalid')}
label={i18n.get('shopperEmail')}
classNameModifiers={['shopperEmail']}
isValid={valid.email}
>
{renderFormField('emailAddress', {
value: data.email,
name: 'shopperEmail',
classNameModifiers: ['large'],
placeholder: props.placeholders.shopperEmail,
spellcheck: false,
required: true,
autocorrect: 'off',
onInput: handleEventFor('email', 'input'),
onChange: handleEventFor('email', 'blur')
})}
</Field>
<Field
errorMessage={!!errors.phoneNumber && i18n.get('telephoneNumber.invalid')}
errorMessage={!!errors.telephoneNumber && i18n.get('telephoneNumber.invalid')}
label={i18n.get('telephoneNumber')}
className={classNames({
'adyen-checkout__input--phone-number': true
})}
isValid={valid.phoneNumber}
// Fixes bug where shopper enters invalid chars - because these get automatically removed, change event does NOT fire
onFieldBlur={handleEventFor('phoneNumber', 'blur')}
className={classNames('adyen-checkout__input--phone-number')}
isValid={valid.telephoneNumber}
>
{renderFormField('tel', {
value: data.phoneNumber,
className: `adyen-checkout__pm__phoneNumber__input ${styles['adyen-checkout__input']}`,
value: data.telephoneNumber,
className: 'adyen-checkout__pm__phoneNumber__input',
placeholder: props.placeholders.telephoneNumber,
required: true,
autoCorrect: 'off',
onInput: handleEventFor('phoneNumber', 'input')
// onChange: handleEventFor('phoneNumber', 'blur')
onChange: handleEventFor('telephoneNumber', 'blur'),
onInput: handleEventFor('telephoneNumber', 'input')
})}
</Field>

{props.showPayButton && props.payButton({ status, label: i18n.get('confirmPurchase') })}
</div>
);
}

MBWayInput.defaultProps = {
placeholders: { shopperEmail: '[email protected]', telephoneNumber: '+351 932 123 456' }
onChange: () => {}
};

export default MBWayInput;
28 changes: 28 additions & 0 deletions packages/lib/src/components/MBWay/components/MBWayInput/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { UIElementProps } from '../../../UIElement';

export interface MBWayInputData {
telephoneNumber?: string;
}

export interface MBWayInputProps extends UIElementProps {
data?: MBWayInputData;
placeholders?: MBWayInputData;
onChange: (state) => void;
}

export interface MBWayDataState {
telephoneNumber?: string;
}

export interface MBWayErrorsState {
telephoneNumber?: boolean;
}

export interface MBWayValidState {
telephoneNumber?: boolean;
}

export interface ValidationObj {
value: string;
isValid: boolean;
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
//const emailRegEx = /\S+@\S+\.\S+/;
/* eslint-disable max-len */
const emailRegEx = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
/* eslint-enable max-len */
const phoneNumberRegEx = /^[+]*[0-9]{1,4}[\s/0-9]*$/;

export const mbwayValidationRules: object = {
input: {
email: (email): object => {
return { isValid: emailRegEx.test(email), value: email };
},
phoneNumber: (num): object => {
telephoneNumber: (num): object => {
// Format
const regEx = /[^0-9+\s]/g;
const formattedVal: string = num.replace(regEx, '');
Expand All @@ -21,10 +14,7 @@ export const mbwayValidationRules: object = {
default: (value): boolean => value && value.length > 0
},
blur: {
email: (email): object => {
return { isValid: emailRegEx.test(email), value: email };
},
phoneNumber: (num): object => {
telephoneNumber: (num): object => {
// Just validate
return { isValid: phoneNumberRegEx.test(num) && num && num.length >= 7, value: num };
},
Expand Down

0 comments on commit 390985e

Please sign in to comment.