@roomstay/frontend 2.6.102 → 2.6.103

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.
Files changed (100) hide show
  1. package/dist/177.bundle.js +1 -1
  2. package/dist/211.bundle.js +1 -0
  3. package/dist/288.bundle.js +1 -1
  4. package/dist/326.bundle.js +2 -0
  5. package/dist/326.bundle.js.LICENSE.txt +16 -0
  6. package/dist/328.bundle.js +1 -1
  7. package/dist/main.bundle.js +1 -1
  8. package/dist/src/api/AnalyticsEventsAPI.d.ts +13 -0
  9. package/dist/src/api/AnalyticsEventsAPI.js +55 -0
  10. package/dist/src/api/AnalyticsEventsAPI.js.map +1 -0
  11. package/dist/src/components/generic/PromotionalCodeInput.js +1 -1
  12. package/dist/src/components/generic/PromotionalCodeInput.js.map +1 -1
  13. package/dist/src/components/steps/confirmation/PayPalPaymentOption/PayPalPaymentOption.d.ts +2 -0
  14. package/dist/src/components/steps/confirmation/PayPalPaymentOption/PayPalPaymentOption.js +86 -0
  15. package/dist/src/components/steps/confirmation/PayPalPaymentOption/PayPalPaymentOption.js.map +1 -0
  16. package/dist/src/components/steps/confirmation/RoomContactDetails.js +2 -0
  17. package/dist/src/components/steps/confirmation/RoomContactDetails.js.map +1 -1
  18. package/dist/src/components/steps/confirmation/StepConfirmationForm.js +1 -1
  19. package/dist/src/components/steps/confirmation/StepConfirmationForm.js.map +1 -1
  20. package/dist/src/components/steps/date/PeoplePicker.js +1 -1
  21. package/dist/src/components/steps/date/PeoplePicker.js.map +1 -1
  22. package/dist/src/components/steps/date/PeoplePickerRow.js +2 -2
  23. package/dist/src/components/steps/date/PeoplePickerRow.js.map +1 -1
  24. package/dist/src/components/steps/room/RoomListCrossSellBlock.js +1 -0
  25. package/dist/src/components/steps/room/RoomListCrossSellBlock.js.map +1 -1
  26. package/dist/src/components/steps/room/UserSearchSummary/UserSearchSummary.js +5 -3
  27. package/dist/src/components/steps/room/UserSearchSummary/UserSearchSummary.js.map +1 -1
  28. package/dist/src/components/steps/room/UserSearchSummary/UserSearchSummaryRow.js +2 -2
  29. package/dist/src/components/steps/room/UserSearchSummary/UserSearchSummaryRow.js.map +1 -1
  30. package/dist/src/components/steps/room/roomBuilderProgress/NumberOfAdultsPicker.js +3 -3
  31. package/dist/src/components/steps/room/roomBuilderProgress/NumberOfAdultsPicker.js.map +1 -1
  32. package/dist/src/components/steps/room/roomBuilderProgress/RoomBuilderProgress.js +3 -3
  33. package/dist/src/components/steps/room/roomBuilderProgress/RoomBuilderProgress.js.map +1 -1
  34. package/dist/src/contexts/BasketContext/BasketContextType.d.ts +4 -0
  35. package/dist/src/contexts/BasketContext/BasketContextType.js.map +1 -1
  36. package/dist/src/contexts/BasketContext/BasketContextWrapper.js +46 -6
  37. package/dist/src/contexts/BasketContext/BasketContextWrapper.js.map +1 -1
  38. package/dist/src/contexts/CompanyContext/CompanyContextWrapper.js +10 -0
  39. package/dist/src/contexts/CompanyContext/CompanyContextWrapper.js.map +1 -1
  40. package/dist/src/contexts/ConfirmationStepContext/ConfirmationStepContextWrapper.js +21 -3
  41. package/dist/src/contexts/ConfirmationStepContext/ConfirmationStepContextWrapper.js.map +1 -1
  42. package/dist/src/contexts/ConfirmationStepContext/ConfirmationStepPriceQuoteErrorModal.d.ts +9 -0
  43. package/dist/src/contexts/ConfirmationStepContext/ConfirmationStepPriceQuoteErrorModal.js +67 -0
  44. package/dist/src/contexts/ConfirmationStepContext/ConfirmationStepPriceQuoteErrorModal.js.map +1 -0
  45. package/dist/src/contexts/FullPageEngineContext/FullPageEngineContextWrapper.js +43 -7
  46. package/dist/src/contexts/FullPageEngineContext/FullPageEngineContextWrapper.js.map +1 -1
  47. package/dist/src/handlers/payment/PayPalPaymentHandler.d.ts +2 -0
  48. package/dist/src/handlers/payment/PayPalPaymentHandler.js +41 -0
  49. package/dist/src/handlers/payment/PayPalPaymentHandler.js.map +1 -0
  50. package/dist/src/hooks/useSearchScopeHook.d.ts +5 -2
  51. package/dist/src/hooks/useSearchScopeHook.js +57 -14
  52. package/dist/src/hooks/useSearchScopeHook.js.map +1 -1
  53. package/dist/src/models/Addon/Addon.js +4 -0
  54. package/dist/src/models/Addon/Addon.js.map +1 -1
  55. package/dist/src/models/Api/HotelDTO.d.ts +1 -1
  56. package/dist/src/models/Api/HotelDTO.js.map +1 -1
  57. package/dist/src/models/BasketRow.d.ts +5 -0
  58. package/dist/src/models/BasketRow.js +13 -1
  59. package/dist/src/models/BasketRow.js.map +1 -1
  60. package/dist/src/models/Client/Hotel/Hotel.d.ts +12 -0
  61. package/dist/src/models/Client/Hotel/Hotel.js.map +1 -1
  62. package/dist/src/pages/findReservation/FindReservationResults.js +2 -2
  63. package/dist/src/pages/findReservation/FindReservationResults.js.map +1 -1
  64. package/dist/src/pages/steps/StepAddon/StepAddonValidator.js +1 -1
  65. package/dist/src/pages/steps/StepAddon/StepAddonValidator.js.map +1 -1
  66. package/dist/src/pages/steps/StepConfirmation/StepConfirmationValidator.js +1 -1
  67. package/dist/src/pages/steps/StepConfirmation/StepConfirmationValidator.js.map +1 -1
  68. package/dist/src/pages/steps/StepRoom/StepRoomValidator.js +1 -1
  69. package/dist/src/pages/steps/StepRoom/StepRoomValidator.js.map +1 -1
  70. package/dist/src/pages/steps/StepThanks/StepThanksComponent.js +2 -2
  71. package/dist/src/pages/steps/StepThanks/StepThanksComponent.js.map +1 -1
  72. package/dist/src/providers/FeatureProvider.js +2 -0
  73. package/dist/src/providers/FeatureProvider.js.map +1 -1
  74. package/dist/src/providers/RatePillProvider.d.ts +1 -0
  75. package/dist/src/providers/RatePillProvider.js +11 -4
  76. package/dist/src/providers/RatePillProvider.js.map +1 -1
  77. package/dist/src/providers/feature/AnalyticsEventsFeature.d.ts +23 -0
  78. package/dist/src/providers/feature/AnalyticsEventsFeature.js +83 -0
  79. package/dist/src/providers/feature/AnalyticsEventsFeature.js.map +1 -0
  80. package/dist/src/translations/Translation.d.ts +5 -0
  81. package/dist/src/translations/Translation.js +5 -0
  82. package/dist/src/translations/Translation.js.map +1 -1
  83. package/dist/src/translations/languages/en-gb.js +9 -4
  84. package/dist/src/translations/languages/en-gb.js.map +1 -1
  85. package/dist/src/util/Analytics/Analytics.d.ts +7 -0
  86. package/dist/src/util/Analytics/Analytics.js +8 -1
  87. package/dist/src/util/Analytics/Analytics.js.map +1 -1
  88. package/dist/src/util/AnalyticsEvents/AnalyticsEvents.d.ts +61 -0
  89. package/dist/src/util/AnalyticsEvents/AnalyticsEvents.js +329 -0
  90. package/dist/src/util/AnalyticsEvents/AnalyticsEvents.js.map +1 -0
  91. package/dist/src/util/AnalyticsEvents/helpers.d.ts +30 -0
  92. package/dist/src/util/AnalyticsEvents/helpers.js +96 -0
  93. package/dist/src/util/AnalyticsEvents/helpers.js.map +1 -0
  94. package/dist/src/util/DataLayer.js +4 -4
  95. package/dist/src/util/DataLayer.js.map +1 -1
  96. package/dist/test.bundle.js +1 -1
  97. package/dist/vendors.bundle.js +1 -1
  98. package/package.json +3 -2
  99. package/dist/180.bundle.js +0 -1
  100. package/dist/570.bundle.js +0 -1
