|
|
|
/*
|
|
|
|
* https://github.com/morethanwords/tweb
|
|
|
|
* Copyright (C) 2019-2021 Eduard Kuzmenko
|
|
|
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
|
|
|
*/
|
|
|
|
|
|
|
|
import PopupElement from ".";
|
|
|
|
import { attachClickEvent } from "../../helpers/dom/clickEvent";
|
|
|
|
import placeCaretAtEnd from "../../helpers/dom/placeCaretAtEnd";
|
|
|
|
import toggleDisability from "../../helpers/dom/toggleDisability";
|
|
|
|
import { InputInvoice, Message, PaymentRequestedInfo, PaymentsPaymentForm, PaymentsValidatedRequestedInfo } from "../../layer";
|
|
|
|
import getServerMessageId from "../../lib/appManagers/utils/messageId/getServerMessageId";
|
|
|
|
import { ApiError } from "../../lib/mtproto/apiManager";
|
|
|
|
import matchEmail from "../../lib/richTextProcessor/matchEmail";
|
|
|
|
import Button from "../button";
|
|
|
|
import CheckboxField from "../checkboxField";
|
|
|
|
import CountryInputField from "../countryInputField";
|
|
|
|
import InputField from "../inputField";
|
|
|
|
import Row from "../row";
|
|
|
|
import { SettingSection } from "../sidebarLeft";
|
|
|
|
import TelInputField from "../telInputField";
|
|
|
|
import { PaymentButton } from "./payment";
|
|
|
|
import { createCountryZipFields, handleInputFieldsOnChange, InputFieldCorrected } from "./paymentCard";
|
|
|
|
|
|
|
|
export type PaymentShippingAddress = PaymentRequestedInfo;
|
|
|
|
|
|
|
|
type ShippingFocusField = 'name' | 'email' | 'phone';
|
|
|
|
|
|
|
|
export default class PopupPaymentShipping extends PopupElement<{
|
|
|
|
finish: (o: {shippingAddress: PaymentShippingAddress, requestedInfo: PaymentsValidatedRequestedInfo}) => void
|
|
|
|
}> {
|
|
|
|
constructor(
|
|
|
|
private paymentForm: PaymentsPaymentForm,
|
|
|
|
private inputInvoice: InputInvoice,
|
|
|
|
private focus?: ShippingFocusField
|
|
|
|
) {
|
|
|
|
super('popup-payment popup-payment-shipping', {
|
|
|
|
closable: true,
|
|
|
|
overlayClosable: true,
|
|
|
|
body: true,
|
|
|
|
scrollable: true,
|
|
|
|
title: 'PaymentShippingInfo'
|
|
|
|
});
|
|
|
|
|
|
|
|
this.d();
|
|
|
|
}
|
|
|
|
|
|
|
|
private d() {
|
|
|
|
const paymentForm = this.paymentForm;
|
|
|
|
const invoice = paymentForm.invoice;
|
|
|
|
const savedInfo = this.paymentForm.saved_info;
|
|
|
|
|
|
|
|
let addressSection: SettingSection,
|
|
|
|
address1InputField: InputField,
|
|
|
|
address2InputField: InputField,
|
|
|
|
cityInputField: InputField,
|
|
|
|
stateInputField: InputField,
|
|
|
|
countryInputField: CountryInputField,
|
|
|
|
postcodeInputField: InputFieldCorrected;
|
|
|
|
if(invoice.pFlags.shipping_address_requested) {
|
|
|
|
addressSection = new SettingSection({name: 'PaymentShippingAddress', noDelimiter: true, noShadow: true});
|
|
|
|
address1InputField = new InputField({label: 'PaymentShippingAddress1Placeholder', maxLength: 64, required: true});
|
|
|
|
address2InputField = new InputField({label: 'PaymentShippingAddress2Placeholder', maxLength: 64});
|
|
|
|
cityInputField = new InputField({label: 'PaymentShippingCityPlaceholder', maxLength: 64, required: true});
|
|
|
|
stateInputField = new InputField({label: 'PaymentShippingStatePlaceholder', maxLength: 64});
|
|
|
|
const res = createCountryZipFields(true, true);
|
|
|
|
countryInputField = res.countryInputField;
|
|
|
|
postcodeInputField = res.postcodeInputField;
|
|
|
|
|
|
|
|
addressSection.content.append(...[
|
|
|
|
address1InputField,
|
|
|
|
address2InputField,
|
|
|
|
cityInputField,
|
|
|
|
stateInputField,
|
|
|
|
countryInputField,
|
|
|
|
postcodeInputField
|
|
|
|
].filter(Boolean).map((inputField) => inputField.container));
|
|
|
|
}
|
|
|
|
|
|
|
|
let receiverSection: SettingSection;
|
|
|
|
let nameInputField: InputField, emailInputField: InputField, telInputField: TelInputField;
|
|
|
|
if([invoice.pFlags.name_requested, invoice.pFlags.email_requested, invoice.pFlags.phone_requested].includes(true)) {
|
|
|
|
receiverSection = new SettingSection({name: 'PaymentShippingReceiver', noDelimiter: true, noShadow: true});
|
|
|
|
|
|
|
|
const validateEmail = () => {
|
|
|
|
const value = emailInputField.value;
|
|
|
|
const match = matchEmail(value);
|
|
|
|
if(!match || match[0].length !== value.length) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
const validatePhone = () => {
|
|
|
|
return !!telInputField.value.match(/\d/);
|
|
|
|
};
|
|
|
|
|
|
|
|
if(invoice.pFlags.name_requested) nameInputField = new InputField({label: 'PaymentShippingName', maxLength: 256, required: true});
|
|
|
|
if(invoice.pFlags.email_requested) emailInputField = new InputField({label: 'PaymentShippingEmailPlaceholder', maxLength: 64, required: true, validate: validateEmail});
|
|
|
|
if(invoice.pFlags.phone_requested) telInputField = new TelInputField({required: true, validate: validatePhone});
|
|
|
|
|
|
|
|
receiverSection.content.append(...[
|
|
|
|
nameInputField,
|
|
|
|
emailInputField,
|
|
|
|
telInputField,
|
|
|
|
].filter(Boolean).map((inputField) => inputField.container));
|
|
|
|
}
|
|
|
|
|
|
|
|
const saveCheckboxField = new CheckboxField({
|
|
|
|
text: 'PaymentShippingSave',
|
|
|
|
checked: true
|
|
|
|
});
|
|
|
|
const saveRow = new Row({
|
|
|
|
checkboxField: saveCheckboxField,
|
|
|
|
subtitleLangKey: 'PaymentShippingSaveInfo',
|
|
|
|
noCheckboxSubtitle: true
|
|
|
|
});
|
|
|
|
|
|
|
|
(receiverSection || addressSection).content.append(saveRow.container);
|
|
|
|
|
|
|
|
this.scrollable.append(...[addressSection, receiverSection].filter(Boolean).map((section) => section.container));
|
|
|
|
|
|
|
|
const payButton = PaymentButton({
|
|
|
|
key: 'PaymentInfo.Done',
|
|
|
|
onClick: async() => {
|
|
|
|
const selectedCountry = countryInputField && countryInputField.getSelected().country;
|
|
|
|
const data: PaymentShippingAddress = {
|
|
|
|
_: 'paymentRequestedInfo',
|
|
|
|
shipping_address: selectedCountry && {
|
|
|
|
_: 'postAddress',
|
|
|
|
street_line1: address1InputField.value,
|
|
|
|
street_line2: address2InputField.value,
|
|
|
|
city: cityInputField.value,
|
|
|
|
state: stateInputField.value,
|
|
|
|
// country: countryInputField.value,
|
|
|
|
country_iso2: selectedCountry?.iso2,
|
|
|
|
post_code: postcodeInputField.value,
|
|
|
|
},
|
|
|
|
name: nameInputField?.value,
|
|
|
|
email: emailInputField?.value,
|
|
|
|
phone: telInputField?.value
|
|
|
|
};
|
|
|
|
|
|
|
|
try {
|
|
|
|
const requestedInfo = await this.managers.appPaymentsManager.validateRequestedInfo(this.inputInvoice, data, saveCheckboxField?.checked);
|
|
|
|
|
|
|
|
this.dispatchEvent('finish', {
|
|
|
|
shippingAddress: data,
|
|
|
|
requestedInfo
|
|
|
|
});
|
|
|
|
|
|
|
|
this.hide();
|
|
|
|
} catch(err: any) {
|
|
|
|
const errorMap: {[err: string]: InputField} = {
|
|
|
|
ADDRESS_STREET_LINE1_INVALID: address1InputField,
|
|
|
|
ADDRESS_STREET_LINE2_INVALID: address2InputField,
|
|
|
|
ADDRESS_COUNTRY_INVALID: countryInputField,
|
|
|
|
ADDRESS_CITY_INVALID: cityInputField,
|
|
|
|
ADDRESS_STATE_INVALID: stateInputField,
|
|
|
|
ADDRESS_POSTCODE_INVALID: postcodeInputField,
|
|
|
|
|
|
|
|
REQ_INFO_NAME_INVALID: nameInputField,
|
|
|
|
REQ_INFO_EMAIL_INVALID: emailInputField,
|
|
|
|
REQ_INFO_PHONE_INVALID: telInputField
|
|
|
|
};
|
|
|
|
|
|
|
|
const inputField = errorMap[(err as ApiError).type];
|
|
|
|
if(inputField) {
|
|
|
|
inputField.setError();
|
|
|
|
(err as any).handled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
this.body.append(this.btnConfirmOnEnter = payButton);
|
|
|
|
|
|
|
|
if(savedInfo) {
|
|
|
|
const shippingAddress = savedInfo.shipping_address;
|
|
|
|
if(shippingAddress) {
|
|
|
|
address1InputField.value = shippingAddress.street_line1;
|
|
|
|
address2InputField.value = shippingAddress.street_line2;
|
|
|
|
cityInputField.value = shippingAddress.city;
|
|
|
|
stateInputField.value = shippingAddress.state;
|
|
|
|
countryInputField.selectCountryByIso2(shippingAddress.country_iso2);
|
|
|
|
postcodeInputField.value = shippingAddress.post_code;
|
|
|
|
}
|
|
|
|
|
|
|
|
savedInfo.name && nameInputField && (nameInputField.value = savedInfo.name);
|
|
|
|
savedInfo.email && emailInputField && (emailInputField.value = savedInfo.email);
|
|
|
|
savedInfo.phone && telInputField && (telInputField.value = savedInfo.phone);
|
|
|
|
}
|
|
|
|
|
|
|
|
const {validate} = handleInputFieldsOnChange([
|
|
|
|
address1InputField,
|
|
|
|
address2InputField,
|
|
|
|
cityInputField,
|
|
|
|
stateInputField,
|
|
|
|
countryInputField,
|
|
|
|
postcodeInputField,
|
|
|
|
nameInputField,
|
|
|
|
emailInputField,
|
|
|
|
telInputField
|
|
|
|
].filter(Boolean), (valid) => {
|
|
|
|
payButton.disabled = !valid;
|
|
|
|
});
|
|
|
|
|
|
|
|
validate();
|
|
|
|
|
|
|
|
this.show();
|
|
|
|
|
|
|
|
let focusField: InputField;
|
|
|
|
if(this.focus) {
|
|
|
|
const focusMap: {[field in ShippingFocusField]?: InputField} = {
|
|
|
|
name: nameInputField,
|
|
|
|
email: emailInputField,
|
|
|
|
phone: telInputField
|
|
|
|
};
|
|
|
|
|
|
|
|
focusField = focusMap[this.focus];
|
|
|
|
} else {
|
|
|
|
focusField = address1InputField;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(focusField) {
|
|
|
|
placeCaretAtEnd(focusField.input);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|