// 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 -> Matrix console.log("Matrix -> Matrix"); 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'));