cineflex/public/js/seat-chooser.js

129 lines
4.8 KiB
JavaScript

// this file should contain a class that gets info from /api/showings/{id}
// and renders the seat chooser
// there may be multiple seats selected at once
// the input is a matrix with null OR a seat object
class Seat {
constructor(id, row, col, linked, reserved) {
this.id = id; // database id
this.row = row;
this.col = col;
this.linked = linked; // linked seat
this.reserved = reserved;
}
}
class SeatChooser {
constructor(showingId, container) {
if (container.innerText === '') {
container.innerText = 'Loading...';
}
this.showingId = showingId; // id of the showing
this.container = container; // the container to render the seat chooser in
this.seats = []; // array of nulls and Seat objects
this.selectedSeats = []; // array of Seat objects
this.init();
}
async init() {
let showingJson = await (await fetch(`/api/showings/${this.showingId}`)).json();
let roomMatrix = await (await fetch(`/api/showings/${this.showingId}/seatMatrix`)).json();
// Matrix<json | null> -> Matrix<Seat | null>
console.log("Matrix<json | null> -> Matrix<Seat | null>");
this.seats = roomMatrix.map((row, rowIndex) => {
return row.map((seat, colIndex) => {
if (seat === null) {
return null;
}
return new Seat(
seat['seat_id'],
seat['seat_row'],
seat['seat_column'],
seat['seat_linked_id'],
seat['reserved']
);
});
});
console.log(this.seats);
this.render();
}
render() {
console.log("rendering");
let linkedCache = false;
// render the seat chooser
this.container.innerHTML = '';
// this -> row -> seat
this.seats.forEach((row, rowIndex) => {
let rowDiv = document.createElement('div');
rowDiv.classList.add('row');
row.forEach((seat, colIndex) => {
let seatDiv = document.createElement('div');
if (seat) {
seatDiv.classList.add('seat');
seatDiv.classList.add(seat.reserved ? 'reserved' : 'available');
if (seat.linked) {
// if cache is false, then this is the first seat in the linked pair
if (!linkedCache) {
seatDiv.classList.add('linked-left');
linkedCache = true;
} else {
seatDiv.classList.add('linked-right');
linkedCache = false;
}
} else {
linkedCache = false;
}
seatDiv.innerText = `${seat.row}-${seat.col}`;
seatDiv.dataset.id = seat.id;
seatDiv.dataset.row = seat.row;
seatDiv.dataset.col = seat.col;
seatDiv.addEventListener('click', (e) => {
this.toggleSeat(seat, e);
});
} else {
seatDiv.classList.add('no-seat');
}
rowDiv.appendChild(seatDiv);
});
this.container.appendChild(rowDiv);
});
}
toggleSeat(seat, e) {
// toggle the seat
// because of linked seats, we need to toggle both seats
if (seat.reserved) return;
e.target.classList.toggle('selected');
if (seat.linked) {
// beware that you can click on the left or right seat
// the left seat has class linked-left and the right seat has class linked-right
let leftbool = e.target.classList.contains('linked-left');
let linkedSeat = this.seats[seat.row - 1][leftbool ? seat.col - 1 : seat.col + 1];
if (leftbool) e.target.nextElementSibling.classList.toggle('selected');
else e.target.previousElementSibling.classList.toggle('selected');
if (this.selectedSeats.includes(linkedSeat)) {
this.selectedSeats.splice(this.selectedSeats.indexOf(linkedSeat), 1);
this.selectedSeats.splice(this.selectedSeats.indexOf(seat), 1);
} else {
this.selectedSeats.push(linkedSeat);
this.selectedSeats.push(seat);
}
} else {
if (this.selectedSeats.includes(seat)) {
this.selectedSeats.splice(this.selectedSeats.indexOf(seat), 1);
} else {
this.selectedSeats.push(seat);
}
}
}
}
let seatChooser = new SeatChooser(1, document.getElementById('seat-chooser'));