Implement ticket selection with Stimulus controller and improve code documentation

- Add ticket selection functionality to event show page using Stimulus
- Create ticket_selection_controller.js for handling ticket quantity changes
- Update ticket card component and event show view to work with Stimulus
- Add comprehensive comments to all JavaScript files for better maintainability
- Remove dependent: :destroy from event ticket_types association
This commit is contained in:
kbe
2025-08-30 14:26:59 +02:00
parent 58dbcf3a6a
commit 56b0a45719
14 changed files with 428 additions and 284 deletions

View File

@@ -0,0 +1,79 @@
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"]
// Initialize the controller and update the cart summary
connect() {
this.updateCartSummary()
}
// 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
}
}
}