[Refactoring] Payments: Use API country list (#1881)

This commit is contained in:
Alexander Zinchuk 2022-05-16 13:34:38 +02:00
parent 7e92a27a37
commit 348ecfdcac
5 changed files with 35 additions and 295 deletions

View File

@ -2,9 +2,10 @@ import React, {
FC, useCallback, memo, useRef, useEffect,
} from '../../lib/teact/teact';
import { ApiCountry } from '../../api/types';
import { FormState, FormEditDispatch } from '../../hooks/reducers/usePaymentReducer';
import useLang from '../../hooks/useLang';
import countryList from '../../util/countries';
import InputText from '../ui/InputText';
import Checkbox from '../ui/Checkbox';
@ -20,6 +21,7 @@ export type OwnProps = {
needCardholderName?: boolean;
needCountry?: boolean;
needZip?: boolean;
countryList: ApiCountry[];
dispatch: FormEditDispatch;
};
@ -29,6 +31,7 @@ const PaymentInfo: FC<OwnProps> = ({
needCardholderName,
needCountry,
needZip,
countryList,
dispatch,
}) => {
// eslint-disable-next-line no-null/no-null
@ -121,12 +124,12 @@ const PaymentInfo: FC<OwnProps> = ({
ref={selectCountryRef}
>
{
countryList.map(({ name }) => (
countryList.map(({ defaultName, name }) => (
<option
value={name}
value={defaultName}
className="county-item"
>
{name}
{defaultName || name}
</option>
))
}

View File

@ -4,6 +4,7 @@ import React, {
import { getActions, withGlobal } from '../../global';
import { GlobalState } from '../../global/types';
import { ApiCountry } from '../../api/types';
import { PaymentStep, ShippingOption, Price } from '../../types';
import { formatCurrency } from '../../util/formatCurrency';
@ -47,6 +48,7 @@ type StateProps = {
needCountry?: boolean;
needZip?: boolean;
confirmPaymentUrl?: string;
countryList: ApiCountry[];
};
type GlobalStateProps = Pick<GlobalState['payment'], (
@ -79,6 +81,7 @@ const Invoice: FC<OwnProps & StateProps & GlobalStateProps> = ({
needZip,
confirmPaymentUrl,
error,
countryList,
}) => {
const {
validateRequestedInfo,
@ -115,6 +118,10 @@ const Invoice: FC<OwnProps & StateProps & GlobalStateProps> = ({
const {
name: fullName, phone, email, shippingAddress,
} = savedInfo;
const {
countryIso2, ...shippingAddressRest
} = shippingAddress || {};
const shippingCountry = countryIso2 && countryList.find(({ iso2 }) => iso2 === countryIso2)!.defaultName;
paymentDispatch({
type: 'updateUserInfo',
payload: {
@ -123,11 +130,14 @@ const Invoice: FC<OwnProps & StateProps & GlobalStateProps> = ({
? `+${phone}`
: phone,
email,
...(shippingAddress || {}),
...(shippingCountry && {
country: shippingCountry,
...shippingAddressRest,
}),
},
});
}
}, [savedInfo, paymentDispatch]);
}, [savedInfo, paymentDispatch, countryList]);
const handleErrorModalClose = useCallback(() => {
clearPaymentError();
@ -181,6 +191,7 @@ const Invoice: FC<OwnProps & StateProps & GlobalStateProps> = ({
needEmail={Boolean(emailRequested || emailToProvider)}
needPhone={Boolean(phoneRequested || phoneToProvider)}
needName={Boolean(nameRequested)}
countryList={countryList}
/>
);
case PaymentStep.Shipping:
@ -201,6 +212,7 @@ const Invoice: FC<OwnProps & StateProps & GlobalStateProps> = ({
needCardholderName={needCardholderName}
needCountry={needCountry}
needZip={needZip}
countryList={countryList}
/>
);
case PaymentStep.Checkout:
@ -415,6 +427,7 @@ export default memo(withGlobal<OwnProps>(
needZip,
error,
confirmPaymentUrl,
countryList: global.countryList.general,
};
},
)(Invoice));

View File

@ -2,10 +2,11 @@ import React, {
FC, useRef, useCallback, useEffect, memo,
} from '../../lib/teact/teact';
import { ApiCountry } from '../../api/types';
import { FormState, FormEditDispatch } from '../../hooks/reducers/usePaymentReducer';
import useFocusAfterAnimation from '../../hooks/useFocusAfterAnimation';
import useLang from '../../hooks/useLang';
import countryList from '../../util/countries';
import InputText from '../ui/InputText';
import Select from '../ui/Select';
@ -19,6 +20,7 @@ export type OwnProps = {
needPhone: boolean;
needName: boolean;
needAddress: boolean;
countryList: ApiCountry[];
dispatch: FormEditDispatch;
};
@ -28,6 +30,7 @@ const ShippingInfo: FC<OwnProps> = ({
needPhone,
needName,
needAddress,
countryList,
dispatch,
}) => {
// eslint-disable-next-line no-null/no-null
@ -65,8 +68,8 @@ const ShippingInfo: FC<OwnProps> = ({
}, [dispatch]);
const handleCountryChange = useCallback((e) => {
dispatch({ type: 'changeCountry', payload: e.target.value });
}, [dispatch]);
dispatch({ type: 'changeCountry', payload: countryList.find((country) => country.iso2 === e.target.value) });
}, [countryList, dispatch]);
const handlePostCodeChange = useCallback((e) => {
dispatch({ type: 'changePostCode', payload: e.target.value });
@ -139,12 +142,12 @@ const ShippingInfo: FC<OwnProps> = ({
error={formErrors.countryIso2}
ref={selectCountryRef}
>
{countryList.map(({ name, id }) => (
{countryList.map(({ defaultName, name, iso2 }) => (
<option
value={id}
value={iso2}
className="county-item"
>
{name}
{defaultName || name}
</option>
))}
</Select>

View File

@ -1,5 +1,4 @@
import useReducer, { StateReducer, Dispatch } from '../useReducer';
import countryList from '../../util/countries';
export type FormState = {
streetLine1: string;
@ -94,8 +93,8 @@ const reducer: StateReducer<FormState, FormActions> = (state, action) => {
case 'changeCountry':
return {
...state,
countryIso2: action.payload,
billingCountry: getBillingCountry(action.payload),
countryIso2: action.payload.iso2,
billingCountry: action.payload.defaultName,
formErrors: {
...state.formErrors,
countryIso2: undefined,
@ -198,11 +197,11 @@ const reducer: StateReducer<FormState, FormActions> = (state, action) => {
case 'changeSaveCredentials':
return { ...state, saveCredentials: action.payload };
case 'updateUserInfo':
if (action.payload.countryIso2) {
if (action.payload.country) {
return {
...state,
...action.payload,
billingCountry: getBillingCountry(action.payload.countryIso2),
billingCountry: action.payload.country,
};
}
return { ...state, ...action.payload };
@ -219,11 +218,6 @@ const reducer: StateReducer<FormState, FormActions> = (state, action) => {
}
};
function getBillingCountry(countryCode: string) {
const country = countryList.find(({ id }) => id === countryCode);
return country ? country.name : '';
}
const usePaymentReducer = () => {
return useReducer(reducer, INITIAL_STATE);
};

View File

@ -1,273 +0,0 @@
// This data was received from Telegram Desktop (Telegram/Resources/numbers.txt)
const DATA = `AF🇦🇫93Afghanistan333
AO🇦🇴244Angola333
AL🇦🇱355Albania234
AD🇦🇩376Andorra222
AE🇦🇪971United Arab Emirates234
AI🇦🇮1264Anguilla34
AR🇦🇷54Argentina
AM🇦🇲374Armenia233
AG🇦🇬1268Antigua and Barbuda34
AU🇦🇺61Australia333
AS🇦🇸1684American Samoa34
AT🇦🇹43Austria
AW🇦🇼297Aruba34
AZ🇦🇿994Azerbaijan2322
BI🇧🇮257Burundi224
BE🇧🇪32Belgium3222
BJ🇧🇯229Benin233
BF🇧🇫226Burkina Faso2222
BD🇧🇩880Bangladesh
BG🇧🇬359Bulgaria
BH🇧🇭973Bahrain44
BS🇧🇸1242Bahamas34
BA🇧🇦387Bosnia and Herzegovina
BY🇧🇾375Belarus2322
BZ🇧🇿501Belize
BO🇧🇴591Bolivia134
BR🇧🇷55Brazil254
BB🇧🇧1246Barbados34
BM🇧🇲1441Bermuda34
BN🇧🇳673Brunei34
BQ🇧🇶599Bonaire, Sint Eustatius and Saba
BT🇧🇹975Bhutan
BW🇧🇼267Botswana233
CF🇨🇫236Central African Republic2222
CA🇨🇦1Canada334
CH🇨🇭41Switzerland234
CK🇨🇰682Cook Islands
CL🇨🇱56Chile144
CN🇨🇳86China344
CI🇨🇮225Côte d\`Ivoire233
CM🇨🇲237Cameroon44
CD🇨🇩243DR Congo234
CG🇨🇬242Republic of the Congo234
CO🇨🇴57Colombia334
KM🇰🇲269Comoros34
CV🇨🇻238Cape Verde34
CR🇨🇷506Costa Rica
CU🇨🇺53Cuba44
CY🇨🇾357Cyprus44
CW🇨🇼599Curaçao
CZ🇨🇿420Czech Republic
DE🇩🇪49Germany38
DJ🇩🇯253Djibouti2222
DM🇩🇲1767Dominica34
DK🇩🇰45Denmark44
DO🇩🇴1Dominican Republic334
DZ🇩🇿213Algeria3222
EC🇪🇨593Ecuador
EG🇪🇬20Egypt234
ER🇪🇷291Eritrea133
ES🇪🇸34Spain333
EE🇪🇪372Estonia
ET🇪🇹251Ethiopia234
FI🇫🇮358Finland
FJ🇫🇯679Fiji
FK🇫🇰500Falkland Islands
FM🇫🇲691Micronesia
FO🇫🇴298Faroe Islands33
FR🇫🇷33France12222
GA🇬🇦241Gabon1222
GB🇬🇧44United Kingdom46
GE🇬🇪995Georgia
GF🇬🇫594French Guiana
GH🇬🇭233Ghana
GI🇬🇮350Gibraltar44
GL🇬🇱299Greenland33
GN🇬🇳224Guinea333
GM🇬🇲220Gambia34
GP🇬🇵590Guadeloupe
GU🇬🇺1671Guam34
GW🇬🇼245Guinea-Bissau34
GQ🇬🇶240Equatorial Guinea333
GR🇬🇷30Greece244
GD🇬🇩1473Grenada34
GT🇬🇹502Guatemala134
GY🇬🇾592Guyana
HK🇭🇰852Hong Kong
HN🇭🇳504Honduras44
HR🇭🇷385Croatia
HT🇭🇹509Haiti
HU🇭🇺36Hungary234
ID🇮🇩62Indonesia
IN🇮🇳91India55
IO🇩🇬246Diego Garcia34
IE🇮🇪353Ireland234
IR🇮🇷98Iran334
IQ🇮🇶964Iraq334
IS🇮🇸354Iceland34
IL🇮🇱972Israel234
IT🇮🇹39Italy334
JM🇯🇲1876Jamaica34
JO🇯🇴962Jordan144
JP🇯🇵81Japan244
KZ🇰🇿7Kazakhstan3322
KE🇰🇪254Kenya333
KG🇰🇬996Kyrgyzstan
KH🇰🇭855Cambodia
KI🇰🇮686Kiribati
KN🇰🇳1869Saint Kitts and Nevis34
KR🇰🇷82South Korea
KW🇰🇼965Kuwait44
KY🇰🇾1345Cayman Islands34
LA🇱🇦856Laos
LB🇱🇧961Lebanon
LR🇱🇷231Liberia
LY🇱🇾218Libya234
LC🇱🇨1758Saint Lucia34
LI🇱🇮423Liechtenstein
LK🇱🇰94Sri Lanka234
LS🇱🇸266Lesotho233
LT🇱🇹370Lithuania35
LU🇱🇺352Luxembourg
LV🇱🇻371Latvia35
MA🇲🇦212Morocco234
MC🇲🇨377Monaco44
MD🇲🇩373Moldova233
MG🇲🇬261Madagascar2232
MP🇲🇵1670Northern Mariana Islands34
MO🇲🇴853Macau
MS🇲🇸1664Montserrat34
MV🇲🇻960Maldives
MX🇲🇽52Mexico
MH🇲🇭692Marshall Islands
MK🇲🇰389Macedonia
ML🇲🇱223Mali44
MT🇲🇹356Malta2222
MM🇲🇲95Myanmar
ME🇲🇪382Montenegro
MN🇲🇳976Mongolia
MZ🇲🇿258Mozambique234
MQ🇲🇶596Martinique
MR🇲🇷222Mauritania44
MU🇲🇺230Mauritius
MW🇲🇼265Malawi
MY🇲🇾60Malaysia
NA🇳🇦264Namibia234
NC🇳🇨687New Caledonia6
NE🇳🇪227Niger2222
NF🇳🇫672Norfolk Island
NG🇳🇬234Nigeria
NI🇳🇮505Nicaragua44
NL🇳🇱31Netherlands12222
NO🇳🇴47Norway44
NP🇳🇵977Nepal
NU🇳🇺683Niue
NR🇳🇷674Nauru
NZ🇳🇿64New Zealand
OM🇴🇲968Oman44
PK🇵🇰92Pakistan334
PA🇵🇦507Panama44
PE🇵🇪51Peru333
PF🇵🇫689French Polynesia
PH🇵🇭63Philippines334
PM🇵🇲508Saint Pierre and Miquelon
PR🇵🇷1Puerto Rico334
PS🇵🇸970Palestine324
PW🇵🇼680Palau
PG🇵🇬675Papua New Guinea
PL🇵🇱48Poland333
KP🇰🇵850North Korea
PT🇵🇹351Portugal144
PY🇵🇾595Paraguay333
QA🇶🇦974Qatar
RE🇷🇪262Réunion333
RO🇷🇴40Romania333
RU🇷🇺7Russia3322
RW🇷🇼250Rwanda333
SA🇸🇦966Saudi Arabia
SD🇸🇩249Sudan234
SN🇸🇳221Senegal234
SG🇸🇬65Singapore44
SH🇸🇭290Saint Helena23
SH🇸🇭247Saint Helena4
SB🇸🇧677Solomon Islands
SL🇸🇱232Sierra Leone233
SV🇸🇻503El Salvador44
SM🇸🇲378San Marino334
SO🇸🇴252Somalia233
RS🇷🇸381Serbia234
SS🇸🇸211South Sudan234
ST🇸🇹239São Tomé and Príncipe25
SR🇸🇷597Suriname34
SK🇸🇰421Slovakia
SI🇸🇮386Slovenia
SE🇸🇪46Sweden234
SZ🇸🇿268Swaziland44
SC🇸🇨248Seychelles1222
SX🇸🇽1721Sint Maarten34
SY🇸🇾963Syria
TC🇹🇨1649Turks and Caicos Islands34
TD🇹🇩235Chad2222
TG🇹🇬228Togo233
TH🇹🇭66Thailand144
TJ🇹🇯992Tajikistan
TK🇹🇰690Tokelau
TM🇹🇲993Turkmenistan26
TL🇹🇱670Timor-Leste
TO🇹🇴676Tonga
TT🇹🇹1868Trinidad and Tobago34
TN🇹🇳216Tunisia233
TR🇹🇷90Turkey334
TV🇹🇻688Tuvalu
TW🇹🇼886Taiwan
TZ🇹🇿255Tanzania234
UG🇺🇬256Uganda234
UA🇺🇦380Ukraine2322
UY🇺🇾598Uruguay44
US🇺🇸1United States334
UZ🇺🇿998Uzbekistan27
VA🇻🇦3Vatican City
VC🇻🇨1784Saint Vincent and the Grenadines34
VE🇻🇪58Venezuela334
VG🇻🇬1284British Virgin Islands34
VI🇻🇮1340US Virgin Islands34
VN🇻🇳84Vietnam
VU🇻🇺678Vanuatu
WF🇼🇫681Wallis and Futuna
WS🇼🇸685Samoa
XK🇽🇰383Kosovo44
YE🇾🇪967Yemen333
ZA🇿🇦27South Africa234
ZM🇿🇲260Zambia234
ZW🇿🇼263Zimbabwe234`;
const formatsCache: Record<string, RegExp> = {};
export const defaultPhoneNumberFormat = /(\d{1,3})(\d{1,3})?(\d{1,3})?(\d{1,3})?(\d{1,3})?/;
const parsed = DATA
.split('\n')
.map((str) => {
const id = str.substr(0, 2);
const flag = str.substr(2, 4);
const code = `+${str.match(/\d+/)![0]}`;
const name = str.split(/\d+/)[1];
const format = str.match(/\d+$/);
const phoneFormat = getPhoneNumberFormat(format);
return {
id, flag, code, name, phoneFormat,
};
});
function getPhoneNumberFormat(format: RegExpMatchArray | null) {
if (!format) {
return defaultPhoneNumberFormat;
}
const formatValue = format[0] as string;
let phoneNumberFormat;
if (!formatsCache[formatValue]) {
const phoneNumberGroups = formatValue.split('').map(Number);
phoneNumberFormat = phoneNumberGroups.reduce((result, count, i) => {
return `${result}(\\d{1,${count}})${i > 0 ? '?' : ''}`;
}, '');
formatsCache[formatValue] = new RegExp(`${phoneNumberFormat}${'()?'.repeat(5 - phoneNumberGroups.length)}`);
}
return formatsCache[formatValue];
}
export default parsed;