wip: OrdersController#new
This commit is contained in:
@@ -2,32 +2,25 @@
|
||||
// Run that command whenever you add a new controller or create them with
|
||||
// ./bin/rails generate stimulus controllerName
|
||||
|
||||
import { application } from "./application"
|
||||
import { application } from "./application";
|
||||
|
||||
import LogoutController from "./logout_controller";
|
||||
application.register("logout", LogoutController);
|
||||
|
||||
import CounterController from "./counter_controller"
|
||||
import CounterController from "./counter_controller";
|
||||
application.register("counter", CounterController);
|
||||
|
||||
import FlashMessageController from "./flash_message_controller"
|
||||
import FlashMessageController from "./flash_message_controller";
|
||||
application.register("flash-message", FlashMessageController);
|
||||
|
||||
import TicketSelectionController from "./ticket_selection_controller"
|
||||
application.register("ticket-selection", TicketSelectionController);
|
||||
import TicketSelectionController from "./ticket_selection_controller";
|
||||
// application.register("ticket-selection", TicketSelectionController);
|
||||
|
||||
import HeaderController from "./header_controller"
|
||||
import HeaderController from "./header_controller";
|
||||
application.register("header", HeaderController);
|
||||
|
||||
import EventFormController from "./event_form_controller"
|
||||
import EventFormController from "./event_form_controller";
|
||||
application.register("event-form", EventFormController);
|
||||
|
||||
import TicketTypeFormController from "./ticket_type_form_controller"
|
||||
import TicketTypeFormController from "./ticket_type_form_controller";
|
||||
application.register("ticket-type-form", TicketTypeFormController);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,150 +1,169 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
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 }
|
||||
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()
|
||||
this.updateCartSummary();
|
||||
this.bindFormSubmission();
|
||||
}
|
||||
|
||||
// Bind form submission to handle cart storage
|
||||
bindFormSubmission() {
|
||||
if (this.hasFormTarget) {
|
||||
this.formTarget.addEventListener('submit', this.submitCart.bind(this))
|
||||
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
|
||||
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()
|
||||
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
|
||||
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()
|
||||
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
|
||||
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
|
||||
if (value < 0) value = 0;
|
||||
if (value > max) value = max;
|
||||
|
||||
input.value = value
|
||||
this.updateCartSummary()
|
||||
input.value = value;
|
||||
this.updateCartSummary();
|
||||
}
|
||||
|
||||
// Calculate and update the cart summary (total quantity and amount)
|
||||
updateCartSummary() {
|
||||
let totalQuantity = 0
|
||||
let totalAmount = 0
|
||||
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
|
||||
this.quantityInputTargets.forEach((input) => {
|
||||
const quantity = parseInt(input.value) || 0;
|
||||
const price = parseInt(input.dataset.price) || 0;
|
||||
|
||||
totalQuantity += quantity
|
||||
totalAmount += quantity * price
|
||||
})
|
||||
totalQuantity += quantity;
|
||||
totalAmount += quantity * price;
|
||||
});
|
||||
|
||||
// Update the displayed total quantity and amount
|
||||
this.totalQuantityTarget.textContent = totalQuantity
|
||||
this.totalAmountTarget.textContent = `€${(totalAmount / 100).toFixed(2)}`
|
||||
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
|
||||
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
|
||||
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()
|
||||
event.preventDefault();
|
||||
|
||||
const cartData = this.buildCartData()
|
||||
const cartData = this.buildCartData();
|
||||
|
||||
if (Object.keys(cartData).length === 0) {
|
||||
alert('Veuillez sélectionner au moins un billet')
|
||||
return
|
||||
alert("Veuillez sélectionner au moins un billet");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Store cart data in session
|
||||
await this.storeCartInSession(cartData)
|
||||
|
||||
// Redirect to tickets/new page
|
||||
const ticketNewUrl = `/events/${this.eventSlugValue}.${this.eventIdValue}/tickets/new`
|
||||
window.location.href = ticketNewUrl
|
||||
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.')
|
||||
console.error("Error storing cart:", error);
|
||||
alert("Une erreur est survenue. Veuillez réessayer.");
|
||||
}
|
||||
}
|
||||
|
||||
// Build cart data from current form state
|
||||
buildCartData() {
|
||||
const cartData = {}
|
||||
const cartData = {};
|
||||
|
||||
this.quantityInputTargets.forEach(input => {
|
||||
const quantity = parseInt(input.value) || 0
|
||||
this.quantityInputTargets.forEach((input) => {
|
||||
const quantity = parseInt(input.value) || 0;
|
||||
if (quantity > 0) {
|
||||
const ticketTypeId = input.dataset.target
|
||||
const ticketTypeId = input.dataset.target;
|
||||
cartData[ticketTypeId] = {
|
||||
quantity: quantity
|
||||
}
|
||||
quantity: quantity,
|
||||
};
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return cartData
|
||||
return cartData;
|
||||
}
|
||||
|
||||
// Store cart data in session via AJAX
|
||||
async storeCartInSession(cartData) {
|
||||
const storeCartUrl = `/api/v1/events/${this.eventIdValue}/store_cart`
|
||||
const storeCartUrl = `/api/v1/events/${this.eventIdValue}/store_cart`;
|
||||
|
||||
const response = await fetch(storeCartUrl, {
|
||||
method: 'POST',
|
||||
method: "POST",
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
|
||||
"Content-Type": "application/json",
|
||||
"X-CSRF-Token": document
|
||||
.querySelector('meta[name="csrf-token"]')
|
||||
.getAttribute("content"),
|
||||
},
|
||||
body: JSON.stringify({ cart: cartData })
|
||||
})
|
||||
body: JSON.stringify({ cart: cartData }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to store cart data: ${response.status} ${response.statusText}`)
|
||||
throw new Error(
|
||||
`Failed to store cart data: ${response.status} ${response.statusText}`,
|
||||
);
|
||||
}
|
||||
|
||||
return response.json()
|
||||
return response.json();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user