feat(show parties): prepare to use ticket cart components
This commit is contained in:
107
app/javascript/controllers/ticket_cart_controller.js
Normal file
107
app/javascript/controllers/ticket_cart_controller.js
Normal file
@@ -0,0 +1,107 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["quantity", "cartCount", "cartTotal", "checkoutButton"]
|
||||
static values = { partyId: String }
|
||||
|
||||
connect() {
|
||||
this.cart = {}
|
||||
this.updateCartDisplay()
|
||||
}
|
||||
|
||||
increaseQuantity(event) {
|
||||
const ticketTypeId = event.currentTarget.dataset.ticketTypeId
|
||||
const max = parseInt(event.currentTarget.dataset.max)
|
||||
const input = this.quantityTargetFor(ticketTypeId)
|
||||
|
||||
const current = parseInt(input.value) || 0
|
||||
if (current < max) {
|
||||
input.value = current + 1
|
||||
this.updateCartItem(ticketTypeId, input)
|
||||
}
|
||||
}
|
||||
|
||||
decreaseQuantity(event) {
|
||||
const ticketTypeId = event.currentTarget.dataset.ticketTypeId
|
||||
const input = this.quantityTargetFor(ticketTypeId)
|
||||
|
||||
const current = parseInt(input.value) || 0
|
||||
if (current > 0) {
|
||||
input.value = current - 1
|
||||
this.updateCartItem(ticketTypeId, input)
|
||||
}
|
||||
}
|
||||
|
||||
updateCartItem(ticketTypeId, input) {
|
||||
const name = input.dataset.name
|
||||
const price = parseInt(input.dataset.price)
|
||||
const quantity = parseInt(input.value) || 0
|
||||
|
||||
if (quantity > 0) {
|
||||
this.cart[ticketTypeId] = {
|
||||
name: name,
|
||||
price: price,
|
||||
quantity: quantity
|
||||
}
|
||||
} else {
|
||||
delete this.cart[ticketTypeId]
|
||||
}
|
||||
|
||||
this.updateCartDisplay()
|
||||
}
|
||||
|
||||
updateCartDisplay() {
|
||||
let totalTickets = 0
|
||||
let totalPrice = 0
|
||||
|
||||
for (let ticketTypeId in this.cart) {
|
||||
totalTickets += this.cart[ticketTypeId].quantity
|
||||
totalPrice += (this.cart[ticketTypeId].price * this.cart[ticketTypeId].quantity) / 100
|
||||
}
|
||||
|
||||
this.cartCountTarget.textContent = totalTickets
|
||||
this.cartTotalTarget.textContent = totalPrice.toFixed(2)
|
||||
|
||||
const checkoutBtn = this.checkoutButtonTarget
|
||||
if (totalTickets > 0) {
|
||||
checkoutBtn.disabled = false
|
||||
} else {
|
||||
checkoutBtn.disabled = true
|
||||
}
|
||||
}
|
||||
|
||||
proceedToCheckout() {
|
||||
if (Object.keys(this.cart).length === 0) {
|
||||
alert('Please select at least one ticket')
|
||||
return
|
||||
}
|
||||
|
||||
const form = document.createElement('form')
|
||||
form.method = 'POST'
|
||||
form.action = `/parties/${this.partyIdValue}/checkout`
|
||||
form.style.display = 'none'
|
||||
|
||||
// Add CSRF token
|
||||
const csrfToken = document.querySelector('meta[name="csrf-token"]').content
|
||||
const csrfInput = document.createElement('input')
|
||||
csrfInput.type = 'hidden'
|
||||
csrfInput.name = 'authenticity_token'
|
||||
csrfInput.value = csrfToken
|
||||
form.appendChild(csrfInput)
|
||||
|
||||
// Add cart data
|
||||
const cartInput = document.createElement('input')
|
||||
cartInput.type = 'hidden'
|
||||
cartInput.name = 'cart'
|
||||
cartInput.value = JSON.stringify(this.cart)
|
||||
form.appendChild(cartInput)
|
||||
|
||||
document.body.appendChild(form)
|
||||
form.submit()
|
||||
}
|
||||
|
||||
// Helper method to find quantity input by ticket type ID
|
||||
quantityTargetFor(ticketTypeId) {
|
||||
return document.querySelector(`#quantity_${ticketTypeId}`)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user