Skip to content

Commit

Permalink
fix(intl-phone-input): format input value (#703)
Browse files Browse the repository at this point in the history
Co-authored-by: Александр Серов <ARserov@alfabank.ru>
Co-authored-by: Alexander Yatsenko <reme3d2y@gmail.com>
  • Loading branch information
3 people committed Jun 22, 2021
1 parent f74cdc7 commit b5e91ed
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 31 deletions.
18 changes: 0 additions & 18 deletions packages/intl-phone-input/src/component.test.tsx
Expand Up @@ -57,24 +57,6 @@ describe('IntlPhoneInput', () => {
expect(onChange).toHaveBeenCalledWith('+74957888878');
});

it('should call `onChange` callback after input was changed with whole russian number', async () => {
const onChange = jest.fn();
render(
<IntlPhoneInput
value=''
onChange={onChange}
dataTestId={testId}
clearableCountryCode={false}
/>,
);

const input = await screen.getByDisplayValue('');
fireEvent.change(input, { target: { value: '84957888878' } });

expect(onChange).toHaveBeenCalled();
expect(onChange).toHaveBeenCalledWith('+74957888878');
});

it('should have default country flag icon', () => {
const { container } = render(<IntlPhoneInput value='' onChange={jest.fn()} />);

Expand Down
18 changes: 5 additions & 13 deletions packages/intl-phone-input/src/component.tsx
Expand Up @@ -11,6 +11,7 @@ import {
} from '@alfalab/core-components-input-autocomplete';
import { CountriesSelect } from './components';
import styles from './index.module.css';
import { formatPhoneWithUnclearableCountryCode } from './utils/format-phone-with-unclearable-country-code';

const countriesHash = getCountriesHash();

Expand Down Expand Up @@ -181,21 +182,12 @@ export const IntlPhoneInput = forwardRef<HTMLInputElement, IntlPhoneInputProps>(
}

if (!clearableCountryCode) {
let newValue;
const newValue = formatPhoneWithUnclearableCountryCode(targetValue, country);

if (targetValue[0] === '8') {
newValue = `+${country.dialCode}${targetValue.substr(1)}`;
setValue(newValue);
return;
}

if (targetValue.substr(1) < country.dialCode) {
newValue = `+${country.dialCode}`;
setValue(newValue);
return;
}
setValue(targetValue);
setValue(newValue);
return;
}
setValue(targetValue);
},
[clearableCountryCode, countryIso2, setCountryByDialCode, setValue, value.length],
);
Expand Down
@@ -0,0 +1,32 @@
import { Country } from '@alfalab/utils';
import { formatPhoneWithUnclearableCountryCode } from './format-phone-with-unclearable-country-code';

describe('formatPhoneWithUnclearableCountryCode', () => {
it('should work', () => {
const ru = {
dialCode: '7',
} as Country;

const az = {
dialCode: '994',
} as Country;
expect(formatPhoneWithUnclearableCountryCode('', ru)).toEqual('+7');
expect(formatPhoneWithUnclearableCountryCode('+', ru)).toEqual('+7');
expect(formatPhoneWithUnclearableCountryCode('7', ru)).toEqual('+7');
expect(formatPhoneWithUnclearableCountryCode('+7', ru)).toEqual('+7');
expect(formatPhoneWithUnclearableCountryCode('+17', ru)).toEqual('+71');
expect(formatPhoneWithUnclearableCountryCode('+71', ru)).toEqual('+71');
expect(formatPhoneWithUnclearableCountryCode('1+7', ru)).toEqual('+71');

expect(formatPhoneWithUnclearableCountryCode('', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('+', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('+9', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('+99', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('+994', az)).toEqual('+994');
expect(formatPhoneWithUnclearableCountryCode('1+994', az)).toEqual('+9941');
expect(formatPhoneWithUnclearableCountryCode('+1994', az)).toEqual('+9941');
expect(formatPhoneWithUnclearableCountryCode('+9194', az)).toEqual('+9941');
expect(formatPhoneWithUnclearableCountryCode('+9914', az)).toEqual('+9941');
expect(formatPhoneWithUnclearableCountryCode('+9941', az)).toEqual('+9941');
});
});
@@ -0,0 +1,32 @@
import { Country } from '@alfalab/utils';
import { getPhoneDiff } from './get-phone-diff';

/**
* Форматирует телефон с неудаляемым кодом страны
*/
export const formatPhoneWithUnclearableCountryCode = (phone: string, country: Country) => {
const defaultValue = `+${country.dialCode}`;
// При попытке стереть код страны возвращаем дефолтное значение
if (phone.length < defaultValue.length) {
return defaultValue;
}

// Если код страны совпадает, даем вводить значение
if (phone.substr(1, country.dialCode.length) === country.dialCode) {
return phone;
}

const lengthDiff = phone.substr(1).length - country.dialCode.length;
// Если разница длины нового значения и длины кода страны равна 1, то определяем отличающийся символ и ставим его после кода
if (lengthDiff === 1) {
const diff = getPhoneDiff(phone, country);
// Если не смогли вычислить отличающийся символ, то возвращаем дефолтное значение
if (!diff) {
return defaultValue;
}

return `+${country.dialCode}${diff}`;
}

return phone;
};
30 changes: 30 additions & 0 deletions packages/intl-phone-input/src/utils/get-phone-diff.test.ts
@@ -0,0 +1,30 @@
import { Country } from '@alfalab/utils';
import { getPhoneDiff } from './get-phone-diff';

describe('getPhoneDiff', () => {
it('should work', () => {
const ru = {
dialCode: '7',
} as Country;

const az = {
dialCode: '994',
} as Country;
expect(getPhoneDiff('', ru)).toEqual(null);
expect(getPhoneDiff('+', ru)).toEqual(null);
expect(getPhoneDiff('7', ru)).toEqual(null);
expect(getPhoneDiff('+7', ru)).toEqual(null);
expect(getPhoneDiff('+17', ru)).toEqual('1');
expect(getPhoneDiff('1+7', ru)).toEqual('1');

expect(getPhoneDiff('', az)).toEqual(null);
expect(getPhoneDiff('+', az)).toEqual(null);
expect(getPhoneDiff('+9', az)).toEqual(null);
expect(getPhoneDiff('+99', az)).toEqual(null);
expect(getPhoneDiff('+994', az)).toEqual(null);
expect(getPhoneDiff('1+994', az)).toEqual('1');
expect(getPhoneDiff('+1994', az)).toEqual('1');
expect(getPhoneDiff('+9194', az)).toEqual('1');
expect(getPhoneDiff('+9914', az)).toEqual('1');
});
});
23 changes: 23 additions & 0 deletions packages/intl-phone-input/src/utils/get-phone-diff.ts
@@ -0,0 +1,23 @@
import { Country } from '@alfalab/utils';

/**
* Возвращает разницу между значением и кодом страны
*/
export const getPhoneDiff = (value: string, country: Country) => {
if (!value || value === `+${country.dialCode}`) return null;

const dialRegex = country.dialCode.split('').reduce((acc, item, index) => {
return `${acc}(?<dial${index}>\\d+)*${item}`;
}, '');
const regex = new RegExp(`(?<beforePlusSign>\\d+)*\\+${dialRegex}`);

const result = value.match(regex);

if (!result) return null;
// eslint-disable-next-line no-prototype-builtins
if (!result.hasOwnProperty('groups')) return null;
const { groups } = result;
if (!groups) return null;

return Object.values(groups).join('');
};

0 comments on commit b5e91ed

Please sign in to comment.