Picking Seats

A click on Choose seats opens the seat picker. It's a component of its own, SeatPicker, and the editor has it ready in SeatPicker.jsx: a card with a heading and an empty grid. It gets the chosen showtime in the prop showtime. Which showtime is chosen is state of Showtimes, chosen: null at first, when there's none, and the showtime's object after a click on its button. The picker is shown only when there is one, with &&:

{chosen !== null && (
    <SeatPicker key={chosen.id} showtime={chosen} />
)}

The key is there for the same reason as with the flashcards in the Final Project of the React course. The picker will remember which seats the visitor selects. When they choose another showtime, React would keep the same SeatPicker with other props, and the seats selected for Friday would stay selected on Saturday. With a different key for each showtime, React makes a new picker, with nothing selected.

The seats. At the top of SeatPicker.jsx, the array seats has the names of all 40 seats, from A1 to E8, made with two loops, as in the old script. In the grid, map() turns them into buttons. A seat that's sold, one in showtime.taken, is disabled and gets the class taken. A seat the visitor selects gets the class selected. A seat can have several classes, so className is a template literal this time: seat always, and each of the other two or nothing, with the conditional operator:

className={`seat ${isTaken(seat) ? "taken" : ""} ${selected.includes(seat) ? "selected" : ""}`}

For a free seat that isn't selected, the result is "seat ", with two spaces at the end, which does no harm: spaces only separate classes.

The selected seats are an array in state, selected, empty at first. A click on a seat adds it with spread, or takes it out with filter() if it's selected already, as in the exercises Adding to an Array and Removing from an Array of the State lesson. Under the grid, the picker shows how many seats are selected and what they cost. One thing to watch there: in total: ${selected.length * showtime.price}, the $ is just a character of the text, the dollar sign, and the curly braces hold the value. It isn't a template literal, which only exists between backticks.

Instructions

  1. In Showtimes, add the state chosen, null at first, and let each Choose seats button set it to its showtime: onClick={() => setChosen(showtime)}. Under the table, show the picker as in the first example (import SeatPicker). Choose a showtime: the picker's heading names it.

  2. In SeatPicker.jsx, write the function isTaken(seat), which returns showtime.taken.includes(seat). In the grid, show a button for each seat, with the key and the text seat, the class seat, and when isTaken(seat) is true, the class taken as well and disabled={isTaken(seat)}. For now, write the className without selected: {`seat ${isTaken(seat) ? "taken" : ""}`}.

  3. Add the state selected, an empty array (import useState), and the handler handleToggleSeat(seat), which adds the seat to selected or takes it out. Give each seat onClick={() => handleToggleSeat(seat)} and the class selected, as in the example above. Under the grid, show <p>Seats: {selected.length}, total: ${selected.length * showtime.price}</p>. Select a few seats, and then choose another showtime.