import { Controller } from "@hotwired/stimulus"; import { loadStripe } from "@stripe/stripe-js"; export default class extends Controller { static targets = ["key", "submit", "firstname", "lastname", "email", "phone", "ticketType", "foodType", "note"]; stripe; async connect() { this.stripe = await loadStripe(this.keyTarget.textContent); } addEntry(event) { event.preventDefault(); const template = this.element.querySelector(".forms").firstElementChild.cloneNode(true); template.querySelectorAll('select, input').forEach(element => { element.value = ''; if (element.id) { element.id = `${element.id}_${Date.now()}`; } }); template.querySelectorAll('label').forEach(label => { const forAttribute = label.getAttribute('for'); if (forAttribute) { label.setAttribute('for', `${forAttribute}_${Date.now()}`); } }); template.classList.add('opacity-0'); this.element.querySelector(".forms").appendChild(template); requestAnimationFrame(() => { template.classList.remove('opacity-0'); template.classList.add('transition-all', 'duration-300'); }); } removeEntry(event) { event.preventDefault(); const forms = this.element.querySelector(".forms"); if (forms.childElementCount <= 1) { return; } const ticketElement = event.currentTarget.closest(".bg-white\\/80"); if (!ticketElement) return; ticketElement.classList.add('opacity-0', 'transition-all', 'duration-300'); setTimeout(() => { ticketElement.remove(); }, 300); } submit(event) { event.preventDefault(); if (!this.validateForm()) { return; } this.submitTarget.querySelector("span").classList.add("hidden"); this.submitTarget.querySelector("svg.arrow").classList.add("hidden"); this.submitTarget.querySelector("svg.loader").classList.remove("hidden"); const tickets = this.element.querySelectorAll(".forms > div"); const personalData = this.getPersonalData(); const ticketData = this.getTicketData(tickets); const formData = { personal: personalData, tickets: ticketData }; fetch("/ticket/submit", { method: "POST", body: JSON.stringify(formData), headers: { "Content-Type": "application/json", }, }).then((response) => { if (!response.ok) { this.submitTarget.querySelector("svg.error").classList.add("hidden"); this.submitTarget.querySelector("svg.loader").classList.remove("hidden"); this.submitTarget.querySelector("span").classList.remove("hidden"); this.showError("Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut."); } else { response.json().then((data) => { this.stripe.redirectToCheckout({ sessionId: data.id, }); }); } }); } validateForm() { let isValid = true; ['firstname', 'lastname', 'email'].forEach(field => { const target = this[`${field}Target`]; if (!target.value.trim()) { this.showFieldError(target); isValid = false; } }); this.element.querySelectorAll(".forms > div").forEach(ticket => { const selects = ticket.querySelectorAll('select[required]'); selects.forEach(select => { if (!select.value) { this.showFieldError(select); isValid = false; } }); }); return isValid; } showFieldError(element) { element.classList.add('border-red-500', 'focus:border-red-500', 'focus:ring-red-200'); element.addEventListener('input', () => { element.classList.remove('border-red-500', 'focus:border-red-500', 'focus:ring-red-200'); }, { once: true }); } showError(message) { const errorDiv = document.createElement('div'); errorDiv.className = 'fixed top-4 right-4 bg-red-50 border-l-4 border-red-500 p-4 rounded shadow-lg transform transition-all duration-500 opacity-0 translate-x-4'; errorDiv.innerHTML = `
${message}