iticket-seatingplan-dev 1.6.9 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = InvalidSeatsPopup;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _encodedSvgs = require("./assets/encodedSvgs");
9
+ var _TicketIcon = _interopRequireDefault(require("./icons/TicketIcon"));
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ function InvalidSeatsPopup(_ref) {
12
+ let {
13
+ onClose
14
+ } = _ref;
15
+ return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
16
+ className: "pricing-popup-backdrop",
17
+ onClick: onClose
18
+ }), /*#__PURE__*/_react.default.createElement("div", {
19
+ className: "pricing-popup remove-multiple-seats-popup",
20
+ role: "dialog",
21
+ "aria-modal": "true"
22
+ }, /*#__PURE__*/_react.default.createElement("div", {
23
+ className: "popup-header"
24
+ }, /*#__PURE__*/_react.default.createElement(_TicketIcon.default, {
25
+ className: "ticket-icon",
26
+ height: "86px",
27
+ width: "86px"
28
+ }), /*#__PURE__*/_react.default.createElement("button", {
29
+ className: "close-button",
30
+ "aria-label": "close popup",
31
+ onClick: onClose
32
+ }, /*#__PURE__*/_react.default.createElement("img", {
33
+ src: _encodedSvgs.closeIconWhite,
34
+ alt: "close",
35
+ height: "20px",
36
+ width: "20px"
37
+ })), /*#__PURE__*/_react.default.createElement("h3", null, "Seat selection")), /*#__PURE__*/_react.default.createElement("div", {
38
+ className: "pricing-popup-content"
39
+ }, /*#__PURE__*/_react.default.createElement("h4", {
40
+ className: "quantity-heading"
41
+ }, "The seats you've chosen aren't available. They may leave a single seat on its own, or there may not be enough seats in the row for your selection. Please select different seats to continue."), /*#__PURE__*/_react.default.createElement("div", {
42
+ className: "buttons buttons-single"
43
+ }, /*#__PURE__*/_react.default.createElement("button", {
44
+ className: "add-cart",
45
+ onClick: onClose
46
+ }, "Ok")))));
47
+ }
@@ -59,10 +59,13 @@ function SeatMap(_ref) {
59
59
  setSelectQuantityPopupOpen,
60
60
  desiredSeatQuantity,
61
61
  setSeatsToRemove,
62
- setRemoveMultipleSeatsPopupOpen
62
+ setRemoveMultipleSeatsPopupOpen,
63
+ setInvalidSeatsPopupOpen
63
64
  } = _ref;
64
65
  const [isLegendOpen, setIsLegendOpen] = (0, _react.useState)(false);
65
66
  const [isDragging, setIsDragging] = (0, _react.useState)(false);
67
+ const [highlightedSeats, setHighlightedSeats] = (0, _react.useState)([]);
68
+ const [greyedOutSeats, setGreyedOutSeats] = (0, _react.useState)([]);
66
69
  const drawLayersRef = (0, _react.useRef)(null);
67
70
  const drawRef = (0, _react.useRef)(null);
68
71
  const popupRef = (0, _react.useRef)(null);
