@qite/tide-booking-component 1.4.109 → 1.4.110

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 (81) hide show
  1. package/build/build-cjs/index.js +1351 -775
  2. package/build/build-cjs/src/booking-wizard/components/step-route.d.ts +2 -2
  3. package/build/build-cjs/src/booking-wizard/features/sidebar/sidebar-flight.d.ts +1 -0
  4. package/build/build-cjs/src/booking-wizard/features/sidebar/sidebar-util.d.ts +2 -1
  5. package/build/build-cjs/src/booking-wizard/features/sidebar/sidebar.d.ts +0 -31
  6. package/build/build-cjs/src/search-results/components/book-packaging-entry/index.d.ts +7 -0
  7. package/build/build-cjs/src/search-results/components/book-packaging-entry/wl-sidebar.d.ts +7 -0
  8. package/build/build-cjs/src/search-results/components/spinner/spinner.d.ts +4 -1
  9. package/build/build-cjs/src/search-results/store/search-results-slice.d.ts +5 -1
  10. package/build/build-cjs/src/shared/booking/BookingPanel.d.ts +13 -0
  11. package/build/build-cjs/src/shared/booking/Sidebar.d.ts +34 -0
  12. package/build/build-cjs/src/shared/booking/StepIndicators.d.ts +7 -0
  13. package/build/build-cjs/src/shared/components/flyin/flyin.d.ts +2 -0
  14. package/build/build-cjs/src/shared/components/flyin/packaging-flights-flyin.d.ts +2 -0
  15. package/build/build-cjs/src/shared/utils/localization-util.d.ts +1 -0
  16. package/build/build-esm/index.js +1335 -770
  17. package/build/build-esm/src/booking-wizard/components/step-route.d.ts +2 -2
  18. package/build/build-esm/src/booking-wizard/features/sidebar/sidebar-flight.d.ts +1 -0
  19. package/build/build-esm/src/booking-wizard/features/sidebar/sidebar-util.d.ts +2 -1
  20. package/build/build-esm/src/booking-wizard/features/sidebar/sidebar.d.ts +0 -31
  21. package/build/build-esm/src/search-results/components/book-packaging-entry/index.d.ts +7 -0
  22. package/build/build-esm/src/search-results/components/book-packaging-entry/wl-sidebar.d.ts +7 -0
  23. package/build/build-esm/src/search-results/components/spinner/spinner.d.ts +4 -1
  24. package/build/build-esm/src/search-results/store/search-results-slice.d.ts +5 -1
  25. package/build/build-esm/src/shared/booking/BookingPanel.d.ts +13 -0
  26. package/build/build-esm/src/shared/booking/Sidebar.d.ts +34 -0
  27. package/build/build-esm/src/shared/booking/StepIndicators.d.ts +7 -0
  28. package/build/build-esm/src/shared/components/flyin/flyin.d.ts +2 -0
  29. package/build/build-esm/src/shared/components/flyin/packaging-flights-flyin.d.ts +2 -0
  30. package/build/build-esm/src/shared/utils/localization-util.d.ts +1 -0
  31. package/package.json +1 -1
  32. package/src/booking-wizard/components/step-indicator.tsx +10 -31
  33. package/src/booking-wizard/components/step-route.tsx +39 -14
  34. package/src/booking-wizard/features/sidebar/index.tsx +10 -4
  35. package/src/booking-wizard/features/sidebar/sidebar-flight.tsx +2 -2
  36. package/src/booking-wizard/features/sidebar/sidebar-util.ts +1 -5
  37. package/src/booking-wizard/features/sidebar/sidebar.tsx +331 -326
  38. package/src/search-results/components/book-packaging-entry/index.tsx +48 -0
  39. package/src/search-results/components/book-packaging-entry/wl-sidebar.tsx +165 -0
  40. package/src/search-results/components/excursions/day-by-day-excursions.tsx +6 -2
  41. package/src/search-results/components/excursions/excursion-results.tsx +1 -1
  42. package/src/search-results/components/flight/flight-selection/independent-flight-selection.tsx +12 -3
  43. package/src/search-results/components/hotel/hotel-accommodation-results.tsx +6 -3
  44. package/src/search-results/components/itinerary/full-itinerary.tsx +1 -1
  45. package/src/search-results/components/itinerary/index.tsx +13 -12
  46. package/src/search-results/components/search-results-container/flight-search-results.tsx +1 -1
  47. package/src/search-results/components/search-results-container/search-results-container.tsx +239 -204
  48. package/src/search-results/components/spinner/spinner.tsx +12 -4
  49. package/src/search-results/store/search-results-slice.ts +16 -2
  50. package/src/shared/booking/BookingPanel.tsx +25 -0
  51. package/src/shared/booking/Sidebar.tsx +432 -0
  52. package/src/shared/booking/StepIndicators.tsx +30 -0
  53. package/src/shared/components/flyin/accommodation-flyin.tsx +3 -4
  54. package/src/shared/components/flyin/flights-flyin.tsx +1 -1
  55. package/src/shared/components/flyin/flyin.tsx +12 -4
  56. package/src/shared/components/flyin/group-tour-flyin.tsx +3 -4
  57. package/src/shared/components/flyin/packaging-flights-flyin.tsx +11 -4
  58. package/src/shared/components/icon.tsx +13 -0
  59. package/src/shared/translations/ar-SA.json +7 -1
  60. package/src/shared/translations/da-DK.json +7 -1
  61. package/src/shared/translations/de-DE.json +7 -1
  62. package/src/shared/translations/en-GB.json +8 -2
  63. package/src/shared/translations/es-ES.json +7 -1
  64. package/src/shared/translations/fr-BE.json +7 -1
  65. package/src/shared/translations/fr-FR.json +7 -1
  66. package/src/shared/translations/is-IS.json +7 -1
  67. package/src/shared/translations/it-IT.json +7 -1
  68. package/src/shared/translations/ja-JP.json +7 -1
  69. package/src/shared/translations/nl-BE.json +7 -1
  70. package/src/shared/translations/nl-NL.json +7 -1
  71. package/src/shared/translations/no-NO.json +7 -1
  72. package/src/shared/translations/pl-PL.json +7 -1
  73. package/src/shared/translations/pt-PT.json +7 -1
  74. package/src/shared/translations/sv-SE.json +7 -1
  75. package/src/shared/utils/localization-util.ts +8 -0
  76. package/styles/components/_loader.scss +82 -0
  77. package/styles/components/_search.scss +9 -2
  78. package/styles/content-blocks-variables.scss +14 -14
  79. /package/build/build-cjs/src/{booking-wizard/components → shared/booking}/product-card.d.ts +0 -0
  80. /package/build/build-esm/src/{booking-wizard/components → shared/booking}/product-card.d.ts +0 -0
  81. /package/src/{booking-wizard/components → shared/booking}/product-card.tsx +0 -0
