Skip to content

Commit

Permalink
Feature/mb way international phone number (#1601)
Browse files Browse the repository at this point in the history
* First draft of new PhoneInput

* Starting to sort out styling

* Mapping country flags, handling onChange & showValidation

* Correctly adding placeholders and labels to PhoneInput comp. Removed spritesheet mapping

* MBWayInput - removing unnecessary useForm fny. MBWay - expect data props to be 'phoneNumber' & 'phonePrefix'

* Allow parent comp to pass in keys for error messages

* Set styling related heights to 35px

* Moved isEmpty util to validator-utils.ts and added some other util fns

* Don't show validation error on an empty phone input

* Styling: better selector names. (Added comments)

* Changed some class names. Show valid and error icons

* Removed duplicated class fro FormFields.scss

* Adjusted width of dropdown and removed inappropriate 'field' string from some selectors

* Adding more new look BEM class names

* Concatenate pref and number into one value for paymentMethod data

* Fully validate a portuguese mobile number

* Remove console.log

* Fixing types

* Increased sf version to 3.10.2

* Show spinner whilst phonenumbers dataset loads

* Turned mechanism for fetching phonePrefixes into a custom hook

* handling error differently
  • Loading branch information
sponglord authored May 23, 2022
1 parent 9310e9b commit f3f9c1d
Show file tree
Hide file tree
Showing 17 changed files with 430 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ValidatorRules } from '../../../../utils/Validator/types';
import { formatCPFCNPJ } from '../../../internal/SocialSecurityNumberBrazil/utils';
import validateSSN from '../../../internal/SocialSecurityNumberBrazil/validate';
import { isEmpty } from '../../../internal/SecuredFields/lib/utilities/commonUtils';
import { isEmpty } from '../../../../utils/validator-utils';

