@qite/tide-booking-component 1.4.88 → 1.4.90

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.
@@ -38514,13 +38514,22 @@ var formatPrice = function (price, currencyCode) {
38514
38514
  }).format(price);
38515
38515
  };
38516
38516
  var GroupTourFlyIn = function (_a) {
38517
- var _b;
38518
- _a.isLoading;
38519
- var isOpen = _a.isOpen,
38517
+ var _b, _c;
38518
+ var isLoading = _a.isLoading,
38519
+ isOpen = _a.isOpen,
38520
38520
  setIsOpen = _a.setIsOpen;
38521
38521
  var dispatch = reactRedux.useDispatch();
38522
38522
  var context = React.useContext(SearchResultsConfigurationContext);
38523
- var language = (_b = context === null || context === void 0 ? void 0 : context.languageCode) !== null && _b !== void 0 ? _b : 'en-GB';
38523
+ if (isLoading) {
38524
+ return React__default['default'].createElement(
38525
+ React__default['default'].Fragment,
38526
+ null,
38527
+ (_b = context === null || context === void 0 ? void 0 : context.customSpinner) !== null && _b !== void 0
38528
+ ? _b
38529
+ : React__default['default'].createElement(Spinner, null)
38530
+ );
38531
+ }
38532
+ var language = (_c = context === null || context === void 0 ? void 0 : context.languageCode) !== null && _c !== void 0 ? _c : 'en-GB';
38524
38533
  var translations = getTranslations(language);
38525
38534
  var bookingPackageDetails = reactRedux.useSelector(function (state) {
38526
38535
  return state.searchResults;
@@ -38536,13 +38545,34 @@ var GroupTourFlyIn = function (_a) {
38536
38545
  },
38537
38546
  [bookingPackageDetails]
38538
38547
  );
38548
+ var packageKey = ''
38549
+ .concat(bookingPackageDetails === null || bookingPackageDetails === void 0 ? void 0 : bookingPackageDetails.transactionId, '-')
38550
+ .concat(selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0 ? void 0 : selectedBookingPackageDetails.id);
38551
+ var initialSelectedOptionsRef = React.useRef({});
38552
+ React.useEffect(
38553
+ function () {
38554
+ if (!packageKey || !(selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0 ? void 0 : selectedBookingPackageDetails.rooms))
38555
+ return;
38556
+ if (!initialSelectedOptionsRef.current[packageKey]) {
38557
+ initialSelectedOptionsRef.current[packageKey] = {};
38558
+ }
38559
+ selectedBookingPackageDetails.rooms.forEach(function (room, roomIndex) {
38560
+ if (!initialSelectedOptionsRef.current[packageKey][roomIndex]) {
38561
+ initialSelectedOptionsRef.current[packageKey][roomIndex] = room.options.find(function (option) {
38562
+ return option.isSelected;
38563
+ });
38564
+ }
38565
+ });
38566
+ },
38567
+ [packageKey, selectedBookingPackageDetails]
38568
+ );
38539
38569
  var groupedRooms = React.useMemo(
38540
38570
  function () {
38541
38571
  if (!(selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0 ? void 0 : selectedBookingPackageDetails.rooms)) return [];
38542
38572
  return selectedBookingPackageDetails.rooms.map(function (room) {
38543
38573
  var groupedMap = new Map();
38544
38574
  room.options.forEach(function (option) {
38545
- var _a;
38575
+ var _a, _b;
38546
38576
  var key = option.accommodationCode;
38547
38577
  if (!groupedMap.has(key)) {
38548
38578
  groupedMap.set(key, {
@@ -38555,7 +38585,7 @@ var GroupTourFlyIn = function (_a) {
38555
38585
  ? void 0
38556
38586
  : _a.regimes.push({
38557
38587
  id: option.entryLineGuid,
38558
- label: option.regimeName
38588
+ label: (_b = option.regimeName) !== null && _b !== void 0 ? _b : 'No regime'
38559
38589
  });
38560
38590
  });
38561
38591
  return Array.from(groupedMap.values());
@@ -38563,19 +38593,14 @@ var GroupTourFlyIn = function (_a) {
38563
38593
  },
38564
38594
  [selectedBookingPackageDetails]
38565
38595
  );
38566
- if (!bookingPackageDetails) {
38596
+ if (!bookingPackageDetails || !selectedBookingPackageDetails) {
38567
38597
  return null;
38568
38598
  }
38569
38599
  var getSelectedOptionForRoom = function (roomIndex) {
38570
38600
  var _a, _b, _c;
38571
38601
  return (_c =
38572
- (_b =
38573
- (_a = selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0 ? void 0 : selectedBookingPackageDetails.rooms) === null ||
38574
- _a === void 0
38575
- ? void 0
38576
- : _a[roomIndex]) === null || _b === void 0
38577
- ? void 0
38578
- : _b.options) === null || _c === void 0
38602
+ (_b = (_a = selectedBookingPackageDetails.rooms) === null || _a === void 0 ? void 0 : _a[roomIndex]) === null || _b === void 0 ? void 0 : _b.options) ===
38603
+ null || _c === void 0
38579
38604
  ? void 0
38580
38605
  : _c.find(function (option) {
38581
38606
  return option.isSelected;
@@ -38584,18 +38609,18 @@ var GroupTourFlyIn = function (_a) {
38584
38609
  var getSelectedOptionForAccommodation = function (roomIndex, accommodationCode) {
38585
38610
  var _a, _b, _c;
38586
38611
  return (_c =
38587
- (_b =
38588
- (_a = selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0 ? void 0 : selectedBookingPackageDetails.rooms) === null ||
38589
- _a === void 0
38590
- ? void 0
38591
- : _a[roomIndex]) === null || _b === void 0
38592
- ? void 0
38593
- : _b.options) === null || _c === void 0
38612
+ (_b = (_a = selectedBookingPackageDetails.rooms) === null || _a === void 0 ? void 0 : _a[roomIndex]) === null || _b === void 0 ? void 0 : _b.options) ===
38613
+ null || _c === void 0
38594
38614
  ? void 0
38595
38615
  : _c.find(function (option) {
38596
38616
  return option.accommodationCode === accommodationCode && option.isSelected;
38597
38617
  });
38598
38618
  };
38619
+ var getInitialSelectedOptionForRoom = function (roomIndex) {
38620
+ var _a;
38621
+ if (!packageKey) return undefined;
38622
+ return (_a = initialSelectedOptionsRef.current[packageKey]) === null || _a === void 0 ? void 0 : _a[roomIndex];
38623
+ };
38599
38624
  var handlePick = function (roomIndex, selectedGuid) {
38600
38625
  if (!bookingPackageDetails || !selectedBookingPackageDetails) return;
38601
38626
  var updatedBookingPackageDetails = __assign(__assign({}, bookingPackageDetails), {
@@ -38623,52 +38648,39 @@ var GroupTourFlyIn = function (_a) {
38623
38648
  if (isOpen) {
38624
38649
  setIsOpen(false);
38625
38650
  }
38626
- console.log('Booking package details sent to onBook callback:', bookingPackageDetails);
38627
38651
  if (context === null || context === void 0 ? void 0 : context.onBook) {
38628
38652
  context.onBook(bookingPackageDetails);
38629
38653
  }
38630
38654
  };
38631
- var calculateTotalPrice = function () {
38632
- var selectedOptions =
38633
- selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0
38634
- ? void 0
38635
- : selectedBookingPackageDetails.rooms.flatMap(function (room) {
38636
- return room.options.filter(function (option) {
38637
- return option.isSelected;
38655
+ var getPriceDifference = function (roomIndex, accommodationCode, regimeId) {
38656
+ var _a, _b, _c, _d, _e, _f, _g;
38657
+ var currentSelectedOption = getSelectedOptionForRoom(roomIndex);
38658
+ var currentSelectedPrice = (currentSelectedOption === null || currentSelectedOption === void 0 ? void 0 : currentSelectedOption.price) || 0;
38659
+ var targetOption;
38660
+ if (regimeId) {
38661
+ targetOption =
38662
+ (_c =
38663
+ (_b = (_a = selectedBookingPackageDetails.rooms) === null || _a === void 0 ? void 0 : _a[roomIndex]) === null || _b === void 0
38664
+ ? void 0
38665
+ : _b.options) === null || _c === void 0
38666
+ ? void 0
38667
+ : _c.find(function (option) {
38668
+ return option.entryLineGuid === regimeId;
38638
38669
  });
38639
- });
38640
- var totalPrice =
38641
- selectedOptions === null || selectedOptions === void 0
38642
- ? void 0
38643
- : selectedOptions.reduce(function (total, option) {
38644
- return total + (option.price || 0);
38645
- }, 0);
38646
- return formatPrice(totalPrice, bookingPackageDetails === null || bookingPackageDetails === void 0 ? void 0 : bookingPackageDetails.currencyCode);
38647
- };
38648
- var getPriceDifference = function (currentSelectedPrice, roomIndex, accommodationCode, regimeId) {
38649
- var targetPrice = 0;
38650
- var selectedOption = getSelectedOptionForAccommodation(roomIndex, accommodationCode);
38651
- if (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.price) {
38652
- targetPrice = selectedOption.price;
38653
38670
  } else {
38654
- var firstOption =
38655
- selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0
38671
+ targetOption =
38672
+ (_d = getSelectedOptionForAccommodation(roomIndex, accommodationCode)) !== null && _d !== void 0
38673
+ ? _d
38674
+ : (_g =
38675
+ (_f = (_e = selectedBookingPackageDetails.rooms) === null || _e === void 0 ? void 0 : _e[roomIndex]) === null || _f === void 0
38676
+ ? void 0
38677
+ : _f.options) === null || _g === void 0
38656
38678
  ? void 0
38657
- : selectedBookingPackageDetails.rooms[roomIndex].options.find(function (option) {
38679
+ : _g.find(function (option) {
38658
38680
  return option.accommodationCode === accommodationCode;
38659
38681
  });
38660
- targetPrice = (firstOption === null || firstOption === void 0 ? void 0 : firstOption.price) || 0;
38661
- }
38662
- if (regimeId) {
38663
- var regimeOption =
38664
- selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0
38665
- ? void 0
38666
- : selectedBookingPackageDetails.rooms[roomIndex].options.find(function (option) {
38667
- return option.entryLineGuid === regimeId;
38668
- });
38669
- targetPrice = (regimeOption === null || regimeOption === void 0 ? void 0 : regimeOption.price) || 0;
38670
38682
  }
38671
- return targetPrice - (currentSelectedPrice || 0);
38683
+ return ((targetOption === null || targetOption === void 0 ? void 0 : targetOption.price) || 0) - currentSelectedPrice;
38672
38684
  };
38673
38685
  var formatPriceDifference = function (difference, currencyCode) {
38674
38686
  if (difference === 0) {
@@ -38687,15 +38699,28 @@ var GroupTourFlyIn = function (_a) {
38687
38699
  return 'flyin__acco__price';
38688
38700
  };
38689
38701
  var regimeFormatter = function (roomIndex, accommodation, regimeId, label) {
38690
- var roomOption = getSelectedOptionForRoom(roomIndex);
38691
- var difference = getPriceDifference(
38692
- roomOption === null || roomOption === void 0 ? void 0 : roomOption.price,
38693
- roomIndex,
38694
- accommodation.accommodationCode,
38695
- regimeId
38696
- );
38702
+ var difference = getPriceDifference(roomIndex, accommodation.accommodationCode, regimeId);
38697
38703
  return ''.concat(label, ' ').concat(difference !== 0 ? '('.concat(formatPriceDifference(difference, bookingPackageDetails.currencyCode), ')') : '');
38698
38704
  };
38705
+ var adjustedTotalPrice = React.useMemo(
38706
+ function () {
38707
+ if (!selectedBookingPackageDetails.rooms || typeof selectedBookingPackageDetails.price !== 'number') {
38708
+ return 0;
38709
+ }
38710
+ var basePrice = selectedBookingPackageDetails.price;
38711
+ var totalDelta = selectedBookingPackageDetails.rooms.reduce(function (sum, room, roomIndex) {
38712
+ var initialOption = getInitialSelectedOptionForRoom(roomIndex);
38713
+ var currentOption = room.options.find(function (option) {
38714
+ return option.isSelected;
38715
+ });
38716
+ var initialPrice = (initialOption === null || initialOption === void 0 ? void 0 : initialOption.price) || 0;
38717
+ var currentPrice = (currentOption === null || currentOption === void 0 ? void 0 : currentOption.price) || 0;
38718
+ return sum + (currentPrice - initialPrice);
38719
+ }, 0);
38720
+ return basePrice + totalDelta;
38721
+ },
38722
+ [selectedBookingPackageDetails, packageKey]
38723
+ );
38699
38724
  return React__default['default'].createElement(
38700
38725
  React__default['default'].Fragment,
38701
38726
  null,
@@ -38712,12 +38737,9 @@ var GroupTourFlyIn = function (_a) {
38712
38737
  'div',
38713
38738
  { className: 'flyin__acco__cards' },
38714
38739
  roomAccommodations.map(function (accommodation) {
38740
+ var _a;
38715
38741
  var selectedOption = getSelectedOptionForAccommodation(roomIndex, accommodation.accommodationCode);
38716
- var priceDifference = getPriceDifference(
38717
- selectedRoomOption === null || selectedRoomOption === void 0 ? void 0 : selectedRoomOption.price,
38718
- roomIndex,
38719
- accommodation.accommodationCode
38720
- );
38742
+ var priceDifference = getPriceDifference(roomIndex, accommodation.accommodationCode);
38721
38743
  return React__default['default'].createElement(
38722
38744
  'div',
38723
38745
  { className: 'flyin__acco__card', key: ''.concat(roomIndex, '-').concat(accommodation.accommodationCode) },
@@ -38731,7 +38753,7 @@ var GroupTourFlyIn = function (_a) {
38731
38753
  { className: 'flyin__acco__footer' },
38732
38754
  React__default['default'].createElement(ItemPicker$1, {
38733
38755
  items: accommodation.regimes,
38734
- selection: selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.regimeName,
38756
+ selection: selectedOption != null ? ((_a = selectedOption.regimeName) !== null && _a !== void 0 ? _a : 'No regime') : undefined,
38735
38757
  label: '',
38736
38758
  placeholder: 'Select regime',
38737
38759
  classModifier: '',
@@ -38749,7 +38771,7 @@ var GroupTourFlyIn = function (_a) {
38749
38771
  'button',
38750
38772
  {
38751
38773
  className:
38752
- (selectedRoomOption === null || selectedRoomOption === void 0 ? void 0 : selectedRoomOption.accommodationCode) ==
38774
+ (selectedRoomOption === null || selectedRoomOption === void 0 ? void 0 : selectedRoomOption.accommodationCode) ===
38753
38775
  accommodation.accommodationCode
38754
38776
  ? 'cta cta--select cta--selected'
38755
38777
  : 'cta cta--select',
@@ -38765,7 +38787,7 @@ var GroupTourFlyIn = function (_a) {
38765
38787
  );
38766
38788
  }
38767
38789
  },
38768
- (selectedRoomOption === null || selectedRoomOption === void 0 ? void 0 : selectedRoomOption.accommodationCode) ==
38790
+ (selectedRoomOption === null || selectedRoomOption === void 0 ? void 0 : selectedRoomOption.accommodationCode) ===
38769
38791
  accommodation.accommodationCode
38770
38792
  ? translations === null || translations === void 0
38771
38793
  ? void 0
@@ -38780,10 +38802,7 @@ var GroupTourFlyIn = function (_a) {
38780
38802
  React__default['default'].createElement(
38781
38803
  'span',
38782
38804
  { className: getPriceDifferenceClassName(priceDifference) },
38783
- formatPriceDifference(
38784
- priceDifference,
38785
- bookingPackageDetails === null || bookingPackageDetails === void 0 ? void 0 : bookingPackageDetails.currencyCode
38786
- )
38805
+ formatPriceDifference(priceDifference, bookingPackageDetails.currencyCode)
38787
38806
  )
38788
38807
  )
38789
38808
  )
@@ -38797,7 +38816,12 @@ var GroupTourFlyIn = function (_a) {
38797
38816
  React__default['default'].createElement(
38798
38817
  'div',
38799
38818
  { className: 'flyin__footer' },
38800
- React__default['default'].createElement('div', { className: 'flyin__footer__price' }, 'Total price: ', calculateTotalPrice()),
38819
+ React__default['default'].createElement(
38820
+ 'div',
38821
+ { className: 'flyin__footer__price' },
38822
+ 'Total price: ',
38823
+ formatPrice(adjustedTotalPrice, bookingPackageDetails.currencyCode)
38824
+ ),
38801
38825
  React__default['default'].createElement(
38802
38826
  'div',
38803
38827
  { className: 'flyin__button-wrapper' },
@@ -38814,7 +38838,8 @@ var FlyIn = function (_a) {
38814
38838
  setIsOpen = _a.setIsOpen,
38815
38839
  _b = _a.className,
38816
38840
  className = _b === void 0 ? '' : _b,
38817
- onPanelRef = _a.onPanelRef;
38841
+ onPanelRef = _a.onPanelRef,
38842
+ detailsLoading = _a.detailsLoading;
38818
38843
  var dispatch = reactRedux.useDispatch();
38819
38844
  var onCancelSearch = useFlightSearch().onCancelSearch;
38820
38845
  var panelRef = React.useRef(null);
@@ -38892,7 +38917,7 @@ var FlyIn = function (_a) {
38892
38917
  srpType === build.PortalQsmType.Accommodation &&
38893
38918
  React__default['default'].createElement(AccommodationFlyIn, { isLoading: true, isOpen: isOpen, setIsOpen: setIsOpen }),
38894
38919
  srpType === build.PortalQsmType.GroupTour &&
38895
- React__default['default'].createElement(GroupTourFlyIn, { isLoading: true, isOpen: isOpen, setIsOpen: setIsOpen })
38920
+ React__default['default'].createElement(GroupTourFlyIn, { isLoading: detailsLoading, isOpen: isOpen, setIsOpen: setIsOpen })
38896
38921
  )
38897
38922
  );
38898
38923
  };
@@ -46821,8 +46846,11 @@ var SearchResultsContainer = function () {
46821
46846
  filtersOpen = _e[0],
46822
46847
  setFiltersOpen = _e[1];
46823
46848
  var _f = React.useState(false),
46824
- itineraryOpen = _f[0],
46825
- setItineraryOpen = _f[1];
46849
+ detailsIsLoading = _f[0],
46850
+ setDetailsIsLoading = _f[1];
46851
+ var _g = React.useState(false),
46852
+ itineraryOpen = _g[0],
46853
+ setItineraryOpen = _g[1];
46826
46854
  var panelRef = React.useRef(null);
46827
46855
  var sortByTypes = [
46828
46856
  { direction: 'asc', label: 'default' },
@@ -47337,6 +47365,7 @@ var SearchResultsContainer = function () {
47337
47365
  return __generator(this, function (_a) {
47338
47366
  switch (_a.label) {
47339
47367
  case 0:
47368
+ setDetailsIsLoading(true);
47340
47369
  console.log('Fetching details for selected search result', selectedSearchResult);
47341
47370
  if (!selectedSearchResult || !context) return [2 /*return*/];
47342
47371
  if (
@@ -47400,12 +47429,14 @@ var SearchResultsContainer = function () {
47400
47429
  case 4:
47401
47430
  detailsResponse = _a.sent();
47402
47431
  dispatch(setBookingPackageDetails({ details: detailsResponse === null || detailsResponse === void 0 ? void 0 : detailsResponse.payload }));
47432
+ setDetailsIsLoading(false);
47403
47433
  _a.label = 5;
47404
47434
  case 5:
47405
47435
  return [3 /*break*/, 7];
47406
47436
  case 6:
47407
47437
  err_3 = _a.sent();
47408
47438
  console.error('Failed to fetch package details', err_3);
47439
+ setDetailsIsLoading(false);
47409
47440
  return [3 /*break*/, 7];
47410
47441
  case 7:
47411
47442
  return [2 /*return*/];
@@ -47570,7 +47601,8 @@ var SearchResultsContainer = function () {
47570
47601
  setIsOpen: handleFlyInToggle,
47571
47602
  onPanelRef: function (el) {
47572
47603
  return (panelRef.current = el);
47573
- }
47604
+ },
47605
+ detailsLoading: detailsIsLoading
47574
47606
  })
47575
47607
  ),
47576
47608
  (context.searchConfiguration.qsmType === build.PortalQsmType.AccommodationAndFlight ||
@@ -47734,7 +47766,8 @@ var SearchResultsContainer = function () {
47734
47766
  setIsOpen: handleFlyInToggle,
47735
47767
  onPanelRef: function (el) {
47736
47768
  return (panelRef.current = el);
47737
- }
47769
+ },
47770
+ detailsLoading: detailsIsLoading
47738
47771
  })
47739
47772
  )
47740
47773
  )
@@ -7,6 +7,7 @@ type FlyInProps = {
7
7
  setIsOpen: (open: boolean) => void;
8
8
  className?: string;
9
9
  onPanelRef?: (el: HTMLDivElement | null) => void;
10
+ detailsLoading: boolean;
10
11
  };
11
12
  declare const FlyIn: React.FC<FlyInProps>;
12
13
  export default FlyIn;
@@ -38337,13 +38337,22 @@ var formatPrice = function (price, currencyCode) {
38337
38337
  }).format(price);
38338
38338
  };
38339
38339
  var GroupTourFlyIn = function (_a) {
38340
- var _b;
38341
- _a.isLoading;
38342
- var isOpen = _a.isOpen,
38340
+ var _b, _c;
38341
+ var isLoading = _a.isLoading,
38342
+ isOpen = _a.isOpen,
38343
38343
  setIsOpen = _a.setIsOpen;
38344
38344
  var dispatch = useDispatch();
38345
38345
  var context = useContext(SearchResultsConfigurationContext);
38346
- var language = (_b = context === null || context === void 0 ? void 0 : context.languageCode) !== null && _b !== void 0 ? _b : 'en-GB';
38346
+ if (isLoading) {
38347
+ return React__default.createElement(
38348
+ React__default.Fragment,
38349
+ null,
38350
+ (_b = context === null || context === void 0 ? void 0 : context.customSpinner) !== null && _b !== void 0
38351
+ ? _b
38352
+ : React__default.createElement(Spinner, null)
38353
+ );
38354
+ }
38355
+ var language = (_c = context === null || context === void 0 ? void 0 : context.languageCode) !== null && _c !== void 0 ? _c : 'en-GB';
38347
38356
  var translations = getTranslations(language);
38348
38357
  var bookingPackageDetails = useSelector(function (state) {
38349
38358
  return state.searchResults;
@@ -38359,13 +38368,34 @@ var GroupTourFlyIn = function (_a) {
38359
38368
  },
38360
38369
  [bookingPackageDetails]
38361
38370
  );
38371
+ var packageKey = ''
38372
+ .concat(bookingPackageDetails === null || bookingPackageDetails === void 0 ? void 0 : bookingPackageDetails.transactionId, '-')
38373
+ .concat(selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0 ? void 0 : selectedBookingPackageDetails.id);
38374
+ var initialSelectedOptionsRef = useRef({});
38375
+ useEffect(
38376
+ function () {
38377
+ if (!packageKey || !(selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0 ? void 0 : selectedBookingPackageDetails.rooms))
38378
+ return;
38379
+ if (!initialSelectedOptionsRef.current[packageKey]) {
38380
+ initialSelectedOptionsRef.current[packageKey] = {};
38381
+ }
38382
+ selectedBookingPackageDetails.rooms.forEach(function (room, roomIndex) {
38383
+ if (!initialSelectedOptionsRef.current[packageKey][roomIndex]) {
38384
+ initialSelectedOptionsRef.current[packageKey][roomIndex] = room.options.find(function (option) {
38385
+ return option.isSelected;
38386
+ });
38387
+ }
38388
+ });
38389
+ },
38390
+ [packageKey, selectedBookingPackageDetails]
38391
+ );
38362
38392
  var groupedRooms = useMemo(
38363
38393
  function () {
38364
38394
  if (!(selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0 ? void 0 : selectedBookingPackageDetails.rooms)) return [];
38365
38395
  return selectedBookingPackageDetails.rooms.map(function (room) {
38366
38396
  var groupedMap = new Map();
38367
38397
  room.options.forEach(function (option) {
38368
- var _a;
38398
+ var _a, _b;
38369
38399
  var key = option.accommodationCode;
38370
38400
  if (!groupedMap.has(key)) {
38371
38401
  groupedMap.set(key, {
@@ -38378,7 +38408,7 @@ var GroupTourFlyIn = function (_a) {
38378
38408
  ? void 0
38379
38409
  : _a.regimes.push({
38380
38410
  id: option.entryLineGuid,
38381
- label: option.regimeName
38411
+ label: (_b = option.regimeName) !== null && _b !== void 0 ? _b : 'No regime'
38382
38412
  });
38383
38413
  });
38384
38414
  return Array.from(groupedMap.values());
@@ -38386,19 +38416,14 @@ var GroupTourFlyIn = function (_a) {
38386
38416
  },
38387
38417
  [selectedBookingPackageDetails]
38388
38418
  );
38389
- if (!bookingPackageDetails) {
38419
+ if (!bookingPackageDetails || !selectedBookingPackageDetails) {
38390
38420
  return null;
38391
38421
  }
38392
38422
  var getSelectedOptionForRoom = function (roomIndex) {
38393
38423
  var _a, _b, _c;
38394
38424
  return (_c =
38395
- (_b =
38396
- (_a = selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0 ? void 0 : selectedBookingPackageDetails.rooms) === null ||
38397
- _a === void 0
38398
- ? void 0
38399
- : _a[roomIndex]) === null || _b === void 0
38400
- ? void 0
38401
- : _b.options) === null || _c === void 0
38425
+ (_b = (_a = selectedBookingPackageDetails.rooms) === null || _a === void 0 ? void 0 : _a[roomIndex]) === null || _b === void 0 ? void 0 : _b.options) ===
38426
+ null || _c === void 0
38402
38427
  ? void 0
38403
38428
  : _c.find(function (option) {
38404
38429
  return option.isSelected;
@@ -38407,18 +38432,18 @@ var GroupTourFlyIn = function (_a) {
38407
38432
  var getSelectedOptionForAccommodation = function (roomIndex, accommodationCode) {
38408
38433
  var _a, _b, _c;
38409
38434
  return (_c =
38410
- (_b =
38411
- (_a = selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0 ? void 0 : selectedBookingPackageDetails.rooms) === null ||
38412
- _a === void 0
38413
- ? void 0
38414
- : _a[roomIndex]) === null || _b === void 0
38415
- ? void 0
38416
- : _b.options) === null || _c === void 0
38435
+ (_b = (_a = selectedBookingPackageDetails.rooms) === null || _a === void 0 ? void 0 : _a[roomIndex]) === null || _b === void 0 ? void 0 : _b.options) ===
38436
+ null || _c === void 0
38417
38437
  ? void 0
38418
38438
  : _c.find(function (option) {
38419
38439
  return option.accommodationCode === accommodationCode && option.isSelected;
38420
38440
  });
38421
38441
  };
38442
+ var getInitialSelectedOptionForRoom = function (roomIndex) {
38443
+ var _a;
38444
+ if (!packageKey) return undefined;
38445
+ return (_a = initialSelectedOptionsRef.current[packageKey]) === null || _a === void 0 ? void 0 : _a[roomIndex];
38446
+ };
38422
38447
  var handlePick = function (roomIndex, selectedGuid) {
38423
38448
  if (!bookingPackageDetails || !selectedBookingPackageDetails) return;
38424
38449
  var updatedBookingPackageDetails = __assign(__assign({}, bookingPackageDetails), {
@@ -38446,52 +38471,39 @@ var GroupTourFlyIn = function (_a) {
38446
38471
  if (isOpen) {
38447
38472
  setIsOpen(false);
38448
38473
  }
38449
- console.log('Booking package details sent to onBook callback:', bookingPackageDetails);
38450
38474
  if (context === null || context === void 0 ? void 0 : context.onBook) {
38451
38475
  context.onBook(bookingPackageDetails);
38452
38476
  }
38453
38477
  };
38454
- var calculateTotalPrice = function () {
38455
- var selectedOptions =
38456
- selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0
38457
- ? void 0
38458
- : selectedBookingPackageDetails.rooms.flatMap(function (room) {
38459
- return room.options.filter(function (option) {
38460
- return option.isSelected;
38478
+ var getPriceDifference = function (roomIndex, accommodationCode, regimeId) {
38479
+ var _a, _b, _c, _d, _e, _f, _g;
38480
+ var currentSelectedOption = getSelectedOptionForRoom(roomIndex);
38481
+ var currentSelectedPrice = (currentSelectedOption === null || currentSelectedOption === void 0 ? void 0 : currentSelectedOption.price) || 0;
38482
+ var targetOption;
38483
+ if (regimeId) {
38484
+ targetOption =
38485
+ (_c =
38486
+ (_b = (_a = selectedBookingPackageDetails.rooms) === null || _a === void 0 ? void 0 : _a[roomIndex]) === null || _b === void 0
38487
+ ? void 0
38488
+ : _b.options) === null || _c === void 0
38489
+ ? void 0
38490
+ : _c.find(function (option) {
38491
+ return option.entryLineGuid === regimeId;
38461
38492
  });
38462
- });
38463
- var totalPrice =
38464
- selectedOptions === null || selectedOptions === void 0
38465
- ? void 0
38466
- : selectedOptions.reduce(function (total, option) {
38467
- return total + (option.price || 0);
38468
- }, 0);
38469
- return formatPrice(totalPrice, bookingPackageDetails === null || bookingPackageDetails === void 0 ? void 0 : bookingPackageDetails.currencyCode);
38470
- };
38471
- var getPriceDifference = function (currentSelectedPrice, roomIndex, accommodationCode, regimeId) {
38472
- var targetPrice = 0;
38473
- var selectedOption = getSelectedOptionForAccommodation(roomIndex, accommodationCode);
38474
- if (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.price) {
38475
- targetPrice = selectedOption.price;
38476
38493
  } else {
38477
- var firstOption =
38478
- selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0
38494
+ targetOption =
38495
+ (_d = getSelectedOptionForAccommodation(roomIndex, accommodationCode)) !== null && _d !== void 0
38496
+ ? _d
38497
+ : (_g =
38498
+ (_f = (_e = selectedBookingPackageDetails.rooms) === null || _e === void 0 ? void 0 : _e[roomIndex]) === null || _f === void 0
38499
+ ? void 0
38500
+ : _f.options) === null || _g === void 0
38479
38501
  ? void 0
38480
- : selectedBookingPackageDetails.rooms[roomIndex].options.find(function (option) {
38502
+ : _g.find(function (option) {
38481
38503
  return option.accommodationCode === accommodationCode;
38482
38504
  });
38483
- targetPrice = (firstOption === null || firstOption === void 0 ? void 0 : firstOption.price) || 0;
38484
- }
38485
- if (regimeId) {
38486
- var regimeOption =
38487
- selectedBookingPackageDetails === null || selectedBookingPackageDetails === void 0
38488
- ? void 0
38489
- : selectedBookingPackageDetails.rooms[roomIndex].options.find(function (option) {
38490
- return option.entryLineGuid === regimeId;
38491
- });
38492
- targetPrice = (regimeOption === null || regimeOption === void 0 ? void 0 : regimeOption.price) || 0;
38493
38505
  }
38494
- return targetPrice - (currentSelectedPrice || 0);
38506
+ return ((targetOption === null || targetOption === void 0 ? void 0 : targetOption.price) || 0) - currentSelectedPrice;
38495
38507
  };
38496
38508
  var formatPriceDifference = function (difference, currencyCode) {
38497
38509
  if (difference === 0) {
@@ -38510,15 +38522,28 @@ var GroupTourFlyIn = function (_a) {
38510
38522
  return 'flyin__acco__price';
38511
38523
  };
38512
38524
  var regimeFormatter = function (roomIndex, accommodation, regimeId, label) {
38513
- var roomOption = getSelectedOptionForRoom(roomIndex);
38514
- var difference = getPriceDifference(
38515
- roomOption === null || roomOption === void 0 ? void 0 : roomOption.price,
38516
- roomIndex,
38517
- accommodation.accommodationCode,
38518
- regimeId
38519
- );
38525
+ var difference = getPriceDifference(roomIndex, accommodation.accommodationCode, regimeId);
38520
38526
  return ''.concat(label, ' ').concat(difference !== 0 ? '('.concat(formatPriceDifference(difference, bookingPackageDetails.currencyCode), ')') : '');
38521
38527
  };
38528
+ var adjustedTotalPrice = useMemo(
38529
+ function () {
38530
+ if (!selectedBookingPackageDetails.rooms || typeof selectedBookingPackageDetails.price !== 'number') {
38531
+ return 0;
38532
+ }
38533
+ var basePrice = selectedBookingPackageDetails.price;
38534
+ var totalDelta = selectedBookingPackageDetails.rooms.reduce(function (sum, room, roomIndex) {
38535
+ var initialOption = getInitialSelectedOptionForRoom(roomIndex);
38536
+ var currentOption = room.options.find(function (option) {
38537
+ return option.isSelected;
38538
+ });
38539
+ var initialPrice = (initialOption === null || initialOption === void 0 ? void 0 : initialOption.price) || 0;
38540
+ var currentPrice = (currentOption === null || currentOption === void 0 ? void 0 : currentOption.price) || 0;
38541
+ return sum + (currentPrice - initialPrice);
38542
+ }, 0);
38543
+ return basePrice + totalDelta;
38544
+ },
38545
+ [selectedBookingPackageDetails, packageKey]
38546
+ );
38522
38547
  return React__default.createElement(
38523
38548
  React__default.Fragment,
38524
38549
  null,
@@ -38535,12 +38560,9 @@ var GroupTourFlyIn = function (_a) {
38535
38560
  'div',
38536
38561
  { className: 'flyin__acco__cards' },
38537
38562
  roomAccommodations.map(function (accommodation) {
38563
+ var _a;
38538
38564
  var selectedOption = getSelectedOptionForAccommodation(roomIndex, accommodation.accommodationCode);
38539
- var priceDifference = getPriceDifference(
38540
- selectedRoomOption === null || selectedRoomOption === void 0 ? void 0 : selectedRoomOption.price,
38541
- roomIndex,
38542
- accommodation.accommodationCode
38543
- );
38565
+ var priceDifference = getPriceDifference(roomIndex, accommodation.accommodationCode);
38544
38566
  return React__default.createElement(
38545
38567
  'div',
38546
38568
  { className: 'flyin__acco__card', key: ''.concat(roomIndex, '-').concat(accommodation.accommodationCode) },
@@ -38554,7 +38576,7 @@ var GroupTourFlyIn = function (_a) {
38554
38576
  { className: 'flyin__acco__footer' },
38555
38577
  React__default.createElement(ItemPicker$1, {
38556
38578
  items: accommodation.regimes,
38557
- selection: selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.regimeName,
38579
+ selection: selectedOption != null ? ((_a = selectedOption.regimeName) !== null && _a !== void 0 ? _a : 'No regime') : undefined,
38558
38580
  label: '',
38559
38581
  placeholder: 'Select regime',
38560
38582
  classModifier: '',
@@ -38572,7 +38594,7 @@ var GroupTourFlyIn = function (_a) {
38572
38594
  'button',
38573
38595
  {
38574
38596
  className:
38575
- (selectedRoomOption === null || selectedRoomOption === void 0 ? void 0 : selectedRoomOption.accommodationCode) ==
38597
+ (selectedRoomOption === null || selectedRoomOption === void 0 ? void 0 : selectedRoomOption.accommodationCode) ===
38576
38598
  accommodation.accommodationCode
38577
38599
  ? 'cta cta--select cta--selected'
38578
38600
  : 'cta cta--select',
@@ -38584,7 +38606,7 @@ var GroupTourFlyIn = function (_a) {
38584
38606
  );
38585
38607
  }
38586
38608
  },
38587
- (selectedRoomOption === null || selectedRoomOption === void 0 ? void 0 : selectedRoomOption.accommodationCode) ==
38609
+ (selectedRoomOption === null || selectedRoomOption === void 0 ? void 0 : selectedRoomOption.accommodationCode) ===
38588
38610
  accommodation.accommodationCode
38589
38611
  ? translations === null || translations === void 0
38590
38612
  ? void 0
@@ -38599,10 +38621,7 @@ var GroupTourFlyIn = function (_a) {
38599
38621
  React__default.createElement(
38600
38622
  'span',
38601
38623
  { className: getPriceDifferenceClassName(priceDifference) },
38602
- formatPriceDifference(
38603
- priceDifference,
38604
- bookingPackageDetails === null || bookingPackageDetails === void 0 ? void 0 : bookingPackageDetails.currencyCode
38605
- )
38624
+ formatPriceDifference(priceDifference, bookingPackageDetails.currencyCode)
38606
38625
  )
38607
38626
  )
38608
38627
  )
@@ -38616,7 +38635,12 @@ var GroupTourFlyIn = function (_a) {
38616
38635
  React__default.createElement(
38617
38636
  'div',
38618
38637
  { className: 'flyin__footer' },
38619
- React__default.createElement('div', { className: 'flyin__footer__price' }, 'Total price: ', calculateTotalPrice()),
38638
+ React__default.createElement(
38639
+ 'div',
38640
+ { className: 'flyin__footer__price' },
38641
+ 'Total price: ',
38642
+ formatPrice(adjustedTotalPrice, bookingPackageDetails.currencyCode)
38643
+ ),
38620
38644
  React__default.createElement(
38621
38645
  'div',
38622
38646
  { className: 'flyin__button-wrapper' },
@@ -38633,7 +38657,8 @@ var FlyIn = function (_a) {
38633
38657
  setIsOpen = _a.setIsOpen,
38634
38658
  _b = _a.className,
38635
38659
  className = _b === void 0 ? '' : _b,
38636
- onPanelRef = _a.onPanelRef;
38660
+ onPanelRef = _a.onPanelRef,
38661
+ detailsLoading = _a.detailsLoading;
38637
38662
  var dispatch = useDispatch();
38638
38663
  var onCancelSearch = useFlightSearch().onCancelSearch;
38639
38664
  var panelRef = useRef(null);
@@ -38710,7 +38735,8 @@ var FlyIn = function (_a) {
38710
38735
  srpType === build.PortalQsmType.Flight && React__default.createElement(FlightsFlyIn, { isOpen: isOpen, setIsOpen: setIsOpen }),
38711
38736
  srpType === build.PortalQsmType.Accommodation &&
38712
38737
  React__default.createElement(AccommodationFlyIn, { isLoading: true, isOpen: isOpen, setIsOpen: setIsOpen }),
38713
- srpType === build.PortalQsmType.GroupTour && React__default.createElement(GroupTourFlyIn, { isLoading: true, isOpen: isOpen, setIsOpen: setIsOpen })
38738
+ srpType === build.PortalQsmType.GroupTour &&
38739
+ React__default.createElement(GroupTourFlyIn, { isLoading: detailsLoading, isOpen: isOpen, setIsOpen: setIsOpen })
38714
38740
  )
38715
38741
  );
38716
38742
  };
@@ -46568,8 +46594,11 @@ var SearchResultsContainer = function () {
46568
46594
  filtersOpen = _e[0],
46569
46595
  setFiltersOpen = _e[1];
46570
46596
  var _f = useState(false),
46571
- itineraryOpen = _f[0],
46572
- setItineraryOpen = _f[1];
46597
+ detailsIsLoading = _f[0],
46598
+ setDetailsIsLoading = _f[1];
46599
+ var _g = useState(false),
46600
+ itineraryOpen = _g[0],
46601
+ setItineraryOpen = _g[1];
46573
46602
  var panelRef = useRef(null);
46574
46603
  var sortByTypes = [
46575
46604
  { direction: 'asc', label: 'default' },
@@ -47084,6 +47113,7 @@ var SearchResultsContainer = function () {
47084
47113
  return __generator(this, function (_a) {
47085
47114
  switch (_a.label) {
47086
47115
  case 0:
47116
+ setDetailsIsLoading(true);
47087
47117
  console.log('Fetching details for selected search result', selectedSearchResult);
47088
47118
  if (!selectedSearchResult || !context) return [2 /*return*/];
47089
47119
  if (
@@ -47147,12 +47177,14 @@ var SearchResultsContainer = function () {
47147
47177
  case 4:
47148
47178
  detailsResponse = _a.sent();
47149
47179
  dispatch(setBookingPackageDetails({ details: detailsResponse === null || detailsResponse === void 0 ? void 0 : detailsResponse.payload }));
47180
+ setDetailsIsLoading(false);
47150
47181
  _a.label = 5;
47151
47182
  case 5:
47152
47183
  return [3 /*break*/, 7];
47153
47184
  case 6:
47154
47185
  err_3 = _a.sent();
47155
47186
  console.error('Failed to fetch package details', err_3);
47187
+ setDetailsIsLoading(false);
47156
47188
  return [3 /*break*/, 7];
47157
47189
  case 7:
47158
47190
  return [2 /*return*/];
@@ -47317,7 +47349,8 @@ var SearchResultsContainer = function () {
47317
47349
  setIsOpen: handleFlyInToggle,
47318
47350
  onPanelRef: function (el) {
47319
47351
  return (panelRef.current = el);
47320
- }
47352
+ },
47353
+ detailsLoading: detailsIsLoading
47321
47354
  })
47322
47355
  ),
47323
47356
  (context.searchConfiguration.qsmType === build.PortalQsmType.AccommodationAndFlight ||
@@ -47481,7 +47514,8 @@ var SearchResultsContainer = function () {
47481
47514
  setIsOpen: handleFlyInToggle,
47482
47515
  onPanelRef: function (el) {
47483
47516
  return (panelRef.current = el);
47484
- }
47517
+ },
47518
+ detailsLoading: detailsIsLoading
47485
47519
  })
47486
47520
  )
47487
47521
  )
@@ -7,6 +7,7 @@ type FlyInProps = {
7
7
  setIsOpen: (open: boolean) => void;
8
8
  className?: string;
9
9
  onPanelRef?: (el: HTMLDivElement | null) => void;
10
+ detailsLoading: boolean;
10
11
  };
11
12
  declare const FlyIn: React.FC<FlyInProps>;
12
13
  export default FlyIn;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qite/tide-booking-component",
3
- "version": "1.4.88",
3
+ "version": "1.4.90",
4
4
  "description": "React Booking wizard & Booking product component for Tide",
5
5
  "main": "build/build-cjs/index.js",
6
6
  "types": "build/build-cjs/src/index.d.ts",
@@ -89,6 +89,8 @@ const SearchResultsContainer: React.FC = () => {
89
89
  const [initialFilters, setInitialFilters] = useState<Filter[]>([]);
90
90
  const [filtersOpen, setFiltersOpen] = useState(false);
91
91
 
92
+ const [detailsIsLoading, setDetailsIsLoading] = useState(false);
93
+
92
94
  const [itineraryOpen, setItineraryOpen] = useState(false);
93
95
 
94
96
  const panelRef = useRef<HTMLDivElement | null>(null);
@@ -577,6 +579,7 @@ const SearchResultsContainer: React.FC = () => {
577
579
  // Seperate detailsCall
578
580
  useEffect(() => {
579
581
  const fetchDetails = async () => {
582
+ setDetailsIsLoading(true);
580
583
  console.log('Fetching details for selected search result', selectedSearchResult);
581
584
  if (!selectedSearchResult || !context) return;
582
585
  if (context?.searchConfiguration.qsmType === PortalQsmType.Accommodation || context?.searchConfiguration.qsmType === PortalQsmType.GroupTour) {
@@ -639,9 +642,11 @@ const SearchResultsContainer: React.FC = () => {
639
642
 
640
643
  const detailsResponse = await details(config, detailsRequest);
641
644
  dispatch(setBookingPackageDetails({ details: detailsResponse?.payload }));
645
+ setDetailsIsLoading(false);
642
646
  }
643
647
  } catch (err) {
644
648
  console.error('Failed to fetch package details', err);
649
+ setDetailsIsLoading(false);
645
650
  }
646
651
  };
647
652
 
@@ -763,6 +768,7 @@ const SearchResultsContainer: React.FC = () => {
763
768
  isOpen={flyInIsOpen}
764
769
  setIsOpen={handleFlyInToggle}
765
770
  onPanelRef={(el) => (panelRef.current = el)}
771
+ detailsLoading={detailsIsLoading}
766
772
  />
767
773
  </FlightSearchProvider>
768
774
  )}
@@ -871,6 +877,7 @@ const SearchResultsContainer: React.FC = () => {
871
877
  isOpen={flyInIsOpen}
872
878
  setIsOpen={handleFlyInToggle}
873
879
  onPanelRef={(el) => (panelRef.current = el)}
880
+ detailsLoading={detailsIsLoading}
874
881
  />
875
882
  </>
876
883
  )}
@@ -15,9 +15,10 @@ type FlyInProps = {
15
15
  setIsOpen: (open: boolean) => void;
16
16
  className?: string;
17
17
  onPanelRef?: (el: HTMLDivElement | null) => void;
18
+ detailsLoading: boolean;
18
19
  };
19
20
 
20
- const FlyIn: React.FC<FlyInProps> = ({ title, srpType, isOpen, setIsOpen, className = '', onPanelRef }) => {
21
+ const FlyIn: React.FC<FlyInProps> = ({ title, srpType, isOpen, setIsOpen, className = '', onPanelRef, detailsLoading }) => {
21
22
  const dispatch = useDispatch();
22
23
  const { onCancelSearch } = useFlightSearch();
23
24
  const panelRef = useRef<HTMLDivElement>(null);
@@ -72,7 +73,7 @@ const FlyIn: React.FC<FlyInProps> = ({ title, srpType, isOpen, setIsOpen, classN
72
73
  </div>
73
74
  {srpType === PortalQsmType.Flight && <FlightsFlyIn isOpen={isOpen} setIsOpen={setIsOpen} />}
74
75
  {srpType === PortalQsmType.Accommodation && <AccommodationFlyIn isLoading={true} isOpen={isOpen} setIsOpen={setIsOpen} />}
75
- {srpType === PortalQsmType.GroupTour && <GroupTourFlyIn isLoading={true} isOpen={isOpen} setIsOpen={setIsOpen} />}
76
+ {srpType === PortalQsmType.GroupTour && <GroupTourFlyIn isLoading={detailsLoading} isOpen={isOpen} setIsOpen={setIsOpen} />}
76
77
  </div>
77
78
  </div>
78
79
  );
@@ -1,4 +1,4 @@
1
- import React, { useContext, useMemo } from 'react';
1
+ import React, { useContext, useMemo, useRef, useEffect } from 'react';
2
2
  import { useDispatch, useSelector } from 'react-redux';
3
3
  import ItemPicker from '../../../qsm/components/item-picker';
4
4
  import { SearchResultsRootState } from '../../../search-results/store/search-results-store';
@@ -8,6 +8,7 @@ import { setBookingPackageDetails } from '../../../search-results/store/search-r
8
8
  import { BookingPackageOption } from '@qite/tide-client';
9
9
  import { PickerItem } from '../../types';
10
10
  import { first } from 'lodash';
11
+ import Spinner from '../../../search-results/components/spinner/spinner';
11
12
 
12
13
  type GroupTourFlyInProps = {
13
14
  isLoading: boolean;
@@ -21,6 +22,8 @@ type GroupedAccommodation = {
21
22
  regimes: PickerItem[];
22
23
  };
23
24
 
25
+ type RoomOption = BookingPackageOption['rooms'][number]['options'][number];
26
+
24
27
  const formatPrice = (price?: number, currencyCode = 'EUR') => {
25
28
  if (typeof price !== 'number') return '';
26
29
 
@@ -33,6 +36,11 @@ const formatPrice = (price?: number, currencyCode = 'EUR') => {
33
36
  const GroupTourFlyIn: React.FC<GroupTourFlyInProps> = ({ isLoading, isOpen, setIsOpen }) => {
34
37
  const dispatch = useDispatch();
35
38
  const context = useContext(SearchResultsConfigurationContext);
39
+
40
+ if (isLoading) {
41
+ return <>{context?.customSpinner ?? <Spinner />}</>;
42
+ }
43
+
36
44
  const language = context?.languageCode ?? 'en-GB';
37
45
  const translations = getTranslations(language);
38
46
 
@@ -42,6 +50,24 @@ const GroupTourFlyIn: React.FC<GroupTourFlyInProps> = ({ isLoading, isOpen, setI
42
50
  return bookingPackageDetails?.options?.find((x) => x.isSelected);
43
51
  }, [bookingPackageDetails]);
44
52
 
53
+ const packageKey = `${bookingPackageDetails?.transactionId}-${selectedBookingPackageDetails?.id}`;
54
+
55
+ const initialSelectedOptionsRef = useRef<Record<string, Record<number, RoomOption | undefined>>>({});
56
+
57
+ useEffect(() => {
58
+ if (!packageKey || !selectedBookingPackageDetails?.rooms) return;
59
+
60
+ if (!initialSelectedOptionsRef.current[packageKey]) {
61
+ initialSelectedOptionsRef.current[packageKey] = {};
62
+ }
63
+
64
+ selectedBookingPackageDetails.rooms.forEach((room, roomIndex) => {
65
+ if (!initialSelectedOptionsRef.current[packageKey][roomIndex]) {
66
+ initialSelectedOptionsRef.current[packageKey][roomIndex] = room.options.find((option) => option.isSelected);
67
+ }
68
+ });
69
+ }, [packageKey, selectedBookingPackageDetails]);
70
+
45
71
  const groupedRooms = useMemo(() => {
46
72
  if (!selectedBookingPackageDetails?.rooms) return [];
47
73
 
@@ -61,7 +87,7 @@ const GroupTourFlyIn: React.FC<GroupTourFlyInProps> = ({ isLoading, isOpen, setI
61
87
 
62
88
  groupedMap.get(key)?.regimes.push({
63
89
  id: option.entryLineGuid,
64
- label: option.regimeName
90
+ label: option.regimeName ?? 'No regime'
65
91
  });
66
92
  });
67
93
 
@@ -69,16 +95,21 @@ const GroupTourFlyIn: React.FC<GroupTourFlyInProps> = ({ isLoading, isOpen, setI
69
95
  });
70
96
  }, [selectedBookingPackageDetails]);
71
97
 
72
- if (!bookingPackageDetails) {
98
+ if (!bookingPackageDetails || !selectedBookingPackageDetails) {
73
99
  return null;
74
100
  }
75
101
 
76
102
  const getSelectedOptionForRoom = (roomIndex: number) => {
77
- return selectedBookingPackageDetails?.rooms?.[roomIndex]?.options?.find((option) => option.isSelected);
103
+ return selectedBookingPackageDetails.rooms?.[roomIndex]?.options?.find((option) => option.isSelected);
78
104
  };
79
105
 
80
106
  const getSelectedOptionForAccommodation = (roomIndex: number, accommodationCode: string) => {
81
- return selectedBookingPackageDetails?.rooms?.[roomIndex]?.options?.find((option) => option.accommodationCode === accommodationCode && option.isSelected);
107
+ return selectedBookingPackageDetails.rooms?.[roomIndex]?.options?.find((option) => option.accommodationCode === accommodationCode && option.isSelected);
108
+ };
109
+
110
+ const getInitialSelectedOptionForRoom = (roomIndex: number) => {
111
+ if (!packageKey) return undefined;
112
+ return initialSelectedOptionsRef.current[packageKey]?.[roomIndex];
82
113
  };
83
114
 
84
115
  const handlePick = (roomIndex: number, selectedGuid?: string) => {
@@ -117,36 +148,27 @@ const GroupTourFlyIn: React.FC<GroupTourFlyInProps> = ({ isLoading, isOpen, setI
117
148
  if (isOpen) {
118
149
  setIsOpen(false);
119
150
  }
120
- console.log('Booking package details sent to onBook callback:', bookingPackageDetails);
151
+
121
152
  if (context?.onBook) {
122
153
  context.onBook(bookingPackageDetails);
123
154
  }
124
155
  };
125
156
 
126
- const calculateTotalPrice = () => {
127
- const selectedOptions = selectedBookingPackageDetails?.rooms.flatMap((room) => room.options.filter((option) => option.isSelected));
128
- const totalPrice = selectedOptions?.reduce((total, option) => total + (option.price || 0), 0);
129
- return formatPrice(totalPrice, bookingPackageDetails?.currencyCode);
130
- };
157
+ const getPriceDifference = (roomIndex: number, accommodationCode: string, regimeId?: string) => {
158
+ const currentSelectedOption = getSelectedOptionForRoom(roomIndex);
159
+ const currentSelectedPrice = currentSelectedOption?.price || 0;
131
160
 
132
- const getPriceDifference = (currentSelectedPrice: number | undefined, roomIndex: number, accommodationCode: string, regimeId?: string) => {
133
- let targetPrice = 0;
134
-
135
- const selectedOption = getSelectedOptionForAccommodation(roomIndex, accommodationCode);
136
-
137
- if (selectedOption?.price) {
138
- targetPrice = selectedOption.price;
139
- } else {
140
- const firstOption = selectedBookingPackageDetails?.rooms[roomIndex].options.find((option) => option.accommodationCode === accommodationCode);
141
- targetPrice = firstOption?.price || 0;
142
- }
161
+ let targetOption;
143
162
 
144
163
  if (regimeId) {
145
- const regimeOption = selectedBookingPackageDetails?.rooms[roomIndex].options.find((option) => option.entryLineGuid === regimeId);
146
- targetPrice = regimeOption?.price || 0;
164
+ targetOption = selectedBookingPackageDetails.rooms?.[roomIndex]?.options?.find((option) => option.entryLineGuid === regimeId);
165
+ } else {
166
+ targetOption =
167
+ getSelectedOptionForAccommodation(roomIndex, accommodationCode) ??
168
+ selectedBookingPackageDetails.rooms?.[roomIndex]?.options?.find((option) => option.accommodationCode === accommodationCode);
147
169
  }
148
170
 
149
- return targetPrice - (currentSelectedPrice || 0);
171
+ return (targetOption?.price || 0) - currentSelectedPrice;
150
172
  };
151
173
 
152
174
  const formatPriceDifference = (difference: number, currencyCode: string) => {
@@ -171,13 +193,30 @@ const GroupTourFlyIn: React.FC<GroupTourFlyInProps> = ({ isLoading, isOpen, setI
171
193
  };
172
194
 
173
195
  const regimeFormatter = (roomIndex: number, accommodation: GroupedAccommodation, regimeId: string, label: string) => {
174
- const roomOption = getSelectedOptionForRoom(roomIndex);
175
-
176
- const difference = getPriceDifference(roomOption?.price, roomIndex, accommodation.accommodationCode, regimeId);
177
-
196
+ const difference = getPriceDifference(roomIndex, accommodation.accommodationCode, regimeId);
178
197
  return `${label} ${difference !== 0 ? `(${formatPriceDifference(difference, bookingPackageDetails.currencyCode)})` : ''}`;
179
198
  };
180
199
 
200
+ const adjustedTotalPrice = useMemo(() => {
201
+ if (!selectedBookingPackageDetails.rooms || typeof selectedBookingPackageDetails.price !== 'number') {
202
+ return 0;
203
+ }
204
+
205
+ const basePrice = selectedBookingPackageDetails.price;
206
+
207
+ const totalDelta = selectedBookingPackageDetails.rooms.reduce((sum, room, roomIndex) => {
208
+ const initialOption = getInitialSelectedOptionForRoom(roomIndex);
209
+ const currentOption = room.options.find((option) => option.isSelected);
210
+
211
+ const initialPrice = initialOption?.price || 0;
212
+ const currentPrice = currentOption?.price || 0;
213
+
214
+ return sum + (currentPrice - initialPrice);
215
+ }, 0);
216
+
217
+ return basePrice + totalDelta;
218
+ }, [selectedBookingPackageDetails, packageKey]);
219
+
181
220
  return (
182
221
  <>
183
222
  <div className="flyin__content">
@@ -190,8 +229,8 @@ const GroupTourFlyIn: React.FC<GroupTourFlyInProps> = ({ isLoading, isOpen, setI
190
229
  <div className="flyin__acco__cards">
191
230
  {roomAccommodations.map((accommodation) => {
192
231
  const selectedOption = getSelectedOptionForAccommodation(roomIndex, accommodation.accommodationCode);
232
+ const priceDifference = getPriceDifference(roomIndex, accommodation.accommodationCode);
193
233
 
194
- const priceDifference = getPriceDifference(selectedRoomOption?.price, roomIndex, accommodation.accommodationCode);
195
234
  return (
196
235
  <div className="flyin__acco__card" key={`${roomIndex}-${accommodation.accommodationCode}`}>
197
236
  <div className="flyin__acco__content">
@@ -201,9 +240,9 @@ const GroupTourFlyIn: React.FC<GroupTourFlyInProps> = ({ isLoading, isOpen, setI
201
240
  <div className="flyin__acco__footer">
202
241
  <ItemPicker
203
242
  items={accommodation.regimes}
204
- selection={selectedOption?.regimeName}
205
- label={''}
206
- placeholder={'Select regime'}
243
+ selection={selectedOption != null ? selectedOption.regimeName ?? 'No regime' : undefined}
244
+ label=""
245
+ placeholder="Select regime"
207
246
  classModifier=""
208
247
  onPick={(selected, selectedGuid) => handlePick(roomIndex, selectedGuid)}
209
248
  valueFormatter={(id, label) => regimeFormatter(roomIndex, accommodation, id, label)}
@@ -212,19 +251,19 @@ const GroupTourFlyIn: React.FC<GroupTourFlyInProps> = ({ isLoading, isOpen, setI
212
251
  <div className="flyin__acco__footer__actions">
213
252
  <button
214
253
  className={
215
- selectedRoomOption?.accommodationCode == accommodation.accommodationCode ? 'cta cta--select cta--selected' : 'cta cta--select'
254
+ selectedRoomOption?.accommodationCode === accommodation.accommodationCode ? 'cta cta--select cta--selected' : 'cta cta--select'
216
255
  }
217
256
  onClick={() => {
218
257
  handlePick(roomIndex, selectedOption ? selectedOption.entryLineGuid : first(accommodation.regimes)?.id);
219
258
  }}>
220
- {selectedRoomOption?.accommodationCode == accommodation.accommodationCode
259
+ {selectedRoomOption?.accommodationCode === accommodation.accommodationCode
221
260
  ? translations?.SHARED.SELECTED
222
261
  : translations?.SHARED.SELECT}
223
262
  </button>
224
263
 
225
264
  <div className="flyin__acco__price__wrapper">
226
265
  <span className={getPriceDifferenceClassName(priceDifference)}>
227
- {formatPriceDifference(priceDifference, bookingPackageDetails?.currencyCode)}
266
+ {formatPriceDifference(priceDifference, bookingPackageDetails.currencyCode)}
228
267
  </span>
229
268
  </div>
230
269
  </div>
@@ -239,7 +278,7 @@ const GroupTourFlyIn: React.FC<GroupTourFlyInProps> = ({ isLoading, isOpen, setI
239
278
  </div>
240
279
 
241
280
  <div className="flyin__footer">
242
- <div className="flyin__footer__price">Total price: {calculateTotalPrice()}</div>
281
+ <div className="flyin__footer__price">Total price: {formatPrice(adjustedTotalPrice, bookingPackageDetails.currencyCode)}</div>
243
282
 
244
283
  <div className="flyin__button-wrapper">
245
284
  <button className="cta cta--select" onClick={handleConfirm}>