@@ -23,6 +23,7 @@ export interface BasketContextType {
23
23
  addRate: (rate: RoomRate, notify?: boolean) => Promise<void>;
24
24
  getAllValidRows: () => BasketRow[];
25
25
  getAllDatelessRows: () => BasketRow[];
26
+ isValidDateRange: () => boolean;
26
27
  getNumberOfAdults: (withTranslation: boolean) => number | string;
27
28
  getNumberOfChildren: (withTranslation: boolean) => number | string;
28
29
  getNumberOfInfants: (withTranslation: boolean) => number | string;
@@ -61,4 +62,7 @@ export interface BasketContextType {
61
62
  updateBasketFeeRows: () => void;
62
63
  onDatePickerOpenChange: (isOpen: boolean) => void;
63
64
  isDatePickerOpen: boolean;
65
+ canAddAnotherRoom: boolean;
66
+ hasPriceQuoteError: boolean;
67
+ isQuoteOrPencilReady: boolean;
64
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"BasketContextType.js","sourceRoot":"/","sources":["src/contexts/BasketContext/BasketContextType.ts"],"names":[],"mappings":"","sourcesContent":["import { IPaymentCheckoutDetails, IPromoCodeDetails, ReservationsDTO } from '@roomstay/core';\nimport type dayjs from 'dayjs';\n\nimport type { Addon } from '@/models/Addon/Addon';\nimport type BasketAddonRow from '@/models/BasketAddonRow';\nimport type BasketRow from '@/models/BasketRow';\nimport { ItemisedFee } from '@/models/Fee';\nimport type { IPromotion } from '@/models/Promotion/IPromotion.type';\nimport type { RoomRate } from '@/models/Room/RoomRate';\nimport { RoomstaySession } from '@/models/RoomstaySession';\n\nexport interface BasketContextType {\n selectedBasketRow: BasketRow;\n currentBasketRows: BasketRow[];\n basketAddonRows: BasketAddonRow[];\n basketFeeRows: ItemisedFee[];\n loadedPromotion: IPromotion | null;\n promoCodeDetails: IPromoCodeDetails | null; // Promo code details from availability response\n quoteQueryID: string; // This ID is used to detect changes and re-fetch deposit quotes during checkout.\n\n startDate: dayjs.Dayjs;\n endDate: dayjs.Dayjs;\n pencilId: string | undefined;\n\n isLoadingPriceQuote: boolean;\n\n addBasketRow: (row: BasketRow) => void;\n addRate: (rate: RoomRate, notify?: boolean) => Promise<void>;\n\n getAllValidRows: () => BasketRow[];\n getAllDatelessRows: () => BasketRow[];\n\n getNumberOfAdults: (withTranslation: boolean) => number | string;\n getNumberOfChildren: (withTranslation: boolean) => number | string;\n getNumberOfInfants: (withTranslation: boolean) => number | string;\n getNumberOfRooms: (withTranslation: boolean) => number | string;\n\n getTotalPrice: () => any;\n getTotalQuoteDeposit: () => number;\n getDepositQuoteFees: () => number;\n getTotalFees: () => number;\n getItemisedFees: () => ItemisedFee[];\n // Can be null if we don't know the pay now amount (SynXis)\n getTotalPayNow: () => number | null;\n\n updateBasketRow: (row: BasketRow, updateGlobalDates?: boolean) => void;\n removeBasketRow: (row: BasketRow) => void;\n\n clearBasketRows: (confirm: boolean) => void;\n selectBasketRow: (row: BasketRow | null) => void;\n\n setStartDate: (date: dayjs.Dayjs) => void;\n setEndDate: (date: dayjs.Dayjs) => void;\n setPromoCodeDetails: (details: IPromoCodeDetails | null) => void;\n\n quoteOrPencilReservation: (applyQuote: () => boolean) => void;\n\n hasCheckedOut: boolean;\n reservationData: ReservationsDTO;\n booked: (data: ReservationsDTO, reservationRequest?: RoomstaySession['reservationRequest']) => Promise<void>;\n rollback: () => void;\n checkedOut: (data: ReservationsDTO) => void;\n clearSelectedRates: () => void;\n finish: () => void;\n additionalPaymentRequired: (data: IPaymentCheckoutDetails) => void;\n\n getRowForAddon: (selectedAddon: Addon) => BasketAddonRow | undefined;\n\n setAddonQuantities: (addon: Addon, quantities: { quantity: number; adult: number; child: number }, selectedDate: string, selectedTime: string) => void;\n\n removeBasketAddonRow: (row: BasketAddonRow) => void;\n attemptSelectUnfilledRow: () => BasketRow | undefined;\n\n initBasketRows: (basketRows: BasketRow[]) => void;\n updateBasketFeeRows: () => void;\n\n onDatePickerOpenChange: (isOpen: boolean) => void;\n isDatePickerOpen: boolean;\n}\n"]}
1
+ {"version":3,"file":"BasketContextType.js","sourceRoot":"/","sources":["src/contexts/BasketContext/BasketContextType.ts"],"names":[],"mappings":"","sourcesContent":["import { IPaymentCheckoutDetails, IPromoCodeDetails, ReservationsDTO } from '@roomstay/core';\nimport type dayjs from 'dayjs';\n\nimport type { Addon } from '@/models/Addon/Addon';\nimport type BasketAddonRow from '@/models/BasketAddonRow';\nimport type BasketRow from '@/models/BasketRow';\nimport { ItemisedFee } from '@/models/Fee';\nimport type { IPromotion } from '@/models/Promotion/IPromotion.type';\nimport type { RoomRate } from '@/models/Room/RoomRate';\nimport { RoomstaySession } from '@/models/RoomstaySession';\n\nexport interface BasketContextType {\n selectedBasketRow: BasketRow;\n currentBasketRows: BasketRow[];\n basketAddonRows: BasketAddonRow[];\n basketFeeRows: ItemisedFee[];\n loadedPromotion: IPromotion | null;\n promoCodeDetails: IPromoCodeDetails | null; // Promo code details from availability response\n quoteQueryID: string; // This ID is used to detect changes and re-fetch deposit quotes during checkout.\n\n startDate: dayjs.Dayjs;\n endDate: dayjs.Dayjs;\n pencilId: string | undefined;\n\n isLoadingPriceQuote: boolean;\n\n addBasketRow: (row: BasketRow) => void;\n addRate: (rate: RoomRate, notify?: boolean) => Promise<void>;\n\n getAllValidRows: () => BasketRow[];\n getAllDatelessRows: () => BasketRow[];\n isValidDateRange: () => boolean;\n\n getNumberOfAdults: (withTranslation: boolean) => number | string;\n getNumberOfChildren: (withTranslation: boolean) => number | string;\n getNumberOfInfants: (withTranslation: boolean) => number | string;\n getNumberOfRooms: (withTranslation: boolean) => number | string;\n\n getTotalPrice: () => any;\n getTotalQuoteDeposit: () => number;\n getDepositQuoteFees: () => number;\n getTotalFees: () => number;\n getItemisedFees: () => ItemisedFee[];\n // Can be null if we don't know the pay now amount (SynXis)\n getTotalPayNow: () => number | null;\n\n updateBasketRow: (row: BasketRow, updateGlobalDates?: boolean) => void;\n removeBasketRow: (row: BasketRow) => void;\n\n clearBasketRows: (confirm: boolean) => void;\n selectBasketRow: (row: BasketRow | null) => void;\n\n setStartDate: (date: dayjs.Dayjs) => void;\n setEndDate: (date: dayjs.Dayjs) => void;\n setPromoCodeDetails: (details: IPromoCodeDetails | null) => void;\n\n quoteOrPencilReservation: (applyQuote: () => boolean) => void;\n\n hasCheckedOut: boolean;\n reservationData: ReservationsDTO;\n booked: (data: ReservationsDTO, reservationRequest?: RoomstaySession['reservationRequest']) => Promise<void>;\n rollback: () => void;\n checkedOut: (data: ReservationsDTO) => void;\n clearSelectedRates: () => void;\n finish: () => void;\n additionalPaymentRequired: (data: IPaymentCheckoutDetails) => void;\n\n getRowForAddon: (selectedAddon: Addon) => BasketAddonRow | undefined;\n\n setAddonQuantities: (addon: Addon, quantities: { quantity: number; adult: number; child: number }, selectedDate: string, selectedTime: string) => void;\n\n removeBasketAddonRow: (row: BasketAddonRow) => void;\n attemptSelectUnfilledRow: () => BasketRow | undefined;\n\n initBasketRows: (basketRows: BasketRow[]) => void;\n updateBasketFeeRows: () => void;\n\n onDatePickerOpenChange: (isOpen: boolean) => void;\n isDatePickerOpen: boolean;\n canAddAnotherRoom: boolean;\n hasPriceQuoteError: boolean;\n isQuoteOrPencilReady: boolean;\n}\n"]}
@@ -105,6 +105,7 @@ function BasketContextWrapper(props) {
105
105
  // Promo code details from availability response
106
106
  const [promoCodeDetails, setPromoCodeDetails] = (0, react_1.useState)(null);
107
107
  const [isLoadingPriceQuote, setIsLoadingPriceQuote] = (0, react_1.useState)(false);
108
+ const [hasPriceQuoteError, setHasPriceQuoteError] = (0, react_1.useState)(false); // If true, showing an error and enabling retry
108
109
  let loadedStartDate = null;
109
110
  let loadedEndDate = null;
110
111
  if ((_d = initialSession === null || initialSession === void 0 ? void 0 : initialSession.basketRows) === null || _d === void 0 ? void 0 : _d.length) {
@@ -276,7 +277,9 @@ function BasketContextWrapper(props) {
276
277
  const availableRow = filteredRows.find((row) => !row.getRate());
277
278
  // Return a row without a rate if found
278
279
  // If no such row exists , return the last row in the list
279
- return availableRow !== null && availableRow !== void 0 ? availableRow : filteredRows[filteredRows.length - 1];
280
+ const nextBasketRow = availableRow !== null && availableRow !== void 0 ? availableRow : filteredRows[filteredRows.length - 1];
281
+ nextBasketRow.normalizeDateRange();
282
+ return nextBasketRow;
280
283
  };
281
284
  const updateQueryParameters = (row) => {
282
285
  if (!row)
@@ -497,12 +500,36 @@ function BasketContextWrapper(props) {
497
500
  setBasketFeeRows(newFees);
498
501
  };
499
502
  const quoteQueryID = (0, react_1.useMemo)(() => {
500
- const requireQuote = (hotel === null || hotel === void 0 ? void 0 : hotel.rmsUseDepositQuote) || (hotel === null || hotel === void 0 ? void 0 : hotel.bookingFlow) !== core_1.EBookingFlow.Default;
503
+ const requireQuote = (hotel === null || hotel === void 0 ? void 0 : hotel.rmsUseDepositQuote) || (hotel === null || hotel === void 0 ? void 0 : hotel.bookingFlow) === core_1.EBookingFlow.PreCheckoutPencil;
501
504
  if (!hotel || !requireQuote) {
502
505
  return '';
503
506
  }
504
507
  return BookingAPI_1.default.Reservation.buildQuoteQueryID(currentBasketRows, isExternalMemberHotel ? memberNumber : undefined);
505
508
  }, [currentBasketRows, isExternalMemberHotel, memberNumber, hotel === null || hotel === void 0 ? void 0 : hotel.hotelID]);
509
+ /**
510
+ * Indicates whether required pricing data is ready.
511
+ *
512
+ * - Returns `true` when the hotel does not require a quote.
513
+ * - While a quote is loading, verifies all basket rows contain
514
+ * the required pricing data (`quoteDetails` or `pencilId`).
515
+ * - Used to block UI actions until pricing is ready.
516
+ */
517
+ const isQuoteOrPencilReady = (0, react_1.useMemo)(() => {
518
+ const requireQuote = !!(hotel === null || hotel === void 0 ? void 0 : hotel.rmsUseDepositQuote) || !!((hotel === null || hotel === void 0 ? void 0 : hotel.bookingFlow) && (hotel === null || hotel === void 0 ? void 0 : hotel.bookingFlow) == core_1.EBookingFlow.PreCheckoutPencil);
519
+ const isLoadedQuoteOrPencil = currentBasketRows.every((basketRow) => {
520
+ if ((hotel === null || hotel === void 0 ? void 0 : hotel.bookingFlow) === core_1.EBookingFlow.PreCheckoutPencil) {
521
+ return !!basketRow.pencilId;
522
+ }
523
+ if (hotel === null || hotel === void 0 ? void 0 : hotel.rmsUseDepositQuote) {
524
+ return !!basketRow.quoteDetails;
525
+ }
526
+ return true;
527
+ });
528
+ if (!hotel || !requireQuote || (requireQuote && !isLoadingPriceQuote && isLoadedQuoteOrPencil)) {
529
+ return true;
530
+ }
531
+ return false;
532
+ }, [isLoadingPriceQuote, hotel === null || hotel === void 0 ? void 0 : hotel.rmsUseDepositQuote, hotel === null || hotel === void 0 ? void 0 : hotel.bookingFlow, currentBasketRows]);
506
533
  /**
507
534
  * Calculate total price of all addons with promo code discounts applied.
508
535
  * Uses AddonDiscountCalculator to handle sequential discount allocation.
@@ -510,6 +537,10 @@ function BasketContextWrapper(props) {
510
537
  const calculateAddonTotalWithDiscounts = (0, react_1.useCallback)(() => {
511
538
  return AddonDiscountCalculator_1.AddonDiscountCalculator.calculateTotal(basketAddonRows, currentBasketRows, promoCodeDetails);
512
539
  }, [basketAddonRows, currentBasketRows, promoCodeDetails]);
540
+ // Whether another room can be added (within max rooms per booking limit)
541
+ const canAddAnotherRoom = (0, react_1.useMemo)(() => {
542
+ return !(hotel === null || hotel === void 0 ? void 0 : hotel.maxRoomsPerBooking) || (hotel === null || hotel === void 0 ? void 0 : hotel.maxRoomsPerBooking) > currentBasketRows.length;
543
+ }, [hotel === null || hotel === void 0 ? void 0 : hotel.maxRoomsPerBooking, currentBasketRows.length]);
513
544
  const workingContext = {
514
545
  startDate: startDate,
515
546
  endDate: endDate,
@@ -541,6 +572,8 @@ function BasketContextWrapper(props) {
541
572
  * @param {BasketRow} row - The basket row to add.
542
573
  */
543
574
  addBasketRow: (row) => {
575
+ if (!canAddAnotherRoom)
576
+ return;
544
577
  syncSelectedDateRange(row);
545
578
  checkAndApplyMemberOnlyPromo(row);
546
579
  // Determine if the basket is currently empty
@@ -675,6 +708,7 @@ function BasketContextWrapper(props) {
675
708
  return false;
676
709
  }
677
710
  setIsLoadingPriceQuote(true);
711
+ setHasPriceQuoteError(false);
678
712
  // Clear currently assigned quote details
679
713
  // If we're fetching basket row information the currently held info should be disregarded.
680
714
  currentBasketRows.forEach((row) => {
@@ -693,24 +727,23 @@ function BasketContextWrapper(props) {
693
727
  if ((hotel === null || hotel === void 0 ? void 0 : hotel.bookingFlow) === core_1.EBookingFlow.PreCheckoutPencil) {
694
728
  // Pencil call also passes back the quote (if applicable)
695
729
  pencilResponse = response;
730
+ // Important: When `hotel?.rmsUseDepositQuote` is false, `pencilResponse.quote` is always null
696
731
  quoteResponse = pencilResponse.quote;
697
732
  // Store parent pencil ID to pass back to the server later
698
733
  setPencilId(pencilResponse.pencilId);
699
734
  (_a = beContext.sessionProvider) === null || _a === void 0 ? void 0 : _a.updateSession({ pencilId: pencilResponse.pencilId });
700
735
  // Future improvement: Handle availability errors
701
736
  }
702
- else {
737
+ else if (hotel.rmsUseDepositQuote) {
703
738
  quoteResponse = response;
704
739
  }
705
- if (!quoteResponse) {
706
- return;
707
- }
708
740
  if (!applyQuote()) {
709
741
  // User has left the Confirmation step before the quote was ready, we'll stop here instead of updating the basket.
710
742
  // If we don't stop here, the user will be redirected back to the Confirmation step.
711
743
  setIsLoadingPriceQuote(false);
712
744
  return;
713
745
  }
746
+ // Ensure pencilId is assigned even when quoteResponse is not available
714
747
  for (const basketRow of currentBasketRows) {
715
748
  const quoteRow = (_b = quoteResponse === null || quoteResponse === void 0 ? void 0 : quoteResponse.rows) === null || _b === void 0 ? void 0 : _b.find((row) => row.rowId === basketRow.getID());
716
749
  const pencilRow = (_c = pencilResponse === null || pencilResponse === void 0 ? void 0 : pencilResponse.rows) === null || _c === void 0 ? void 0 : _c.find((row) => row.rowId === basketRow.getID());
@@ -723,6 +756,7 @@ function BasketContextWrapper(props) {
723
756
  updateBasketRow(basketRow);
724
757
  }
725
758
  }, (error) => {
759
+ setHasPriceQuoteError(true);
726
760
  console.log(error);
727
761
  console.log(`Error!: Retried ${maxRetryAttempts} times then quit!`);
728
762
  }, () => {
@@ -740,6 +774,9 @@ function BasketContextWrapper(props) {
740
774
  getAllDatelessRows: () => {
741
775
  return currentBasketRows.filter((item) => !item.getStartDate() || !item.getEndDate());
742
776
  },
777
+ isValidDateRange: () => {
778
+ return !!startDate && !!endDate && startDate.isBefore(endDate);
779
+ },
743
780
  getNumberOfAdults: (withTranslation = false) => {
744
781
  return returnAggregationAndTranslation((row) => row.getAdults(), withTranslation ? Translation_1.Translation.Step.Date.Adult : undefined);
745
782
  },
@@ -1055,6 +1092,9 @@ function BasketContextWrapper(props) {
1055
1092
  },
1056
1093
  // Indicates whether the DatePicker is currently open.
1057
1094
  isDatePickerOpen: isDatePickerOpen,
1095
+ canAddAnotherRoom: canAddAnotherRoom,
1096
+ hasPriceQuoteError: hasPriceQuoteError,
1097
+ isQuoteOrPencilReady: isQuoteOrPencilReady,
1058
1098
  };
1059
1099
  return (react_1.default.createElement(contexts_1.BasketContext.Provider, { value: workingContext },
1060
1100
  react_1.default.createElement(contexts_1.AuthenticationContextProvider, null,