@@ -0,0 +1,48 @@
1
+ import React, { useContext } from 'react';
2
+ import { getTranslations } from '../../../shared/utils/localization-util';
3
+ import { SearchResultsRootState } from '../../store/search-results-store';
4
+ import { useDispatch, useSelector } from 'react-redux';
5
+ import SearchResultsConfigurationContext from '../../search-results-configuration-context';
6
+ import BookingPanel from '../../../shared/booking/BookingPanel';
7
+ import StepIndicators from '../../../shared/booking/StepIndicators';
8
+ import WLSidebar from './wl-sidebar';
9
+ import { SearchSeed } from '../../types';
10
+
11
+ interface BookPackagingEntryProps {
12
+ activeSearchSeed: SearchSeed | null;
13
+ }
14
+
15
+ const BookPackagingEntry: React.FC<BookPackagingEntryProps> = ({ activeSearchSeed }) => {
16
+ const context = useContext(SearchResultsConfigurationContext);
17
+ if (!context) {
18
+ return null;
19
+ }
20
+ const translations = getTranslations(context.languageCode ?? 'en-GB');
21
+ const { currentStep } = useSelector((state: SearchResultsRootState) => state.searchResults);
22
+ const dispatch = useDispatch();
23
+
24
+ const stepLabels = [translations.STEPS.PERSONAL_DETAILS, translations.STEPS.SUMMARY, translations.STEPS.CONFIRMATION];
25
+
26
+ return (
27
+ <div className="booking">
28
+ <div className="booking__content">
29
+ <BookingPanel
30
+ currentStep={currentStep}
31
+ stepLabels={stepLabels}
32
+ StepIndicatorsComponent={StepIndicators}
33
+ renderTitle={(step) => (
34
+ <>
35
+ {step + 1}.&nbsp;{stepLabels[step]}
36
+ </>
37
+ )}>
38
+ {/* Panel body content goes here */}
39
+ <div></div>
40
+ </BookingPanel>
41
+ <div className="backdrop" id="backdrop"></div>
42
+ <WLSidebar activeSearchSeed={activeSearchSeed} />
43
+ </div>
44
+ </div>
45
+ );
46
+ };
47
+
48
+ export default BookPackagingEntry;
@@ -0,0 +1,165 @@
1
+ import React, { useContext, useMemo } from 'react';
2
+ import { formatDate, getDateOnlyTime, getTranslations } from '../../../shared/utils/localization-util';
3
+ import { SearchResultsRootState } from '../../store/search-results-store';
4
+ import { useSelector } from 'react-redux';
5
+ import SearchResultsConfigurationContext from '../../search-results-configuration-context';
6
+ import SharedSidebar from '../../../shared/booking/Sidebar';
7
+
8
+ import { ACCOMMODATION_SERVICE_TYPE, FLIGHT_SERVICE_TYPE } from '../../utils/query-utils';
9
+ import { first, last, sum } from 'lodash';
10
+ import { SearchSeed } from '../../types';
11
+ import { getTravelersText } from '../../../booking-wizard/features/sidebar/sidebar-util';
12
+ import { RoomTraveler } from '../../../booking-wizard/types';
13
+
14
+ import { BookingPackageFlightMetaData, BookingPriceDetail, PackagingEntryLine } from '@qite/tide-client';
15
+ import Spinner from '../spinner/spinner';
16
+
17
+ interface WLSidebarProps {
18
+ activeSearchSeed: SearchSeed | null;
19
+ }
20
+
21
+ const mapToSidebarFlightMetaData = (entryLine: PackagingEntryLine) => {
22
+ return {
23
+ flightLines: entryLine.flightInformation?.flightLines.map((f) => ({
24
+ number: f.flightNumber,
25
+ departureDate: f.departureDate,
26
+ departureAirport: f.departureAirportCode,
27
+ departureAirportDescription: f.departureAirportDescription,
28
+ departureTime: f.departureTime,
29
+ arrivalDate: f.arrivalDate,
30
+ arrivalAirport: f.arrivalAirportCode,
31
+ arrivalAirportDescription: f.arrivalAirportDescription,
32
+ arrivalTime: f.arrivalTime,
33
+ flightClass: '',
34
+ travelClass: '',
35
+ airline: f.airlineDescription,
36
+ airlineCode: f.airlineCode,
37
+ operatingAirlineCode: f.operatingAirlineCode,
38
+ operatingAirlineDescription: f.operatingAirlineDescription,
39
+ durationInTicks: f.durationInTicks
40
+ })),
41
+ luggageIncluded: false, // Not present in editablePackagingEntry, set default
42
+ bagageAllowed: false, // Not present in editablePackagingEntry, set default
43
+ bagage: '', // Not present in editablePackagingEntry, set default
44
+ mealIncluded: false, // Not present in editablePackagingEntry, set default
45
+ meal: '', // Not present in editablePackagingEntry, set default
46
+ durationInTicks: entryLine.flightInformation?.flightLines.reduce((s, { durationInTicks }) => s + (durationInTicks ?? 0), 0)
47
+ } as BookingPackageFlightMetaData;
48
+ };
49
+
50
+ const selectSeparatePackagePriceDetails = (priceDetails: BookingPriceDetail[]) => {
51
+ const result: BookingPriceDetail[] = [];
52
+ const filteredPriceDetails = priceDetails.filter((priceDetail) => priceDetail.isSeparate);
53
+
54
+ filteredPriceDetails.forEach((priceDetail) => {
55
+ const priceDetailToMerge = result.find(
56
+ (x) => x.productCode === priceDetail.productCode && x.accommodationCode === priceDetail.accommodationCode && x.productType === priceDetail.productType
57
+ );
58
+ if (priceDetailToMerge) {
59
+ priceDetailToMerge.total += priceDetail.total;
60
+ priceDetailToMerge.price += priceDetail.price;
61
+ } else {
62
+ result.push(Object.assign({}, priceDetail));
63
+ }
64
+ });
65
+
66
+ return result;
67
+ };
68
+
69
+ const WLSidebar: React.FC<WLSidebarProps> = ({ activeSearchSeed }) => {
70
+ const context = useContext(SearchResultsConfigurationContext);
71
+ if (!context) {
72
+ return null;
73
+ }
74
+ const translations = getTranslations(context.languageCode ?? 'en-GB');
75
+ const { editablePackagingEntry, priceDetails } = useSelector((state: SearchResultsRootState) => state.searchResults);
76
+
77
+ // Map editablePackagingEntry to sidebar props (example, adjust as needed)
78
+ if (!editablePackagingEntry) {
79
+ return null;
80
+ }
81
+
82
+ console.log('editablePackagingEntry in WLSidebar:', editablePackagingEntry);
83
+ console.log('priceDetails in WLSidebar:', priceDetails);
84
+
85
+ const sortedLines = useMemo(() => {
86
+ return [...(editablePackagingEntry?.lines ?? [])].sort((a, b) => {
87
+ const dateA = getDateOnlyTime(a.from);
88
+ const dateB = getDateOnlyTime(b.from);
89
+
90
+ if (dateA !== dateB) {
91
+ return dateA - dateB;
92
+ }
93
+
94
+ return (a.order ?? Infinity) - (b.order ?? Infinity);
95
+ });
96
+ }, [editablePackagingEntry]);
97
+
98
+ const firstEntryLine = first(sortedLines);
99
+ const accommodationLines = editablePackagingEntry.lines.filter((line) => line.serviceType === ACCOMMODATION_SERVICE_TYPE);
100
+ const accommodationLine = first(accommodationLines) ?? firstEntryLine;
101
+
102
+ const location =
103
+ accommodationLine?.location?.name ??
104
+ accommodationLine?.oord?.name ??
105
+ accommodationLine?.region?.name ??
106
+ accommodationLine?.country?.name ??
107
+ firstEntryLine?.location?.name;
108
+
109
+ const rooms =
110
+ activeSearchSeed?.rooms.map((room) => {
111
+ const adults = room.pax
112
+ .filter((p) => p.age && p.age >= 18)
113
+ .map((p) => {
114
+ return { id: p.id, age: p.age } as RoomTraveler;
115
+ });
116
+ const children = room.pax
117
+ .filter((p) => p.age && p.age < 18)
118
+ .map((p) => {
119
+ return { id: p.id, age: p.age } as RoomTraveler;
120
+ });
121
+ return { adults, children };
122
+ }) || [];
123
+
124
+ const travelerRooms = getTravelersText(rooms, translations);
125
+
126
+ const flightSegments = sortedLines.filter(
127
+ (line) => line.serviceType === FLIGHT_SERVICE_TYPE && line.flightInformation && Array.isArray(line.flightInformation.flightLines)
128
+ );
129
+ const outboundFlight = first(flightSegments);
130
+ const returnFlight = flightSegments.length > 1 ? last(flightSegments) : undefined;
131
+ const outboundFlightMetaData = outboundFlight ? mapToSidebarFlightMetaData(outboundFlight) : undefined;
132
+ const returnFlightMetaData = returnFlight ? mapToSidebarFlightMetaData(returnFlight) : undefined;
133
+
134
+ const basePrice = sum(priceDetails?.details.filter((pd) => pd.isInPackage).map((pd) => pd.price * pd.amount) ?? []);
135
+ const separateExtraPriceDetails = priceDetails?.details.filter((pd) => !pd.isInPackage && pd.isSeparate) ?? [];
136
+ const totalPrice = sum([basePrice, ...separateExtraPriceDetails.map((priceDetail) => priceDetail.price * priceDetail.amount)]);
137
+
138
+ const includedCosts = selectSeparatePackagePriceDetails(priceDetails?.details.filter((pd) => pd.isInPackage) ?? []);
139
+ return (
140
+ <SharedSidebar
141
+ productName={location ?? ''}
142
+ thumbnailUrl={context.destinationImage?.url}
143
+ translations={translations}
144
+ travelerRooms={travelerRooms}
145
+ startDateText={first(sortedLines)?.from && formatDate(new Date(first(sortedLines)!.from))}
146
+ endDateText={last(sortedLines)?.to && formatDate(new Date(last(sortedLines)!.to))}
147
+ isLoading={!editablePackagingEntry || !priceDetails}
148
+ loaderComponent={<Spinner />}
149
+ departureFlightMetaData={outboundFlightMetaData}
150
+ returnFlightMetaData={returnFlightMetaData}
151
+ includedServiceTypes={editablePackagingEntry.lines.map((line) => line.serviceType)}
152
+ packagingAccommodations={accommodationLines}
153
+ basePrice={basePrice}
154
+ commission={priceDetails?.commission}
155
+ totalPrice={totalPrice}
156
+ includedCosts={includedCosts}
157
+ extraCosts={separateExtraPriceDetails}
158
+ deposit={priceDetails?.deposit}
159
+ isUnavailable={false}
160
+ agent={context.agentId}
161
+ />
162
+ );
163
+ };
164
+
165
+ export default WLSidebar;
@@ -93,10 +93,14 @@ const DayByDayExcursions: React.FC<DayByDayExcursionsProps> = () => {
93
93
  <React.Fragment key={dayKey}>
94
94
  <div className="search__results__label search__results__label--secondary">
95
95
  <div className="search__results__label__date">
96
- <Icon name="ui-excursion" height={16} fill="white" />
96
+ <p className="search__results__label__date-date">{format(day, 'd', { locale: getLocale(context?.languageCode ?? 'en-GB') })}</p>
97
+ <p>{format(day, 'MMM', { locale: getLocale(context?.languageCode ?? 'en-GB') })}</p>
97
98
  </div>
98
99
  <div className="search__results__label__text">
99
- <h3>{format(day, 'EEEE d MMMM', { locale: getLocale(context?.languageCode ?? 'en-GB') })}</h3>
100
+ <Icon name="ui-excursion" height={16} />
101
+ <h3>
102
+ {translations.SRP.SELECT} <strong>{translations.SRP.EXCURSION}</strong>
103
+ </h3>
100
104
  </div>
101
105
  </div>
102
106
 
@@ -122,7 +122,7 @@ const ExcursionResults: React.FC<ExcursionResultsProps> = ({ isFlyIn, activeSear
122
122
  };
123
123
 
124
124
  return isLoading ? (
125
- <Spinner />
125
+ <Spinner label={translations.SRP.LOADING_EXCURSIONS} />
126
126
  ) : (
127
127
  <div className="flyin__content flyin__content--columns">
128
128
  {/* <Filters
@@ -3,12 +3,12 @@ import Icon from '../../../../shared/components/icon';
3
3
  import { ExtendedFlightSearchResponseItem } from '../../../types';
4
4
  import SearchResultsConfigurationContext from '../../../search-results-configuration-context';
5
5
  import { getTranslations } from '../../../../shared/utils/localization-util';
6
- import { FlightSearchResponseFlightSegment } from '@qite/tide-client';
7
6
  import IndependentFlightOption from './independent-flight-option';
8
7
  import { useDispatch } from 'react-redux';
9
8
  import { setFlyInIsOpen, setSelectedFlight } from '../../../store/search-results-slice';
10
9
  import { useFlightSearch } from '../flight-search-context';
11
10
  import { getFlightKey } from '../../../utils/flight-utils';
11
+ import { format } from 'date-fns';
12
12
 
13
13
  interface IndependentFlightSelectionProps {
14
14
  searchResults: ExtendedFlightSearchResponseItem[];
@@ -93,13 +93,20 @@ const IndependentFlightSelection: React.FC<IndependentFlightSelectionProps> = ({
93
93
  return searchResults.find((flight) => getFlightKey(flight.return.segments) === selectedReturnKey) || null;
94
94
  }, [searchResults, selectedReturnKey]);
95
95
 
96
+ const firstResultDate = uniqueOutwardFlights.length > 0 ? uniqueOutwardFlights[0].outward.segments[0].departureDateTime : null;
97
+
98
+ const firstResultDay = firstResultDate ? format(firstResultDate, 'd') : null;
99
+ const firstResultMonth = firstResultDate ? format(firstResultDate, 'MMM') : null;
100
+
96
101
  return (
97
102
  <>
98
103
  <div className="search__results__label search__results__label--secondary">
99
104
  <div className="search__results__label__date">
100
- <Icon name="ui-flight" height={16} fill="white" />
105
+ <p className="search__results__label__date-date">{firstResultDay}</p>
106
+ <p>{firstResultMonth}</p>
101
107
  </div>
102
108
  <div className="search__results__label__text">
109
+ <Icon name="ui-flight" height={16} fill="white" />
103
110
  <h3>
104
111
  {translations.SRP.SELECT} <strong> {translations.SRP.DEPARTURE}</strong>
105
112
  </h3>
@@ -131,9 +138,11 @@ const IndependentFlightSelection: React.FC<IndependentFlightSelectionProps> = ({
131
138
 
132
139
  <div className="search__results__label search__results__label--secondary">
133
140
  <div className="search__results__label__date">
134
- <Icon name="ui-flight" height={16} fill="white" />
141
+ {/* <p className="search__results__label__date-date">{format(day, 'd', { locale: getLocale(context?.languageCode ?? 'en-GB') })}</p>
142
+ <p>{format(day, 'MMM', { locale: getLocale(context?.languageCode ?? 'en-GB') })}</p> */}
135
143
  </div>
136
144
  <div className="search__results__label__text">
145
+ <Icon name="ui-flight" height={16} fill="white" />
137
146
  <h3>
138
147
  {translations.SRP.SELECT} <strong> {translations.SRP.RETURN}</strong>
139
148
  </h3>
@@ -196,16 +196,19 @@ const HotelAccommodationResults: React.FC<HotelAccommodationResultsProps> = ({ i
196
196
  {!isFlyIn && (
197
197
  <div className="search__results__label search__results__label--secondary">
198
198
  <div className="search__results__label__date">
199
- {firstResultDay && firstResultMonth ? (
199
+ {/* /* {firstResultDay && firstResultMonth ? (
200
200
  <>
201
201
  <p className="search__results__label__date-date">{firstResultDay}</p>
202
202
  <p>{firstResultMonth}</p>
203
203
  </>
204
204
  ) : (
205
205
  <Icon name="ui-bed" height={16} fill="white" />
206
- )}
206
+ )} */}
207
+ <p className="search__results__label__date-date">{firstResultDay}</p>
208
+ <p>{firstResultMonth}</p>
207
209
  </div>
208
210
  <div className="search__results__label__text">
211
+ <Icon name="ui-bed" height={16} />
209
212
  <h3>
210
213
  {translations.SRP.SELECT} <strong>{translations.SRP.ACCOMMODATION}</strong>
211
214
  </h3>
@@ -213,7 +216,7 @@ const HotelAccommodationResults: React.FC<HotelAccommodationResultsProps> = ({ i
213
216
  </div>
214
217
  )}
215
218
  {isLoading ? (
216
- <>{context.customSpinner ?? <Spinner />}</>
219
+ <>{context.customSpinner ?? <Spinner label={translations.SRP.LOADING_ACCOMMODATIONS} />}</>
217
220
  ) : (
218
221
  renderHotelResults(visibleResults, context, activeTab, translations, selectedPackagingAccoResult, isFlyIn)
219
222
  )}
@@ -365,7 +365,7 @@ const FullItinerary: React.FC<FullItineraryProps> = ({ isLoading }) => {
365
365
 
366
366
  return (
367
367
  <>
368
- {isLoading && <Spinner />}
368
+ {isLoading && <Spinner label={translations.SRP.LOADING_ITINERARY} />}
369
369
  <div ref={hostRef} style={{ display: isLoading ? 'none' : 'block' }} />
370
370
  </>
371
371
  );
@@ -4,11 +4,12 @@ import { first, groupBy, isEmpty, last } from 'lodash';
4
4
  import { PackagingEntryLine, PackagingEntryLineFlightLine } from '@qite/tide-client';
5
5
  import Icon from '../../../shared/components/icon';
6
6
  import SearchResultsConfigurationContext from '../../search-results-configuration-context';
7
- import { formatPrice, getTranslations } from '../../../shared/utils/localization-util';
8
- import { useSelector } from 'react-redux';
7
+ import { formatPrice, getDateOnlyTime, getTranslations } from '../../../shared/utils/localization-util';
8
+ import { useDispatch, useSelector } from 'react-redux';
9
9
  import { SearchResultsRootState } from '../../store/search-results-store';
10
10
  import { ACCOMMODATION_SERVICE_TYPE, FLIGHT_SERVICE_TYPE } from '../../utils/query-utils';
11
11
  import Spinner from '../spinner/spinner';
12
+ import { setBookPackagingEntry } from '../../store/search-results-slice';
12
13
 
13
14
  interface ItineraryProps {
14
15
  isOpen: boolean;
@@ -113,19 +114,13 @@ const getServiceTypePriority = (serviceType?: number) => {
113
114
  return SERVICE_TYPE_PRIORITY[serviceType ?? -1] ?? 2;
114
115
  };
115
116
 
116
- const getDateOnlyTime = (date?: string | Date | null) => {
117
- if (!date) return 0;
118
-
119
- const parsedDate = new Date(date);
120
-
121
- return new Date(parsedDate.getFullYear(), parsedDate.getMonth(), parsedDate.getDate()).getTime();
122
- };
123
-
124
117
  const Itinerary: React.FC<ItineraryProps> = ({ isOpen, handleSetIsOpen, isLoading, onEditAccommodation }) => {
125
118
  const context = useContext(SearchResultsConfigurationContext);
126
119
  const translations = getTranslations(context?.languageCode ?? 'en-GB');
127
120
  const { editablePackagingEntry, priceDetails } = useSelector((state: SearchResultsRootState) => state.searchResults);
128
121
 
122
+ const dispatch = useDispatch();
123
+
129
124
  const packagingEntry = editablePackagingEntry ?? context?.packagingEntry;
130
125
 
131
126
  const sortedLines = useMemo(() => {
@@ -177,6 +172,10 @@ const Itinerary: React.FC<ItineraryProps> = ({ isOpen, handleSetIsOpen, isLoadin
177
172
  const totalPrice = priceDetails?.total || packagingEntry.price || 0;
178
173
  const pricePerPerson = totalPrice / numberOfPax;
179
174
 
175
+ const handleConfirm = () => {
176
+ dispatch(setBookPackagingEntry(true));
177
+ };
178
+
180
179
  return (
181
180
  <div className={`search__filters--modal ${isOpen ? 'is-open' : ''}`}>
182
181
  <div className="search__filters--background" onClick={handleSetIsOpen}></div>
@@ -211,7 +210,7 @@ const Itinerary: React.FC<ItineraryProps> = ({ isOpen, handleSetIsOpen, isLoadin
211
210
 
212
211
  <div className="search__filter__prices">
213
212
  {isLoading ? (
214
- <Spinner />
213
+ <Spinner label={translations.PRODUCT.LOADING_PRICE} />
215
214
  ) : (
216
215
  <>
217
216
  <div className="search__filter__prices__wrapper">
@@ -223,7 +222,9 @@ const Itinerary: React.FC<ItineraryProps> = ({ isOpen, handleSetIsOpen, isLoadin
223
222
  </strong>
224
223
  </p>
225
224
  </div>
226
- <button className="cta">{translations.QSM.CONFIRM}</button>
225
+ <button className="cta" onClick={handleConfirm}>
226
+ {translations.QSM.CONFIRM}
227
+ </button>
227
228
  </>
228
229
  )}
229
230
  </div>
@@ -123,7 +123,7 @@ const FlightResultsContainer: React.FC<FlightResultsContainerProps> = ({ isMobil
123
123
  </div>
124
124
 
125
125
  <div className="search__results__wrapper">
126
- {flightsLoading && <Spinner />}
126
+ {flightsLoading && <Spinner label={translations.SRP.LOADING_FLIGHTS} />}
127
127
  {context?.searchConfiguration.qsmType == PortalQsmType.Flight && context?.showFlightAccommodationResults && results && results.length > 0 && (
128
128
  <FlightSelection searchResults={results} flightSelectionType={flightSelectionType} />
129
129
  )}