import { Controller } from "@hotwired/stimulus"; // Controller for handling ticket selection on the event show page // Manages quantity inputs, calculates totals, and enables/disables the checkout button export default class extends Controller { static targets = [ "quantityInput", "totalQuantity", "totalAmount", "checkoutButton", "form", ]; static values = { eventSlug: String, eventId: String }; // Initialize the controller and update the cart summary connect() { this.updateCartSummary(); this.bindFormSubmission(); } // Bind form submission to handle cart storage bindFormSubmission() { if (this.hasFormTarget) { this.formTarget.addEventListener("submit", this.submitCart.bind(this)); } } // Increment the quantity for a specific ticket type increment(event) { const ticketTypeId = event.currentTarget.dataset.target; const input = this.quantityInputTargets.find( (input) => input.dataset.target === ticketTypeId, ); const value = parseInt(input.value) || 0; const max = parseInt(input.max) || 0; if (value < max) { input.value = value + 1; this.updateCartSummary(); } } // Decrement the quantity for a specific ticket type decrement(event) { const ticketTypeId = event.currentTarget.dataset.target; const input = this.quantityInputTargets.find( (input) => input.dataset.target === ticketTypeId, ); const value = parseInt(input.value) || 0; if (value > 0) { input.value = value - 1; this.updateCartSummary(); } } // Update quantity when directly edited in the input field updateQuantity(event) { const input = event.currentTarget; let value = parseInt(input.value) || 0; const max = parseInt(input.max) || 0; // Ensure value is within valid range (0 to max available) if (value < 0) value = 0; if (value > max) value = max; input.value = value; this.updateCartSummary(); } // Calculate and update the cart summary (total quantity and amount) updateCartSummary() { let totalQuantity = 0; let totalAmount = 0; // Sum up quantities and calculate total amount this.quantityInputTargets.forEach((input) => { const quantity = parseInt(input.value) || 0; const price = parseInt(input.dataset.price) || 0; totalQuantity += quantity; totalAmount += quantity * price; }); // Update the displayed total quantity and amount this.totalQuantityTarget.textContent = totalQuantity; this.totalAmountTarget.textContent = `€${(totalAmount / 100).toFixed(2)}`; // Enable/disable checkout button based on whether any tickets are selected if (totalQuantity > 0) { this.checkoutButtonTarget.classList.remove( "opacity-50", "cursor-not-allowed", ); this.checkoutButtonTarget.disabled = false; } else { this.checkoutButtonTarget.classList.add( "opacity-50", "cursor-not-allowed", ); this.checkoutButtonTarget.disabled = true; } } // Handle form submission - store cart in session before proceeding async submitCart(event) { event.preventDefault(); const cartData = this.buildCartData(); if (Object.keys(cartData).length === 0) { alert("Veuillez sélectionner au moins un billet"); return; } try { // Store cart data in session await this.storeCartInSession(cartData); // Redirect to orders/new page const OrderNewUrl = `/orders/new`; window.location.href = OrderNewUrl; } catch (error) { console.error("Error storing cart:", error); alert("Une erreur est survenue. Veuillez réessayer."); } } // Build cart data from current form state buildCartData() { const cartData = {}; this.quantityInputTargets.forEach((input) => { const quantity = parseInt(input.value) || 0; if (quantity > 0) { const ticketTypeId = input.dataset.target; cartData[ticketTypeId] = { quantity: quantity, }; } }); return cartData; } // Store cart data in session via AJAX async storeCartInSession(cartData) { const storeCartUrl = `/api/v1/events/${this.eventIdValue}/store_cart`; const response = await fetch(storeCartUrl, { method: "POST", headers: { "Content-Type": "application/json", "X-CSRF-Token": document .querySelector('meta[name="csrf-token"]') .getAttribute("content"), }, body: JSON.stringify({ cart: cartData }), }); if (!response.ok) { throw new Error( `Failed to store cart data: ${response.status} ${response.statusText}`, ); } return response.json(); } }