megacommit
This commit is contained in:
parent
2451ab45cb
commit
34ed81516b
51 changed files with 1200 additions and 251 deletions
24
public/js/freq.js
Normal file
24
public/js/freq.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
class FreqManager {
|
||||
#store;
|
||||
static getInstance() {
|
||||
if (this._instance === null) {
|
||||
this._instance = new FreqManager();
|
||||
}
|
||||
return this._instance;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.#store = {};
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
this.#store[key] = value;
|
||||
}
|
||||
|
||||
get(key) {
|
||||
return this.#store[key];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
window.freq = FreqManager.getInstance();
|
106
public/js/order.js
Normal file
106
public/js/order.js
Normal file
|
@ -0,0 +1,106 @@
|
|||
// DEPENDS ON seat-chooser.js
|
||||
(async () => {
|
||||
let scDiv = document.querySelector('#seat-chooser');
|
||||
let summaryDiv = document.querySelector('#summary-dyn');
|
||||
|
||||
let showingId = scDiv.getAttribute('data-showing-id');
|
||||
let ticketTypes = await (await fetch(`/api/showing/${showingId}/prices`)).json();
|
||||
|
||||
let sc = new SeatChooser(
|
||||
showingId,
|
||||
scDiv,
|
||||
(sc, s, add) => {
|
||||
// seat click callback
|
||||
// sc is the seat chooser
|
||||
// s is the seat // but it's better to look at sc.selectedSeats
|
||||
// add is a boolean indicating whether the seat is being added or removed
|
||||
|
||||
// update the summary
|
||||
summaryDiv.innerHTML = '';
|
||||
sc.selectedSeats.forEach((seat, index) => {
|
||||
// set seat ticket if ticket is not set
|
||||
if (!seat.ticket) seat.ticket = ticketTypes[0];
|
||||
let seatDiv = document.createElement('div');
|
||||
seatDiv.classList.add('seat');
|
||||
let ticketSelect = document.createElement('select');
|
||||
ticketTypes.forEach((ticketType, index) => {
|
||||
let option = document.createElement('option');
|
||||
option.value = index;
|
||||
option.innerText = ticketType.price_type;
|
||||
ticketSelect.appendChild(option);
|
||||
});
|
||||
ticketSelect.classList.add('ticket-select');
|
||||
ticketSelect.value = ticketTypes.indexOf(seat.ticket);
|
||||
ticketSelect.addEventListener('change', (e) => {
|
||||
seat.ticket = ticketTypes[e.target.value];
|
||||
updateTicket(sc, seat, seatDiv);
|
||||
updateTotal(sc);
|
||||
});
|
||||
seatDiv.appendChild(ticketSelect);
|
||||
|
||||
seatDiv.appendChild(document.createTextNode(' '));
|
||||
|
||||
let seatSpan = document.createElement('span');
|
||||
seatSpan.innerText = `Row ${seat.row}, Seat ${seat.col}`;
|
||||
seatSpan.classList.add('seat-span');
|
||||
seatDiv.appendChild(seatSpan);
|
||||
seatDiv.appendChild(document.createTextNode(' '));
|
||||
|
||||
let priceSpan = document.createElement('span');
|
||||
priceSpan.classList.add('price');
|
||||
seatDiv.appendChild(priceSpan);
|
||||
summaryDiv.appendChild(seatDiv);
|
||||
|
||||
updateTicket(sc, seat, seatDiv);
|
||||
});
|
||||
|
||||
updateTotal(sc);
|
||||
|
||||
if (sc.selectedSeats.length == 0) document.querySelector('button#order-button').disabled = true;
|
||||
else document.querySelector('button#order-button').disabled = false;
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
window.freq.set('seat-chooser', sc);
|
||||
})();
|
||||
|
||||
let total = 0;
|
||||
|
||||
function updateTicket(sc, seat, seatDiv) {
|
||||
seatDiv.querySelector('span:last-child').innerText = `€${seat.ticket.price}`;
|
||||
}
|
||||
|
||||
function updateTotal(sc) {
|
||||
total = 0;
|
||||
sc.selectedSeats.forEach(_seat => {
|
||||
total += Number(_seat.ticket.price);
|
||||
});
|
||||
document.querySelector('#summary-total').innerText = `Total: €${total}`;
|
||||
}
|
||||
|
||||
document.querySelector('button#order-button').addEventListener('click', (e) => {
|
||||
let seats = [];
|
||||
window.sc.selectedSeats.forEach(seat => {
|
||||
seats.push({
|
||||
seat: seat.id,
|
||||
ticket: seat.ticket.id
|
||||
});
|
||||
});
|
||||
fetch(`/api/order`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
showing: sc.showingId,
|
||||
seats: seats
|
||||
})
|
||||
}).then(res => {
|
||||
if (res.ok) {
|
||||
window.location = '/order/complete';
|
||||
} else {
|
||||
alert('Error placing order');
|
||||
}
|
||||
});
|
||||
});
|
|
@ -26,19 +26,21 @@ class SeatChooser {
|
|||
status.style.textAlign = 'center';
|
||||
this.container.appendChild(status);
|
||||
}
|
||||
// set the message
|
||||
this.container.querySelector('#seat-chooser-status-message').innerText = msg;
|
||||
// set the message if it exists
|
||||
if (this.container.querySelector('#seat-chooser-status-message'))
|
||||
this.container.querySelector('#seat-chooser-status-message').innerText = msg;
|
||||
}
|
||||
|
||||
constructor(showingId, container, submitCallback) {
|
||||
constructor(showingId, container, seatClickCallback = (sc, s) => {}, submitCallback = null) {
|
||||
this.showingId = showingId; // id of the showing
|
||||
this.container = container; // the container to render the seat chooser in
|
||||
this.submitCallback = submitCallback; // callback function to call when the user submits the form
|
||||
|
||||
this.setLoadingStatus("Initializing...");
|
||||
|
||||
this.seats = []; // array of nulls and Seat objects
|
||||
this.submitCallback = submitCallback; // callback function to call when the user submits the form
|
||||
this.seatClickCallback = seatClickCallback; // callback function to call when the user clicks on a seat
|
||||
|
||||
this.seats = []; // array of nulls and Seat objects
|
||||
this.selectedSeats = []; // array of Seat objects
|
||||
|
||||
this.init();
|
||||
|
@ -171,15 +173,17 @@ class SeatChooser {
|
|||
});
|
||||
buttonContainer.appendChild(clearButton);
|
||||
|
||||
// submit button
|
||||
let submitButton = document.createElement('button');
|
||||
submitButton.classList.add('button');
|
||||
submitButton.style.margin = '1rem';
|
||||
submitButton.innerText = 'Submit';
|
||||
submitButton.addEventListener('click', () => {
|
||||
this.submitCallback(this);
|
||||
});
|
||||
buttonContainer.appendChild(submitButton);
|
||||
if (this.submitCallback !== null) {
|
||||
// submit button
|
||||
let submitButton = document.createElement('button');
|
||||
submitButton.classList.add('button');
|
||||
submitButton.style.margin = '1rem';
|
||||
submitButton.innerText = 'Submit';
|
||||
submitButton.addEventListener('click', () => {
|
||||
this.submitCallback(this);
|
||||
});
|
||||
buttonContainer.appendChild(submitButton);
|
||||
}
|
||||
this.container.appendChild(buttonContainer);
|
||||
}
|
||||
|
||||
|
@ -209,6 +213,7 @@ class SeatChooser {
|
|||
this.selectedSeats.push(seat);
|
||||
}
|
||||
}
|
||||
this.seatClickCallback(this, seat, this.selectedSeats.includes(seat));
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
|
@ -219,21 +224,3 @@ class SeatChooser {
|
|||
this.selectedSeats = [];
|
||||
}
|
||||
}
|
||||
|
||||
let seatChooser = new SeatChooser(1, document.getElementById('seat-chooser'), (sc) => {
|
||||
// gray overlay and show selected seats
|
||||
let overlay = document.createElement('div');
|
||||
overlay.style.position = 'fixed';
|
||||
overlay.style.top = '0';
|
||||
overlay.style.left = '0';
|
||||
overlay.style.width = '100vw';
|
||||
overlay.style.height = '100vh';
|
||||
overlay.style.backgroundColor = 'rgba(0,0,0,0.5)';
|
||||
overlay.style.display = 'flex';
|
||||
overlay.style.justifyContent = 'center';
|
||||
overlay.innerText = 'You selected the following seats: ' + sc.selectedSeats.map(seat => `${seat.row}-${seat.col}`).join(', ');
|
||||
overlay.addEventListener('click', () => {
|
||||
overlay.remove();
|
||||
});
|
||||
sc.container.appendChild(overlay);
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue