class PaymentWidget {
promocodeRoute;
stripe;
elements;
card;
iban;
submitting;
constructor() {
this.promocodeRoute = null;
this.stripe = null;
this.elements = null;
this.card = null;
this.iban = null;
this.submitting = false;
this.paymentForm = document.getElementById('payment-form');
this.promocodeElement = document.querySelector('input[name="promocode"]');
this.initialize();
}
/**
* @param {string} key
* @param {string} phColor
* @param {string} autofillColor
*/
initStripe(key, phColor = '#aab7c4', autofillColor = '#32325d') {
if (document.getElementById('card-element') === null) {
return;
}
let style = {
base: {
color: '',
fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
fontSmoothing: 'antialiased',
fontSize: '16px',
'::placeholder': {
color: phColor
},
':-webkit-autofill': {
color: autofillColor,
},
},
invalid: {
color: '#fa755a',
iconColor: '#fa755a',
':-webkit-autofill': {
color: '#fa755a',
},
}
}
this.stripe = Stripe(key);
this.elements = this.stripe.elements();
this.card = this.elements.create('card', {
hidePostalCode: true,
style: style
});
this.card.mount('#card-element');
// Create an instance of the IBAN Element
this.iban = this.elements.create('iban', {style, supportedCountries: ['SEPA']});
// Add an instance of the IBAN Element into the `iban-element`
if (document.getElementById('iban-element')) {
this.iban.mount('#iban-element');
}
this.card.addEventListener('change', event => {
let displayError = document.getElementById('card-errors');
displayError.textContent = event.error?.message ?? '';
});
}
/**
* @param {string} promocodeRoute
*/
setPromocodeRoute(promocodeRoute) {
this.promocodeRoute = promocodeRoute;
}
getPromocodeRoute() {
return this.promocodeRoute;
}
initialize() {
document.querySelectorAll('[data-payment-mode="iban"]')
.forEach(mode => mode.classList?.add('d-none'));
document.querySelectorAll('button[data-toggle-show]')
.forEach(element => {
element.addEventListener('click', () => {
let paymentModes = document.querySelectorAll('[data-payment-mode]');
paymentModes.forEach(mode => mode.classList.toggle('d-block'));
paymentModes.forEach(mode => mode.classList.toggle('d-none'));
})
})
if (this.promocodeElement) {
this.promocodeElement
.addEventListener('keyup', Commons.debounce(this.checkPromocode.bind(this), 750));
}
if (this.paymentForm) {
this.paymentForm.addEventListener('submit', this.onSubmitPaymentForm.bind(this));
}
}
checkPromocode(event) {
let value = event.target.value;
if (value.length > 3) {
let route = this.getPromocodeRoute().replace('VALUE', value);
fetch(route)
.then(response => response.json())
.then(data => {
let resultContainer = document.getElementById('promocode-res');
resultContainer.innerHTML = `${data.message}`;
resultContainer.classList.remove('d-none');
})
}
}
onSubmitPaymentForm(event) {
if (this.submitting) {
return;
}
let form = event.target;
event.preventDefault();
this.submitting = true;
form.querySelectorAll('button').forEach(btn => btn.disabled = true)
let cardholderName = document.getElementById('cardholder-name');
let email = document.getElementById('email');
if (!cardholderName.value) {
document.getElementById('cardholderName-error')?.classList?.remove('d-none');
form.querySelectorAll('button').forEach(btn => btn.disabled = false)
this.submitting = false;
return false;
}
let submitButton = document.getElementById(event.submitter.id);
let billingDetails = {
name: cardholderName.value,
email: email.value,
address: {}
};
let billingPhone = document.getElementById('billing-phone');
let billingCity = document.getElementById('billing-city');
let billingCountry = document.getElementById('billing-country_iso');
let billingAddress = document.getElementById('billing-address');
let billingZipcode = document.getElementById('billing-zipcode');
if (billingPhone?.value) {
billingDetails.phone = billingPhone.value;
}
if (billingCity?.value) {
billingDetails.address.city = billingCity.value;
}
if (billingCountry?.value) {
billingDetails.address.country = billingCountry.value;
}
if (billingAddress?.value) {
billingDetails.address.line1 = billingAddress.value;
}
if (billingZipcode?.value) {
billingDetails.address.postal_code = billingZipcode.value;
}
if (event.submitter.id === 'iban-button') {
this.stripe.confirmSepaDebitSetup(
submitButton.dataset.secret,
{
payment_method: {
sepa_debit: this.iban,
billing_details: billingDetails
},
}
).then(result => this.handleResult(result, 'iban-errors'));
} else {
Commons.setSpinner(form);
this.stripe.handleCardSetup(
submitButton.dataset.secret, this.card, {
payment_method_data: {
billing_details: billingDetails
}
}
).then(result => this.handleResult(result, 'card-errors'));
}
form.querySelectorAll('button').forEach(btn => btn.disabled = false)
this.submitting = false;
}
/**
* @param {object} result
* @param {string} destId
*/
handleResult(result, destId) {
let form = document.getElementById('payment-form');
console.log(result);
Commons.unsetSpinner(form);
if (result.error) {
// Inform the user if there was an error.
let errorElement = document.getElementById(destId);
errorElement.textContent = result.error.message;
return;
}
let hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'setupIntentId');
hiddenInput.setAttribute('value', result.setupIntent.id);
form.appendChild(hiddenInput);
form.submit();
}
}