export const cardInputFormatters = {
socialSecurityNumber: formatCPFCNPJ
Expand Down
7 changes: 4 additions & 3 deletions packages/lib/src/components/MBWay/MBWay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ export class MBWayElement extends UIElement {
return {
...props,
data: {
telephoneNumber: data.telephoneNumber || data.phoneNumber
phoneNumber: data.telephoneNumber || data.phoneNumber,
phonePrefix: data.phonePrefix || '+351' // if not specified default to Portuguese country code
},
placeholders: {
telephoneNumber: placeholders.telephoneNumber || placeholders.phoneNumber || '+351 932 123 456'
phoneNumber: placeholders.telephoneNumber || placeholders.phoneNumber || '932123456'
}
};
}
Expand All @@ -29,7 +30,7 @@ export class MBWayElement extends UIElement {
return {
paymentMethod: {
type: MBWayElement.type,
...(this.state.data?.telephoneNumber && { telephoneNumber: this.state.data.telephoneNumber })
...(this.state.data?.phoneNumber && { telephoneNumber: this.state.data.phonePrefix + this.state.data.phoneNumber })
}
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,69 +1,45 @@
import { h } from 'preact';
import { useState, useEffect } from 'preact/hooks';
import classNames from 'classnames';
import { useState, useRef } from 'preact/hooks';
import useCoreContext from '../../../../core/Context/useCoreContext';
import Field from '../../../internal/FormFields/Field';
import { renderFormField } from '../../../internal/FormFields';
import { MBWayDataState, MBWayInputProps } from './types';
import { MBWayInputProps } from './types';
import './MBWayInput.scss';
import useForm from '../../../../utils/useForm';
const phoneNumberRegEx = /^[+]*[0-9]{1,4}[\s/0-9]*$/;
import PhoneInput from '../../../internal/PhoneInputNew';
import LoadingWrapper from '../../../internal/LoadingWrapper';
import usePhonePrefixes from '../../../internal/PhoneInputNew/usePhonePrefixes';

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

const { handleChangeFor, triggerValidation, data, valid, errors, isValid } = useForm<MBWayDataState>({
schema: ['telephoneNumber'],
defaultData: props.data,
rules: {
telephoneNumber: {
validate: num => phoneNumberRegEx.test(num) && num.length >= 7,
errorMessage: 'mobileNumber.invalid',
modes: ['blur']
}
},
formatters: {
telephoneNumber: num => num.replace(/[^0-9+\s]/g, '')
}
});
const phoneInputRef = useRef(null);

const [status, setStatus] = useState('ready');
const { allowedCountries = [] } = props;

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

this.setStatus = setStatus;
this.showValidation = triggerValidation;
this.showValidation = phoneInputRef?.current?.triggerValidation;

const { loadingStatus: prefixLoadingStatus, phonePrefixes } = usePhonePrefixes({ allowedCountries, loadingContext, handleError: props.onError });

useEffect(() => {
const onChange = ({ data, valid, errors, isValid }) => {
props.onChange({ data, valid, errors, isValid });
}, [data, valid, errors, isValid]);
};

return (
<div className="adyen-checkout__mb-way">
<Field
errorMessage={!!errors.telephoneNumber && i18n.get('mobileNumber.invalid')}
label={i18n.get('mobileNumber')}
className={classNames('adyen-checkout__input--phone-number')}
isValid={valid.telephoneNumber}
dir={'ltr'}
name={'telephoneNumber'}
>
{renderFormField('tel', {
value: data.telephoneNumber,
className: 'adyen-checkout__pm__phoneNumber__input',
placeholder: props.placeholders.telephoneNumber,
required: true,
autoCorrect: 'off',
onBlur: handleChangeFor('telephoneNumber', 'blur'),
onInput: handleChangeFor('telephoneNumber', 'input')
})}
</Field>
<LoadingWrapper status={prefixLoadingStatus}>
<div className="adyen-checkout__mb-way">
<PhoneInput {...props} items={phonePrefixes} ref={phoneInputRef} onChange={onChange} data={props.data} />

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

MBWayInput.defaultProps = {
onChange: () => {}
onChange: () => {},
phoneNumberKey: 'mobileNumber',
phoneNumberErrorKey: 'mobileNumber.invalid'
};

export default MBWayInput;
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import { UIElementProps } from '../../../types';

export interface MBWayInputData {
telephoneNumber?: string;
phoneNumber?: string;
phonePrefix?: string;
}

export interface MBWayInputProps extends UIElementProps {
data?: MBWayInputData;
placeholders?: MBWayInputData;
onChange: (state) => void;
allowedCountries?: string[];
requiredFields?: string[];
phoneNumberKey?: string;
}

export interface MBWayDataState {
Expand Down
2 changes: 1 addition & 1 deletion packages/lib/src/components/internal/Address/validate.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ValidatorRules, ValidatorRule } from '../../../utils/Validator/types';
import { countrySpecificFormatters } from './validate.formats';
import { ERROR_CODES, ERROR_MSG_INCOMPLETE_FIELD } from '../../../core/Errors/constants';
import { isEmpty } from '../SecuredFields/lib/utilities/commonUtils';
import { isEmpty } from '../../../utils/validator-utils';

const createPatternByDigits = (digits: number) => {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,6 @@
color: $color-alert;
}

.adyen-checkout__input--invalid {
border-color: $color-alert;
}

.adyen-checkout__input--valid {
border-bottom-color: $color-success;
}
Expand Down
82 changes: 82 additions & 0 deletions packages/lib/src/components/internal/PhoneInputNew/PhoneInput.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
.adyen-checkout-phone-input--new {
direction: ltr;

// inherited style (FormFields.scss)
.adyen-checkout__input-wrapper {
width: 100%;

// inherited style (FormFields.scss)
.adyen-checkout__input {
padding: 0;
height: auto;

&:focus-within {
border: 1px solid #06f;

.adyen-checkout-dropdown--countrycode-selector {
border-right: 1px solid #06f;
}
}
}

// inherited style (Select.scss)
.adyen-checkout__dropdown__button {
width: auto;
border: 0;
height: 35px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;

&:after {
box-sizing: revert;
height: 10px;
}
}

// inherited style (Select.scss)
.adyen-checkout__dropdown__button--active {
box-shadow: none;

&:hover {
box-shadow: none;
}
}

// Example of better BEM naming i.e. 'adyen-checkout-input' as the Base
.adyen-checkout-input--phone-number {
height: 35px;
line-height: 35px;
min-height: 35px;
padding-bottom: 0;
padding-top: 0;
border: 1px solid transparent;
padding-left: 15px;

&:focus-within {
border: 1px solid #06f;
box-shadow: 0 0 0 2px #99c2ff;
}
}

.adyen-checkout-dropdown--countrycode-selector {
border-right: 1px solid #dce0e5;
min-width: 134px;
width: 134px;
}

.adyen-checkout-input-holder--phone-input {
align-items: center;
display: flex;
}

.adyen-checkout-phone-number {
align-items: center;
display: flex;
flex: 3;
}
}

.adyen-checkout-phone-input__error-holder {
margin-top: -10px;
}
}
Loading

0 comments on commit f3f9c1d

Please sign in to comment.