@@ -421,9 +424,7 @@ function SeatMap(_ref) {
421
424
  zIndex: 10
422
425
  }) : /*#__PURE__*/_react.default.createElement(_reactLeaflet.Circle, {
423
426
  center: [s.r.includes("NORTH") ? getNorthSeatLat(s) : seatCenter.lat, seatCenter.lng],
424
- pathOptions: (0, _utils.getInitialColor)(s, price, !hasSeatPrices,
425
- // TEST selected state for multiselect
426
- !!selectedSeats.find(selectedSeat => selectedSeat.ssId === s.ssId)),
427
+ pathOptions: (0, _utils.getInitialColor)(s, price, !hasSeatPrices, selectedSeats.some(selectedSeat => selectedSeat.ssId === s.ssId) || highlightedSeats.some(hs => hs.ssId === s.ssId), greyedOutSeats.some(gs => gs.ssId === s.ssId)),
427
428
  radius: 12000,
428
429
  eventHandlers: {
429
430
  click: e => {
@@ -431,12 +432,18 @@ function SeatMap(_ref) {
431
432
  map.closePopup();
432
433
  if (s.s === _utils.statuses.USER_PENDING) {
433
434
  const newSeatsToRemove = (0, _utils.getAdjacentBookedSeats)(s, seatsMap);
434
- setSeatsToRemove(newSeatsToRemove);
435
- setRemoveMultipleSeatsPopupOpen(true);
436
- }
437
- if (selectedSeats.length > 0 && selectedSeats.length === desiredSeatQuantity) {
435
+ if (newSeatsToRemove.length === 1) {
436
+ handleClickSeat(e, s);
437
+ } else {
438
+ setSeatsToRemove(newSeatsToRemove);
439
+ setRemoveMultipleSeatsPopupOpen(true);
440
+ }
441
+ } else if (highlightedSeats.length > 0 && highlightedSeats.length === desiredSeatQuantity) {
442
+ setSelectedSeats([...highlightedSeats]);
438
443
  setPricingPopupOpen(true);
439
- } else if (s.s === _utils.statuses.USER_PENDING) {}
444
+ } else if (greyedOutSeats.some(gs => gs.ssId === s.ssId)) {
445
+ setInvalidSeatsPopupOpen(true);
446
+ }
440
447
  } else if (mode === _utils.modes.SINGLE && hasSeatPrices) {
441
448
  handleClickSeat(e, s);
442
449
  }
@@ -462,12 +469,23 @@ function SeatMap(_ref) {
462
469
  setSelectedSeats(prev => [...prev, s]);
463
470
  }
464
471
  } else {
465
- setSelectedSeats([]);
466
472
  if (seats.preventOrphanedSeats && desiredSeatQuantity > 0 && s.s === _utils.statuses.UNSOLD) {
467
473
  const seatsToBook = (0, _utils.getValidSeats)(s, seatsMap, desiredSeatQuantity);
468
- setSelectedSeats(seatsToBook);
474
+ if (seatsToBook.valid) {
475
+ setHighlightedSeats(seatsToBook.seats);
476
+ } else {
477
+ setGreyedOutSeats(seatsToBook.seats);
478
+ }
469
479
  }
470
480
  }
481
+ },
482
+ mouseout: () => {
483
+ if (highlightedSeats.length > 0) {
484
+ setHighlightedSeats([]);
485
+ }
486
+ if (greyedOutSeats.length > 0) {
487
+ setGreyedOutSeats([]);
488
+ }
471
489
  }
472
490
  }
473
491
  // value={s}
@@ -62,19 +62,19 @@ const PriceSelect = _ref => {
62
62
  };
63
63
  function PricingPopup(_ref2) {
64
64
  let {
65
- cancel,
65
+ onClose,
66
66
  groupedSelectedSeats,
67
67
  pricing,
68
68
  priceSectionIds,
69
69
  batchAddTicketsToCart,
70
70
  selectedSeatsWithPricing,
71
- singleSeats
71
+ isSingleSeats
72
72
  } = _ref2;
73
73
  const [seatGroupsToBook, setSeatGroupsToBook] = (0, _react.useState)(groupedSelectedSeats);
74
74
  const [singleSeatsToBook, setSingleSeatsToBook] = (0, _react.useState)(selectedSeatsWithPricing);
75
75
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
76
76
  className: "pricing-popup-backdrop",
77
- onClick: cancel
77
+ onClick: onClose
78
78
  }), /*#__PURE__*/_react.default.createElement("div", {
79
79
  className: "pricing-popup",
80
80
  role: "dialog",
@@ -88,7 +88,7 @@ function PricingPopup(_ref2) {
88
88
  }), /*#__PURE__*/_react.default.createElement("button", {
89
89
  className: "close-button",
90
90
  "aria-label": "close popup",
91
- onClick: cancel
91
+ onClick: onClose
92
92
  }, /*#__PURE__*/_react.default.createElement("img", {
93
93
  src: _encodedSvgs.closeIconWhite,
94
94
  alt: "close",
@@ -98,7 +98,7 @@ function PricingPopup(_ref2) {
98
98
  className: "pricing-popup-content"
99
99
  }, /*#__PURE__*/_react.default.createElement("div", {
100
100
  className: "seat-list"
101
- }, !singleSeats && groupedSelectedSeats ? Object.entries(seatGroupsToBook).map(_ref3 => {
101
+ }, !isSingleSeats && groupedSelectedSeats ? Object.entries(seatGroupsToBook).map(_ref3 => {
102
102
  let [id, seatGroup] = _ref3;
103
103
  const seatPriceages = pricing.filter(price => (!priceSectionIds || priceSectionIds.includes(price.psId)) && price.psId === parseInt(id));
104
104
  return /*#__PURE__*/_react.default.createElement("div", {
@@ -119,7 +119,7 @@ function PricingPopup(_ref2) {
119
119
  }) : /*#__PURE__*/_react.default.createElement("p", {
120
120
  className: "no-prices-available"
121
121
  }, "Oops, looks like there are no prices available for this section."));
122
- }) : singleSeats && selectedSeatsWithPricing ? selectedSeatsWithPricing.map(_ref4 => {
122
+ }) : isSingleSeats && selectedSeatsWithPricing ? selectedSeatsWithPricing.map(_ref4 => {
123
123
  let {
124
124
  seat,
125
125
  priceage
@@ -151,16 +151,16 @@ function PricingPopup(_ref2) {
151
151
  className: "buttons"
152
152
  }, /*#__PURE__*/_react.default.createElement("button", {
153
153
  className: "cancel",
154
- onClick: cancel
154
+ onClick: onClose
155
155
  }, "Cancel"), /*#__PURE__*/_react.default.createElement("button", {
156
156
  className: "add-cart",
157
157
  onClick: () => {
158
- singleSeats ? batchAddTicketsToCart(singleSeatsToBook) : batchAddTicketsToCart(Object.values(seatGroupsToBook).filter(v => !!v.priceage).flatMap(s => s.seats.map(seat => ({
158
+ isSingleSeats ? batchAddTicketsToCart(singleSeatsToBook) : batchAddTicketsToCart(Object.values(seatGroupsToBook).filter(v => !!v.priceage).flatMap(s => s.seats.map(seat => ({
159
159
  seat,
160
160
  priceage: s.priceage
161
161
  }))));
162
- cancel();
162
+ onClose();
163
163
  },
164
- disabled: singleSeats ? singleSeatsToBook.every(v => !v.priceage) : Object.values(seatGroupsToBook).every(v => !v.priceage)
164
+ disabled: isSingleSeats ? singleSeatsToBook.every(v => !v.priceage) : Object.values(seatGroupsToBook).every(v => !v.priceage)
165
165
  }, "Add to cart")))));
166
166
  }
@@ -15,6 +15,7 @@ var _reactDom = require("react-dom");
15
15
  var _PricingPopup = _interopRequireDefault(require("./PricingPopup"));
16
16
  var _SelectQuantityPopup = _interopRequireDefault(require("./SelectQuantityPopup"));
17
17
  var _RemoveMultipleSeatsPopup = _interopRequireDefault(require("./RemoveMultipleSeatsPopup"));
18
+ var _InvalidSeatsPopup = _interopRequireDefault(require("./InvalidSeatsPopup"));
18
19
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
19
20
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
20
21
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -64,6 +65,7 @@ const SeatingPlan = _ref => {
64
65
  const [selectedSeats, setSelectedSeats] = (0, _react.useState)([]);
65
66
  const [seatsToRemove, setSeatsToRemove] = (0, _react.useState)([]);
66
67
  const [removeMultipleSeatsPopupOpen, setRemoveMultipleSeatsPopupOpen] = (0, _react.useState)(false);
68
+ const [invalidSeatsPopupOpen, setInvalidSeatsPopupOpen] = (0, _react.useState)(false);
67
69
  const mapRef = (0, _react.useRef)(null);
68
70
  const canMultiSelect = bookingMode === _utils.bookingModes.POS;
69
71
  const apiUrl = "".concat(baseUrl, "/legacy/").concat(countryCode, "/shop/events/").concat(eventId, "/").concat(eventVenueId, "/showings/").concat(showingId, "/tickets/allocated/").concat(areaId);
@@ -290,7 +292,7 @@ const SeatingPlan = _ref => {
290
292
  try {
291
293
  for (let seat of seatsToBook) {
292
294
  try {
293
- await fetch(apiUrl, {
295
+ const res = await fetch(apiUrl, {
294
296
  method: "POST",
295
297
  body: JSON.stringify({
296
298
  priceAgeId: seat.priceage.paId,
@@ -303,6 +305,9 @@ const SeatingPlan = _ref => {
303
305
  "basket-key": sessionId
304
306
  }
305
307
  });
308
+ if (!res.ok) {
309
+ throw new Error("".concat(res.status));
310
+ }
306
311
  succeeded.push(seat);
307
312
  } catch (error) {
308
313
  console.error("Failed to book seat ".concat(seat, ":"), error);
@@ -396,12 +401,15 @@ const SeatingPlan = _ref => {
396
401
  try {
397
402
  for (let seat of seatsToRemove) {
398
403
  try {
399
- await fetch("".concat(apiUrl, "/seat/").concat(seat.ssId), {
404
+ const res = await fetch("".concat(apiUrl, "/seat/").concat(seat.ssId), {
400
405
  method: "DELETE",
401
406
  headers: {
402
407
  "basket-key": sessionId
403
408
  }
404
409
  });
410
+ if (!res.ok) {
411
+ throw new Error("".concat(res.status));
412
+ }
405
413
  succeededIds.push(seat.ssId);
406
414
  } catch (error) {
407
415
  console.error("Failed to remove seat ".concat(seat, ":"), error);
@@ -580,10 +588,6 @@ const SeatingPlan = _ref => {
580
588
  }
581
589
  return acc;
582
590
  }, {});
583
- const cancelPriceSelect = () => {
584
- setPricingPopupOpen(false);
585
- setSelectedSeats([]);
586
- };
587
591
 
588
592
  // return seating plan
589
593
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
@@ -598,27 +602,32 @@ const SeatingPlan = _ref => {
598
602
  className: "seating-plan-container ".concat(isFullScreen ? "full-screen" : ""),
599
603
  "data-mode": mode
600
604
  }, pricingPopupOpen && (canMultiSelect || seats.preventOrphanedSeats) ? /*#__PURE__*/_react.default.createElement(_PricingPopup.default, {
601
- cancel: cancelPriceSelect,
605
+ onClose: () => {
606
+ setPricingPopupOpen(false);
607
+ setSelectedSeats([]);
608
+ },
602
609
  groupedSelectedSeats: groupedSelectedSeats,
603
610
  selectedSeatsWithPricing: selectedSeatsWithPricing,
604
611
  priceSectionIds: priceSectionIds,
605
612
  pricing: seats.pricing,
606
613
  batchAddTicketsToCart: batchAddTicketsToCart,
607
- singleSeats: seats.preventOrphanedSeats
608
- }) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null), selectQuantityPopupOpen && /*#__PURE__*/_react.default.createElement(_SelectQuantityPopup.default, {
614
+ isSingleSeats: seats.preventOrphanedSeats
615
+ }) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null), seats.preventOrphanedSeats && selectQuantityPopupOpen ? /*#__PURE__*/_react.default.createElement(_SelectQuantityPopup.default, {
609
616
  quantity: desiredSeatQuantity,
610
617
  setQuantity: v => {
611
618
  setDesiredSeatQuantity(v);
612
619
  setSelectedSeats([]);
613
620
  },
614
621
  onClose: () => setSelectQuantityPopupOpen(false)
615
- }), removeMultipleSeatsPopupOpen && /*#__PURE__*/_react.default.createElement(_RemoveMultipleSeatsPopup.default, {
622
+ }) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null), seats.preventOrphanedSeats && removeMultipleSeatsPopupOpen ? /*#__PURE__*/_react.default.createElement(_RemoveMultipleSeatsPopup.default, {
616
623
  onConfirm: () => {
617
624
  batchRemoveTicketsFromCart(seatsToRemove);
618
625
  setRemoveMultipleSeatsPopupOpen(false);
619
626
  },
620
627
  onClose: () => setRemoveMultipleSeatsPopupOpen(false)
621
- }), /*#__PURE__*/_react.default.createElement(_reactLeaflet.MapContainer, {
628
+ }) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null), seats.preventOrphanedSeats && invalidSeatsPopupOpen ? /*#__PURE__*/_react.default.createElement(_InvalidSeatsPopup.default, {
629
+ onClose: () => setInvalidSeatsPopupOpen(false)
630
+ }) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null), /*#__PURE__*/_react.default.createElement(_reactLeaflet.MapContainer, {
622
631
  zoomSnap: 0,
623
632
  zoomDelta: 1,
624
633
  center: (0, _utils.calculateCenterOfMap)(height, seats.seats),
@@ -660,7 +669,8 @@ const SeatingPlan = _ref => {
660
669
  setSelectQuantityPopupOpen: setSelectQuantityPopupOpen,
661
670
  desiredSeatQuantity: desiredSeatQuantity,
662
671
  setSeatsToRemove: setSeatsToRemove,
663
- setRemoveMultipleSeatsPopupOpen: setRemoveMultipleSeatsPopupOpen
672
+ setRemoveMultipleSeatsPopupOpen: setRemoveMultipleSeatsPopupOpen,
673
+ setInvalidSeatsPopupOpen: setInvalidSeatsPopupOpen
664
674
  }))), mapContainer)) : /*#__PURE__*/_react.default.createElement("div", {
665
675
  className: "loading"
666
676
  }, /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("svg", {
@@ -120,6 +120,10 @@
120
120
  margin-top: 1.2rem;
121
121
  }
122
122
 
123
+ .pricing-popup .buttons.buttons-single {
124
+ justify-content: center;
125
+ }
126
+
123
127
  .pricing-popup .buttons button {
124
128
  display: block;
125
129
  background: transparent;
@@ -132,6 +136,10 @@
132
136
  margin-bottom: 0;
133
137
  }
134
138
 
139
+ .pricing-popup .buttons.buttons-single button {
140
+ width: 100%;
141
+ }
142
+
135
143
  .pricing-popup .buttons button.add-cart {
136
144
  background: var(--accent);
137
145
  color: white;
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.statuses = exports.statusColors = exports.modes = exports.bookingModes = void 0;
7
7
  const statusColors = exports.statusColors = {
8
- unknown: "#95a5a6",
8
+ unknown: "#bdc3c7",
9
9
  available: "#00E640",
10
10
  sold: "#95a5a6",
11
11
  reserved: "#95a5a6",
@@ -11,7 +11,8 @@ const getInitialColor = (s, price, disabled, selected, greyedOut) => {
11
11
  return {
12
12
  fillColor: _enums.statusColors.selected,
13
13
  color: "none",
14
- fillOpacity: s.loading ? 0 : 1
14
+ fillOpacity: s.loading ? 0 : 1,
15
+ stroke: false
15
16
  };
16
17
  }
17
18
  if (greyedOut) {
@@ -94,55 +95,88 @@ const canSelectSingleSeatGivenOrphanRules = (seat, rowSection) => {
94
95
  return true;
95
96
  };
96
97
  exports.canSelectSingleSeatGivenOrphanRules = canSelectSingleSeatGivenOrphanRules;
98
+ const traverse = (arr, seat, direction, rowSectionMap, desiredSeatQuantity, rowSection, ignoreOrphans) => {
99
+ const nextSeatId = direction === "left" ? seat.sb : seat.sa;
100
+ if (nextSeatId) {
101
+ const nextSeat = rowSectionMap.get(nextSeatId);
102
+ if (nextSeat && nextSeat.s === _enums.statuses.UNSOLD && arr.length < desiredSeatQuantity && !(!ignoreOrphans && arr.length === desiredSeatQuantity - 1 && createsOrphan(nextSeat, rowSection, false, arr)) && !arr.some(s => s.sId === nextSeat.sId)) {
103
+ if (direction === "left") {
104
+ arr.unshift(nextSeat);
105
+ } else {
106
+ arr.push(nextSeat);
107
+ }
108
+ if (arr.length < desiredSeatQuantity) {
109
+ traverse(arr, nextSeat, direction, rowSectionMap, desiredSeatQuantity, rowSection, ignoreOrphans);
110
+ }
111
+ }
112
+ }
113
+ };
114
+ const getSeats = (seat, rowSectionMap, desiredSeatQuantity, rowSection, ignoreOrphans) => {
115
+ let seats = [seat];
116
+ traverse(seats, seat, "right", rowSectionMap, desiredSeatQuantity, rowSection, ignoreOrphans);
117
+ if (seats.length < desiredSeatQuantity) {
118
+ traverse(seats, seat, "left", rowSectionMap, desiredSeatQuantity, rowSection, ignoreOrphans);
119
+ }
120
+ const firstSeat = seats[0];
121
+ const sb = rowSectionMap.get(firstSeat.sb);
122
+ const sbb = rowSectionMap.get(sb === null || sb === void 0 ? void 0 : sb.sb);
123
+ const orphanToLeft = sb && sbb && sb.s === _enums.statuses.UNSOLD && sbb.s !== _enums.statuses.UNSOLD || sb && !sbb && sb.s === _enums.statuses.UNSOLD;
124
+ if (seats.length < desiredSeatQuantity || orphanToLeft && !ignoreOrphans) {
125
+ seats = [seat];
126
+ traverse(seats, seat, "left", rowSectionMap, desiredSeatQuantity, rowSection, ignoreOrphans);
127
+ if (seats.length < desiredSeatQuantity) {
128
+ traverse(seats, seat, "right", rowSectionMap, desiredSeatQuantity, rowSection, ignoreOrphans);
129
+ }
130
+ }
131
+ const lastSeat = seats[seats.length - 1];
132
+ const sa = rowSectionMap.get(lastSeat.sa);
133
+ const saa = rowSectionMap.get(sa === null || sa === void 0 ? void 0 : sa.sa);
134
+ const orphanToRight = sa && saa && sa.s === _enums.statuses.UNSOLD && saa.s !== _enums.statuses.UNSOLD || sa && !saa && sa.s === _enums.statuses.UNSOLD;
135
+ if (orphanToRight && !ignoreOrphans) {
136
+ return [];
137
+ }
138
+ return seats;
139
+ };
97
140
  const getValidSeats = (s, seatsMap, desiredSeatQuantity) => {
98
- let seatsToBook = [s];
99
141
  const rowSection = getRowSection(s, seatsMap);
142
+ const rowSectionMap = new Map(rowSection.map(seat => [seat.sId, seat]));
143
+ if (s && desiredSeatQuantity === 1) {
144
+ return {
145
+ seats: [s],
146
+ valid: canSelectSingleSeatGivenOrphanRules(s, rowSection) ? true : false
147
+ };
148
+ }
149
+ const seatsToBook = getSeats(s, rowSectionMap, desiredSeatQuantity, rowSection);
100
150
  if (seatsToBook.length < desiredSeatQuantity) {
101
- const traverse = (seat, direction) => {
102
- const nextSeatId = direction === "left" ? seat.sb : seat.sa;
103
- if (nextSeatId) {
104
- const nextSeat = rowSection.find(v => v.sId === nextSeatId);
105
- if (nextSeat && nextSeat.s === _enums.statuses.UNSOLD && seatsToBook.length < desiredSeatQuantity && !(seatsToBook.length === desiredSeatQuantity - 1 && createsOrphan(nextSeat, rowSection, false, seatsToBook))) {
106
- if (direction === "left") {
107
- seatsToBook.unshift(nextSeat);
108
- } else {
109
- seatsToBook.push(nextSeat);
110
- }
111
- if (seatsToBook.length < desiredSeatQuantity) {
112
- traverse(nextSeat, direction);
151
+ let hasOtherOptions = false;
152
+ const orphaningSeats = getSeats(s, rowSectionMap, desiredSeatQuantity, rowSection, true);
153
+ if (orphaningSeats.length === desiredSeatQuantity) {
154
+ const otherAvailableSeats = rowSection.filter(seat => seat.s === _enums.statuses.UNSOLD && seat.sId !== s.sId);
155
+ if (otherAvailableSeats.length > 0) {
156
+ for (const seat of otherAvailableSeats) {
157
+ const possibleSeats = getSeats(seat, rowSectionMap, desiredSeatQuantity, rowSection);
158
+ if (possibleSeats.length === desiredSeatQuantity) {
159
+ hasOtherOptions = true;
160
+ break;
113
161
  }
114
162
  }
115
163
  }
116
- };
117
- traverse(s, "right");
118
- if (seatsToBook.length < desiredSeatQuantity) {
119
- traverse(s, "left");
164
+ return {
165
+ seats: orphaningSeats,
166
+ valid: hasOtherOptions ? false : true
167
+ };
120
168
  }
121
- const firstSeat = seatsToBook[0];
122
- const sb = rowSection.find(v => v.sId === firstSeat.sb);
123
- const sbb = rowSection.find(v => v.sId === (sb === null || sb === void 0 ? void 0 : sb.sb));
124
- const orphanToLeft = sb && sbb && sb.s === _enums.statuses.UNSOLD && sbb.s !== _enums.statuses.UNSOLD || sb && !sbb && sb.s === _enums.statuses.UNSOLD;
125
- if (seatsToBook.length < desiredSeatQuantity || orphanToLeft) {
126
- seatsToBook = [s];
127
- traverse(s, "left");
128
- if (seatsToBook.length < desiredSeatQuantity) {
129
- traverse(s, "right");
130
- }
131
- }
132
- }
133
- if (seatsToBook.length === 1 && desiredSeatQuantity === 1) {
134
- return canSelectSingleSeatGivenOrphanRules(s, rowSection) ? seatsToBook : [];
135
- }
136
- if (seatsToBook.length === desiredSeatQuantity && !(seatsToBook.length === 1 && createsOrphan(s, rowSection, false, seatsToBook))) {
137
- return seatsToBook;
138
169
  }
139
- return [];
170
+ return {
171
+ seats: seatsToBook,
172
+ valid: seatsToBook.length === desiredSeatQuantity ? true : false
173
+ };
140
174
  };
141
175
  exports.getValidSeats = getValidSeats;
142
176
  const getAdjacentBookedSeats = (seat, seatsMap) => {
143
177
  const rowSection = getRowSection(seat, seatsMap);
144
178
  const adjacentBookedSeats = [seat];
145
- const traverse = (seat, direction) => {
179
+ const traverseRow = (seat, direction) => {
146
180
  const nextSeatId = direction === "left" ? seat.sb : seat.sa;
147
181
  if (nextSeatId) {
148
182
  const nextSeat = rowSection.find(v => v.sId === nextSeatId);
@@ -152,12 +186,12 @@ const getAdjacentBookedSeats = (seat, seatsMap) => {
152
186
  } else {
153
187
  adjacentBookedSeats.push(nextSeat);
154
188
  }
155
- traverse(nextSeat, direction);
189
+ traverseRow(nextSeat, direction);
156
190
  }
157
191
  }
158
192
  };
159
- traverse(seat, "right");
160
- traverse(seat, "left");
193
+ traverseRow(seat, "right");
194
+ traverseRow(seat, "left");
161
195
  return adjacentBookedSeats;
162
196
  };
163
197
  exports.getAdjacentBookedSeats = getAdjacentBookedSeats;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "iticket-seatingplan-dev",
3
3
  "description": "Seating plan with FLEXi pricing",
4
4
  "author": "gedwyne",
5
- "version": "1.6.9",
5
+ "version": "1.7.0",
6
6
  "private": false,
7
7
  "keywords": [
8
8
  "iticket",