@qite/tide-booking-component 1.4.98 → 1.4.99

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 (30) hide show
  1. package/build/build-cjs/index.js +1088 -637
  2. package/build/build-cjs/src/search-results/components/itinerary/index.d.ts +2 -0
  3. package/build/build-cjs/src/search-results/store/search-results-slice.d.ts +9 -10
  4. package/build/build-cjs/src/search-results/types.d.ts +23 -1
  5. package/build/build-cjs/src/search-results/utils/packaging-utils.d.ts +7 -0
  6. package/build/build-cjs/src/search-results/utils/query-utils.d.ts +11 -0
  7. package/build/build-cjs/src/shared/components/flyin/accommodation-flyin.d.ts +1 -2
  8. package/build/build-cjs/src/shared/components/flyin/flyin.d.ts +4 -0
  9. package/build/build-cjs/src/shared/utils/localization-util.d.ts +1 -0
  10. package/build/build-esm/index.js +1088 -637
  11. package/build/build-esm/src/search-results/components/itinerary/index.d.ts +2 -0
  12. package/build/build-esm/src/search-results/store/search-results-slice.d.ts +9 -10
  13. package/build/build-esm/src/search-results/types.d.ts +23 -1
  14. package/build/build-esm/src/search-results/utils/packaging-utils.d.ts +7 -0
  15. package/build/build-esm/src/search-results/utils/query-utils.d.ts +11 -0
  16. package/build/build-esm/src/shared/components/flyin/accommodation-flyin.d.ts +1 -2
  17. package/build/build-esm/src/shared/components/flyin/flyin.d.ts +4 -0
  18. package/build/build-esm/src/shared/utils/localization-util.d.ts +1 -0
  19. package/package.json +2 -2
  20. package/src/qsm/components/search-input-group/index.tsx +0 -1
  21. package/src/search-results/components/itinerary/index.tsx +132 -70
  22. package/src/search-results/components/search-results-container/search-results-container.tsx +444 -383
  23. package/src/search-results/store/search-results-slice.ts +22 -10
  24. package/src/search-results/types.ts +25 -1
  25. package/src/search-results/utils/packaging-utils.ts +75 -0
  26. package/src/search-results/utils/query-utils.ts +152 -0
  27. package/src/shared/components/flyin/accommodation-flyin.tsx +10 -11
  28. package/src/shared/components/flyin/flyin.tsx +52 -4
  29. package/styles/components/_flyin.scss +25 -0
  30. package/styles/components/_search.scss +26 -1
@@ -9,21 +9,21 @@ import {
9
9
  setIsLoading,
10
10
  setSelectedSearchResult,
11
11
  setBookingPackageDetails,
12
- setEntry,
13
12
  setFlyInIsOpen,
14
13
  setFilteredResults,
15
14
  setPackagingAccoResults,
16
15
  setFilteredPackagingAccoResults,
17
- setPackagingAccoSearchDetails
16
+ setPackagingAccoSearchDetails,
17
+ setEditablePackagingEntry,
18
+ setTransactionId,
19
+ setAccommodationFlyInStep
18
20
  } from '../../store/search-results-slice';
19
- import { Filter, SortByType } from '../../types';
21
+ import { AccommodationFlyInStep, Filter, SearchSeed, SortByType } from '../../types';
20
22
  import useMediaQuery from '../../../shared/utils/use-media-query-util';
21
23
  import ItemPicker from '../item-picker';
22
24
  import {
23
25
  TideClientConfig,
24
26
  details,
25
- detailsWL,
26
- getEntryLight,
27
27
  search,
28
28
  searchPackagingAccommodations,
29
29
  BookingPackageDestination,
@@ -32,16 +32,15 @@ import {
32
32
  BookingPackageRequest,
33
33
  BookingPackageRequestRoom,
34
34
  BookingPackageSearchRequest,
35
- EntryLight,
36
- EntryRoom,
37
35
  PackagingAccommodationRequest,
38
36
  PackagingDestination,
39
- PackagingRoom,
40
- PackagingTraveller,
41
- PortalQsmType
37
+ PortalQsmType,
38
+ PackagingEntry,
39
+ startTransaction,
40
+ PackagingEntryLine
42
41
  } from '@qite/tide-client';
43
42
  import { getDateFromParams, getNumberFromParams, getRoomsFromParams, getStringFromParams } from '../../../shared/utils/query-string-util';
44
- import { range } from 'lodash';
43
+ import { first, last, range } from 'lodash';
45
44
  import { Room } from '../../../booking-wizard/types';
46
45
  import Icon from '../icon';
47
46
  import Itinerary from '../itinerary';
@@ -61,8 +60,22 @@ import {
61
60
  enrichFiltersWithPackageAccoResults,
62
61
  enrichFiltersWithResults
63
62
  } from '../../utils/search-results-utils';
63
+ import {
64
+ ACCOMMODATION_SERVICE_TYPE,
65
+ FLIGHT_SERVICE_TYPE,
66
+ getDepartureAirportFromEntry,
67
+ getDestinationAirportFromEntry,
68
+ getPackagingRequestRoomsFromBookingRooms,
69
+ getRequestRoomsFromPackagingEntry,
70
+ GROUP_TOUR_SERVICE_TYPE,
71
+ parseHotelId,
72
+ toDateOnlyString
73
+ } from '../../utils/query-utils';
74
+ import { getRequestRoomsFromPackagingSegments, getRoomIndexFromLine, getSelectedOptionsPerRoom } from '../../utils/packaging-utils';
64
75
 
65
76
  const SearchResultsContainer: React.FC = () => {
77
+ const currentSearch = typeof window !== 'undefined' ? window.location.search : '';
78
+
66
79
  const dispatch = useDispatch();
67
80
 
68
81
  const context = useContext(SearchResultsConfigurationContext);
@@ -74,13 +87,16 @@ const SearchResultsContainer: React.FC = () => {
74
87
  packagingAccoResults,
75
88
  filteredPackagingAccoResults,
76
89
  bookingPackageDetails,
77
- entry,
78
90
  isLoading,
79
91
  filters,
80
92
  selectedSortType,
81
93
  selectedSearchResult,
82
94
  selectedPackagingAccoResultCode,
83
- flyInIsOpen
95
+ flyInIsOpen,
96
+ packagingAccoSearchDetails,
97
+ editablePackagingEntry,
98
+ transactionId,
99
+ accommodationFlyInStep
84
100
  } = useSelector((state: SearchResultsRootState) => state.searchResults);
85
101
 
86
102
  const isMobile = useMediaQuery('(max-width: 1200px)');
@@ -93,6 +109,8 @@ const SearchResultsContainer: React.FC = () => {
93
109
 
94
110
  const [itineraryOpen, setItineraryOpen] = useState(false);
95
111
 
112
+ const [selectedAccommodationSeed, setSelectedAccommodationSeed] = useState<SearchSeed | null>(null);
113
+
96
114
  const panelRef = useRef<HTMLDivElement | null>(null);
97
115
 
98
116
  const sortByTypes: SortByType[] = [
@@ -112,96 +130,43 @@ const SearchResultsContainer: React.FC = () => {
112
130
  }
113
131
  };
114
132
 
115
- const buildSearchFromEntry = (entry: EntryLight): BookingPackageRequest<BookingPackageSearchRequest> => {
116
- const from = new Date(Math.min(...entry.items.map((i) => i.startDate.getTime()))).toISOString();
117
- const to = new Date(Math.max(...entry.items.map((i) => i.endDate.getTime()))).toISOString();
118
- const rooms = entry.rooms;
119
-
120
- const hotelItem = entry.items.find((i) => i.productType === 3);
121
-
122
- let country = hotelItem ? hotelItem.countryId : null;
123
- let region = hotelItem ? hotelItem.regionId : null;
124
- let oord = hotelItem ? hotelItem.oordId : null;
125
- let city = hotelItem ? hotelItem.locationId : null;
126
- let hotel = hotelItem ? hotelItem.productCode : null;
127
-
128
- if (typeof window !== 'undefined') {
129
- window.scrollTo(0, 0);
130
- }
131
-
132
- let destinationId: number | null = null;
133
- let destinationIsCountry = false;
134
- let destinationIsRegion = false;
135
- let destinationIsOord = false;
136
- let destinationIsLocation = false;
137
-
138
- if (country) {
139
- destinationId = country;
140
- destinationIsCountry = true;
141
- } else if (region) {
142
- destinationId = region;
143
- destinationIsRegion = true;
144
- } else if (oord) {
145
- destinationId = oord;
146
- destinationIsOord = true;
147
- } else if (city) {
148
- destinationId = city;
149
- destinationIsLocation = true;
133
+ const getRequestRooms = (rooms: Room[] | null) => {
134
+ if (!rooms) {
135
+ // Fall back to 2 adults
136
+ var room = { index: 0, pax: [] } as BookingPackageRequestRoom;
137
+ range(0, 2).forEach(() => {
138
+ room.pax.push({
139
+ age: 30
140
+ } as BookingPackagePax);
141
+ });
142
+ return [room];
150
143
  }
151
144
 
152
- var searchRequest = {
153
- officeId: 1,
154
- agentId: context?.agentId,
155
- payload: {
156
- catalogueIds: context!.tideConnection.catalogueIds ?? [],
157
- serviceType:
158
- context!.searchConfiguration.qsmType === PortalQsmType.Accommodation || context!.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight
159
- ? 3
160
- : context!.searchConfiguration.qsmType === PortalQsmType.Flight
161
- ? 7
162
- : context!.searchConfiguration.qsmType === PortalQsmType.RoundTrip
163
- ? 1
164
- : 0,
165
- searchType: 0,
166
- destination: {
167
- id: Number(destinationId),
168
- isCountry: destinationIsCountry,
169
- isRegion: destinationIsRegion,
170
- isOord: destinationIsOord,
171
- isLocation: destinationIsLocation
172
- } as BookingPackageDestination,
173
- rooms: getRequestRoomsFromEntry(rooms),
174
- fromDate: from,
175
- toDate: to,
176
- earliestFromOffset: 0,
177
- latestToOffset: 0,
178
- includeFlights: true,
179
- regimeCodes: entry.items.map((i) => i.regimeCode) || [],
180
- useExactDates: true,
181
- onlyCachedResults: false,
182
- includeAllAllotments: true,
183
- productCodes: hotel ? [hotel] : []
184
- }
185
- };
145
+ const requestRooms = rooms?.map((x, i) => {
146
+ var room = { index: i, pax: [] } as BookingPackageRequestRoom;
147
+ range(0, x.adults).forEach(() => {
148
+ room.pax.push({
149
+ age: 30
150
+ } as BookingPackagePax);
151
+ });
152
+ x.childAges.forEach((x) => {
153
+ room.pax.push({
154
+ age: x
155
+ } as BookingPackagePax);
156
+ });
157
+ return room;
158
+ });
186
159
 
187
- return searchRequest;
160
+ return requestRooms;
188
161
  };
189
162
 
190
- const buildSearchFromQueryParams = (params: URLSearchParams): BookingPackageRequest<BookingPackageSearchRequest> | null => {
191
- let from = getDateFromParams(params, 'fromDate');
192
- let to = getDateFromParams(params, 'toDate');
193
- const rooms = getRoomsFromParams(params, 'rooms');
194
- let country = getNumberFromParams(params, 'country');
195
- let region = getNumberFromParams(params, 'region');
196
- let oord = getNumberFromParams(params, 'oord');
197
- let city = getNumberFromParams(params, 'location');
198
- let hotel = getNumberFromParams(params, 'hotel');
199
- let tagId = getNumberFromParams(params, 'tagId');
200
-
201
- if (!from || !to) {
202
- console.error('Missing fromDate or toDate in query params, using default values');
203
- return null;
204
- }
163
+ const buildSearchFromSeed = (seed: SearchSeed): BookingPackageRequest<BookingPackageSearchRequest> => {
164
+ const country = seed.country;
165
+ const region = seed.region;
166
+ const oord = seed.oord;
167
+ const city = seed.location;
168
+ const hotel = seed.hotel;
169
+ const tagId = seed.tagId;
205
170
 
206
171
  if (typeof window !== 'undefined') {
207
172
  window.scrollTo(0, 0);
@@ -227,18 +192,18 @@ const SearchResultsContainer: React.FC = () => {
227
192
  destinationIsLocation = true;
228
193
  }
229
194
 
230
- var searchRequest = {
195
+ return {
231
196
  officeId: 1,
232
197
  agentId: context?.agentId,
233
198
  payload: {
234
199
  catalogueIds: context!.tideConnection.catalogueIds ?? [],
235
200
  serviceType:
236
201
  context!.searchConfiguration.qsmType === PortalQsmType.Accommodation || context!.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight
237
- ? 3
202
+ ? ACCOMMODATION_SERVICE_TYPE
238
203
  : context!.searchConfiguration.qsmType === PortalQsmType.Flight
239
- ? 7
204
+ ? FLIGHT_SERVICE_TYPE
240
205
  : context!.searchConfiguration.qsmType === PortalQsmType.RoundTrip
241
- ? 1
206
+ ? GROUP_TOUR_SERVICE_TYPE
242
207
  : undefined,
243
208
  searchType: context!.searchConfiguration.qsmType === PortalQsmType.GroupTour ? 1 : 0,
244
209
  destination: {
@@ -248,19 +213,12 @@ const SearchResultsContainer: React.FC = () => {
248
213
  isOord: destinationIsOord,
249
214
  isLocation: destinationIsLocation
250
215
  } as BookingPackageDestination,
251
- rooms: getRequestRooms(rooms),
252
- fromDate: from,
253
- toDate: to,
216
+ rooms: seed.rooms,
217
+ fromDate: seed.fromDate,
218
+ toDate: seed.toDate,
254
219
  earliestFromOffset: 0,
255
220
  latestToOffset: 0,
256
- includeFlights: context!.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight ? true : false,
257
- // regimeCodes:
258
- // filters
259
- // .find((f) => f.property === 'regime')
260
- // ?.options?.filter((o) => o.isChecked)
261
- // .flatMap((o) => o.value.toString()) || [],
262
- // minPrice: filters.find((f) => f.property === 'price')?.selectedMin,
263
- // maxPrice: filters.find((f) => f.property === 'price')?.selectedMax,
221
+ includeFlights: context!.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight,
264
222
  useExactDates: context?.searchConfiguration.qsmType === PortalQsmType.GroupTour ? false : true,
265
223
  onlyCachedResults: false,
266
224
  includeAllAllotments: true,
@@ -268,86 +226,16 @@ const SearchResultsContainer: React.FC = () => {
268
226
  productTagIds: tagId ? [tagId] : []
269
227
  }
270
228
  };
271
-
272
- console.log('Built search request from query params', searchRequest);
273
-
274
- return searchRequest;
275
229
  };
276
230
 
277
- const getRequestRoomsFromEntry = (rooms: EntryRoom[] | null) => {
278
- if (!rooms) {
279
- // Fall back to 2 adults
280
- var room = { index: 0, pax: [] } as BookingPackageRequestRoom;
281
- range(0, 2).forEach(() => {
282
- room.pax.push({
283
- age: 30
284
- } as BookingPackagePax);
285
- });
286
- return [room];
287
- }
288
-
289
- const requestRooms = rooms?.map((x, i) => {
290
- var room = { index: i, pax: [] } as BookingPackageRequestRoom;
291
- x.travellers.forEach((p) => {
292
- room.pax.push({
293
- age: p.age,
294
- dateOfBirth: p.dateOfBirth
295
- } as BookingPackagePax);
296
- });
297
-
298
- return room;
299
- });
300
-
301
- return requestRooms;
302
- };
303
-
304
- const getRequestRooms = (rooms: Room[] | null) => {
305
- if (!rooms) {
306
- // Fall back to 2 adults
307
- var room = { index: 0, pax: [] } as BookingPackageRequestRoom;
308
- range(0, 2).forEach(() => {
309
- room.pax.push({
310
- age: 30
311
- } as BookingPackagePax);
312
- });
313
- return [room];
314
- }
315
-
316
- const requestRooms = rooms?.map((x, i) => {
317
- var room = { index: i, pax: [] } as BookingPackageRequestRoom;
318
- range(0, x.adults).forEach(() => {
319
- room.pax.push({
320
- age: 30
321
- } as BookingPackagePax);
322
- });
323
- x.childAges.forEach((x) => {
324
- room.pax.push({
325
- age: x
326
- } as BookingPackagePax);
327
- });
328
- return room;
329
- });
330
-
331
- return requestRooms;
332
- };
333
-
334
- const buildPackagingAccommodationRequestFromQueryParams = (params: URLSearchParams): PackagingAccommodationRequest | null => {
335
- let from = getDateFromParams(params, 'fromDate');
336
- let to = getDateFromParams(params, 'toDate');
337
- const rooms = getRoomsFromParams(params, 'rooms');
338
- let country = getNumberFromParams(params, 'country');
339
- let region = getNumberFromParams(params, 'region');
340
- let oord = getNumberFromParams(params, 'oord');
341
- let city = getNumberFromParams(params, 'location');
342
- let hotel = getNumberFromParams(params, 'hotel');
343
- let tagId = getNumberFromParams(params, 'tagId');
344
- let agentId = getNumberFromParams(params, 'agentId');
345
- let destinationAirport = getStringFromParams(params, 'destinationAirport');
346
-
347
- if (!from || !to) {
348
- console.error('Missing fromDate or toDate in query params, using default values');
349
- return null;
350
- }
231
+ const buildPackagingAccommodationRequestFromSeed = (seed: SearchSeed, currentTransactionId: string): PackagingAccommodationRequest => {
232
+ const country = seed.country;
233
+ const region = seed.region;
234
+ const oord = seed.oord;
235
+ const city = seed.location;
236
+ const hotelCode = seed.hotelCode ?? (seed.hotel ? seed.hotel.toString() : '');
237
+ const tagId = seed.tagId;
238
+ const destinationAirport = seed.destinationAirport;
351
239
 
352
240
  if (typeof window !== 'undefined') {
353
241
  window.scrollTo(0, 0);
@@ -361,32 +249,33 @@ const SearchResultsContainer: React.FC = () => {
361
249
  let destinationCode: string | null = null;
362
250
  let destinationIsAirport = false;
363
251
 
364
- if (country) {
365
- destinationId = country;
366
- destinationIsCountry = true;
367
- } else if (region) {
368
- destinationId = region;
369
- destinationIsRegion = true;
252
+ if (city) {
253
+ destinationId = city;
254
+ destinationIsLocation = true;
370
255
  } else if (oord) {
371
256
  destinationId = oord;
372
257
  destinationIsOord = true;
373
- } else if (city) {
374
- destinationId = city;
375
- destinationIsLocation = true;
258
+ } else if (region) {
259
+ destinationId = region;
260
+ destinationIsRegion = true;
261
+ } else if (country) {
262
+ destinationId = country;
263
+ destinationIsCountry = true;
376
264
  } else if (destinationAirport) {
377
265
  destinationCode = destinationAirport;
378
266
  destinationIsAirport = true;
379
267
  }
380
268
 
381
- var searchRequest = {
269
+ return {
270
+ transactionId: currentTransactionId,
382
271
  officeId: 1,
383
- agentId: agentId ?? null,
272
+ agentId: context?.agentId ?? null,
384
273
  catalogueId: context!.searchConfiguration.defaultCatalogueId ?? 0,
385
274
  searchConfigurationId: context!.searchConfiguration.id,
386
275
  language: context!.languageCode ?? 'en-GB',
387
- servicesType: 3, // accommodation
388
- fromDate: from,
389
- toDate: to,
276
+ serviceType: ACCOMMODATION_SERVICE_TYPE,
277
+ fromDate: seed.fromDate,
278
+ toDate: seed.toDate,
390
279
  destination: {
391
280
  id: Number(destinationId),
392
281
  isCountry: destinationIsCountry,
@@ -396,194 +285,313 @@ const SearchResultsContainer: React.FC = () => {
396
285
  isAirport: destinationIsAirport,
397
286
  code: destinationCode
398
287
  } as PackagingDestination,
399
- productCode: hotel ? hotel.toString() : '',
400
- rooms: getPackagingRequestRooms(rooms),
288
+ productCode: '',
289
+ rooms: getPackagingRequestRoomsFromBookingRooms(seed.rooms),
401
290
  tagIds: tagId ? [tagId] : []
402
291
  };
292
+ };
293
+
294
+ const buildSearchSeedFromQueryParams = (params: URLSearchParams): SearchSeed | null => {
295
+ const from = getDateFromParams(params, 'fromDate');
296
+ const to = getDateFromParams(params, 'toDate');
297
+ const rooms = getRoomsFromParams(params, 'rooms');
298
+ const country = getNumberFromParams(params, 'country');
299
+ const region = getNumberFromParams(params, 'region');
300
+ const oord = getNumberFromParams(params, 'oord');
301
+ const city = getNumberFromParams(params, 'location');
302
+ const hotel = getNumberFromParams(params, 'hotel');
303
+ const tagId = getNumberFromParams(params, 'tagId');
304
+ const destinationAirport = getStringFromParams(params, 'destinationAirport');
305
+ const departureAirport = getStringFromParams(params, 'departureAirport');
403
306
 
404
- console.log('Search request for packaging accommodation from query params', searchRequest);
307
+ if (!from || !to) {
308
+ return null;
309
+ }
405
310
 
406
- return searchRequest;
311
+ return {
312
+ fromDate: from,
313
+ toDate: to,
314
+ country,
315
+ region,
316
+ oord,
317
+ location: city,
318
+ hotel,
319
+ hotelCode: hotel ? hotel.toString() : null,
320
+ tagId,
321
+ destinationAirport,
322
+ departureAirport,
323
+ rooms: getRequestRooms(rooms)
324
+ };
407
325
  };
408
326
 
409
- const getPackagingRequestRooms = (rooms: Room[] | null) => {
410
- if (!rooms) {
411
- // Fall back to 2 adults
412
- var room = { index: 0, travellers: [] } as PackagingRoom;
413
- range(0, 2).forEach(() => {
414
- room.travellers.push({
415
- age: 30
416
- } as PackagingTraveller);
417
- });
418
- return [room];
419
- }
327
+ const handleConfirmHotelSwap = () => {
328
+ const updatedEntry = swapHotelInPackagingEntry();
329
+ console.log('Updated entry after hotel swap', updatedEntry);
330
+ if (!updatedEntry) return;
420
331
 
421
- const requestRooms = rooms?.map((x, i) => {
422
- var room = { index: i, travellers: [] } as PackagingRoom;
423
- range(0, x.adults).forEach(() => {
424
- room.travellers.push({
425
- age: 30
426
- } as PackagingTraveller);
427
- });
428
- x.childAges.forEach((x) => {
429
- room.travellers.push({
430
- age: x
431
- } as PackagingTraveller);
432
- });
433
- return room;
332
+ dispatch(setEditablePackagingEntry(updatedEntry));
333
+ handleFlyInToggle(false);
334
+ };
335
+
336
+ const swapHotelInPackagingEntry = (): PackagingEntry | null => {
337
+ const sourceEntry = editablePackagingEntry ?? context?.packagingEntry;
338
+ const details = packagingAccoSearchDetails;
339
+
340
+ if (!sourceEntry || !details?.length) return null;
341
+
342
+ const selectedOptionsPerRoom = getSelectedOptionsPerRoom(details);
343
+ if (!selectedOptionsPerRoom.length) return null;
344
+
345
+ const selectedHotel = details[0];
346
+
347
+ const updatedLines = sourceEntry.lines.map((line) => {
348
+ if (line.serviceType !== ACCOMMODATION_SERVICE_TYPE) {
349
+ return line;
350
+ }
351
+
352
+ // TODO: fix roomIndex
353
+ const roomIndex = getRoomIndexFromLine(line);
354
+ console.log('Processing line', line, 'with room index', roomIndex);
355
+ const selectedRoom = selectedOptionsPerRoom.find((x) => x.roomIndex === roomIndex);
356
+ const selectedOption = selectedRoom?.option;
357
+
358
+ if (!selectedOption) {
359
+ return line;
360
+ }
361
+
362
+ return {
363
+ ...line,
364
+ guid: selectedOption.guid,
365
+ productName: selectedHotel.name,
366
+ productCode: selectedHotel.code,
367
+ accommodationName: selectedOption.accommodationName,
368
+ accommodationCode: selectedOption.accommodationCode,
369
+ regimeName: selectedOption.regimeName,
370
+ regimeCode: selectedOption.regimeCode,
371
+
372
+ country: line.country
373
+ ? { ...line.country, id: selectedHotel.countryId ?? line.country.id, name: selectedHotel.countryName ?? line.country.name }
374
+ : selectedHotel.countryId
375
+ ? { id: selectedHotel.countryId, name: selectedHotel.countryName, localizations: [] }
376
+ : line.country,
377
+
378
+ region: line.region
379
+ ? { ...line.region, id: selectedHotel.regionId ?? line.region.id, name: selectedHotel.regionName ?? line.region.name }
380
+ : selectedHotel.regionId
381
+ ? { id: selectedHotel.regionId, name: selectedHotel.regionName, localizations: [] }
382
+ : line.region,
383
+
384
+ oord: line.oord
385
+ ? { ...line.oord, id: selectedHotel.oordId ?? line.oord.id, name: selectedHotel.oordName ?? line.oord.name }
386
+ : selectedHotel.oordId
387
+ ? { id: selectedHotel.oordId, name: selectedHotel.oordName, localizations: [] }
388
+ : line.oord,
389
+
390
+ location: line.location
391
+ ? { ...line.location, id: selectedHotel.locationId ?? line.location.id, name: selectedHotel.locationName ?? line.location.name }
392
+ : selectedHotel.locationId
393
+ ? { id: selectedHotel.locationId, name: selectedHotel.locationName, localizations: [] }
394
+ : line.location,
395
+
396
+ latitude: selectedHotel.latitude ?? line.latitude,
397
+ longitude: selectedHotel.longitude ?? line.longitude,
398
+
399
+ from: selectedHotel.fromDate ?? line.from,
400
+ to: selectedHotel.toDate ?? line.to,
401
+ isChanged: true
402
+ };
434
403
  });
435
404
 
436
- return requestRooms;
405
+ return {
406
+ ...sourceEntry,
407
+ lines: updatedLines
408
+ };
437
409
  };
438
410
 
411
+ const activeSearchSeed = React.useMemo(() => {
412
+ if (selectedAccommodationSeed) {
413
+ return selectedAccommodationSeed;
414
+ }
415
+
416
+ if (typeof window === 'undefined') return null;
417
+
418
+ const params = new URLSearchParams(window.location.search);
419
+ return buildSearchSeedFromQueryParams(params);
420
+ }, [selectedAccommodationSeed, currentSearch]);
421
+
439
422
  useEffect(() => {
440
423
  if (typeof document !== 'undefined') {
441
424
  document.body.classList.toggle('has-overlay', filtersOpen);
442
425
  }
443
426
  }, [filtersOpen]);
444
427
 
445
- // seperate Search
446
- useEffect(() => {
447
- const runSearch = async () => {
428
+ const runSearch = async () => {
429
+ try {
430
+ if (!context) return;
448
431
  dispatch(setIsLoading(true));
449
- try {
450
- if (!context) {
451
- return;
452
- }
453
432
 
454
- const config: TideClientConfig = {
455
- host: context.tideConnection.host,
456
- apiKey: context.tideConnection.apiKey
457
- };
433
+ const config: TideClientConfig = {
434
+ host: context.tideConnection.host,
435
+ apiKey: context.tideConnection.apiKey
436
+ };
458
437
 
459
- const params = new URLSearchParams(location.search);
460
- let entryId = getStringFromParams(params, 'entryId');
461
- let entryLight: EntryLight | null = null;
462
- // If entryId is present, we want to fetch the details of that entry and use the details to populate the search results, instead of running a search with the other query params
438
+ const seed = activeSearchSeed;
439
+ if (!seed) {
440
+ throw new Error('Invalid search parameters');
441
+ }
463
442
 
464
- let searchRequest: BookingPackageRequest<BookingPackageSearchRequest>;
443
+ const searchRequest = buildSearchFromSeed(seed);
444
+ const packageSearchResults = await search(config, searchRequest);
465
445
 
466
- if (entryId) {
467
- entryLight = await getEntryLight(config, entryId);
468
- // populate itinerary store
469
- dispatch(setEntry({ entry: entryLight }));
470
- searchRequest = buildSearchFromEntry(entryLight);
471
- } else {
472
- const rq = buildSearchFromQueryParams(params);
473
- if (!rq) {
474
- throw new Error('Invalid search parameters');
475
- }
446
+ console.log('Search results', packageSearchResults);
476
447
 
477
- searchRequest = rq;
478
- }
479
- const packageSearchResults = await search(config, searchRequest);
448
+ const enrichedFilters = enrichFiltersWithResults(packageSearchResults, context.filters, context.tags ?? []);
449
+ if (!initialFiltersSet) {
450
+ dispatch(resetFilters(enrichedFilters));
451
+ setInitialFilters(enrichedFilters);
452
+ setInitialFiltersSet(true);
453
+ }
480
454
 
481
- console.log('Search results', packageSearchResults);
455
+ dispatch(setResults(packageSearchResults));
456
+ const initialFilteredResults = applyFilters(packageSearchResults, filters, null);
457
+ dispatch(setFilteredResults(initialFilteredResults));
482
458
 
483
- const enrichedFilters = enrichFiltersWithResults(packageSearchResults, context.filters, context.tags ?? []);
484
- if (!initialFiltersSet) {
485
- dispatch(resetFilters(enrichedFilters));
486
- setInitialFilters(enrichedFilters);
487
- setInitialFiltersSet(true);
459
+ if (packageSearchResults?.length > 0) {
460
+ if (context.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight) {
461
+ dispatch(setSelectedSearchResult(packageSearchResults[0]));
488
462
  }
463
+ }
464
+ } catch (err) {
465
+ console.error('Search failed', err);
466
+ } finally {
467
+ dispatch(setIsLoading(false));
468
+ }
469
+ };
489
470
 
490
- dispatch(setResults(packageSearchResults));
491
- const initialFilteredResults = applyFilters(packageSearchResults, filters, null);
492
- dispatch(setFilteredResults(initialFilteredResults));
493
-
494
- if (packageSearchResults?.length > 0) {
495
- if (entryId) {
496
- const matching = packageSearchResults.find((r) => r.productId === entry?.id);
497
-
498
- if (matching) {
499
- dispatch(setSelectedSearchResult(matching));
500
- }
501
- } else {
502
- if (context.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight) {
503
- dispatch(setSelectedSearchResult(packageSearchResults[0]));
504
- }
505
- }
506
- }
471
+ const runStartTransaction = async (): Promise<string | null> => {
472
+ try {
473
+ if (!context) return null;
507
474
 
508
- dispatch(setIsLoading(false));
509
- } catch (err) {
510
- console.error('Search failed', err);
511
- dispatch(setIsLoading(false));
512
- }
513
- };
475
+ const config: TideClientConfig = {
476
+ host: context.tideConnection.host,
477
+ apiKey: context.tideConnection.apiKey
478
+ };
479
+
480
+ const transaction = await startTransaction(config);
481
+ console.log('Transaction started', transaction);
482
+
483
+ dispatch(setTransactionId(transaction.transactionId));
484
+
485
+ return transaction.transactionId;
486
+ } catch (err) {
487
+ console.error('Transaction failed', err);
488
+ return null;
489
+ }
490
+ };
514
491
 
515
- const runHotelSearch = async () => {
492
+ const runHotelSearch = async (currentTransactionId: string, seed: SearchSeed) => {
493
+ try {
494
+ if (!context) return;
516
495
  dispatch(setIsLoading(true));
517
- try {
518
- if (!context) {
519
- return;
520
- }
521
496
 
522
- const config: TideClientConfig = {
523
- host: context.tideConnection.host,
524
- apiKey: context.tideConnection.apiKey
525
- };
497
+ const config: TideClientConfig = {
498
+ host: context.tideConnection.host,
499
+ apiKey: context.tideConnection.apiKey
500
+ };
526
501
 
527
- const params = new URLSearchParams(location.search);
502
+ let searchRequest: PackagingAccommodationRequest = buildPackagingAccommodationRequestFromSeed(seed, currentTransactionId);
503
+ searchRequest.portalId = context.portalId;
504
+ searchRequest.agentId = context.agentId;
528
505
 
529
- let searchRequest: PackagingAccommodationRequest;
506
+ console.log('Packaging accommodation search request', searchRequest);
507
+ const packageAccoSearchResults = await searchPackagingAccommodations(config, searchRequest);
530
508
 
531
- const rq = buildPackagingAccommodationRequestFromQueryParams(params);
532
- if (!rq) {
533
- throw new Error('Invalid search parameters');
534
- }
509
+ const enrichedFilters = enrichFiltersWithPackageAccoResults(packageAccoSearchResults, context.filters, context.tags ?? []);
510
+ if (!initialFiltersSet) {
511
+ dispatch(resetFilters(enrichedFilters));
512
+ setInitialFilters(enrichedFilters);
513
+ setInitialFiltersSet(true);
514
+ }
535
515
 
536
- searchRequest = rq;
537
- searchRequest.portalId = context.portalId;
538
- searchRequest.agentId = context.agentId;
516
+ dispatch(setPackagingAccoResults(packageAccoSearchResults));
517
+ const initialFilteredResults = applyFiltersToPackageAccoResults(packageAccoSearchResults, filters, null);
518
+ dispatch(setFilteredPackagingAccoResults(initialFilteredResults));
539
519
 
540
- const packageAccoSearchResults = await searchPackagingAccommodations(config, searchRequest);
520
+ dispatch(setIsLoading(false));
521
+ } catch (err) {
522
+ console.error('Search failed', err);
523
+ dispatch(setIsLoading(false));
524
+ }
525
+ };
541
526
 
542
- console.log('package Acco SearchResults', packageAccoSearchResults);
527
+ const runAccommodationFlow = async (seed: SearchSeed) => {
528
+ if (!context || context.showMockup) return;
543
529
 
544
- const enrichedFilters = enrichFiltersWithPackageAccoResults(packageAccoSearchResults, context.filters, context.tags ?? []);
545
- if (!initialFiltersSet) {
546
- dispatch(resetFilters(enrichedFilters));
547
- setInitialFilters(enrichedFilters);
548
- setInitialFiltersSet(true);
549
- }
530
+ let currentTransactionId = context?.packagingEntry?.transactionId || transactionId;
531
+ console.log('Current transaction ID', currentTransactionId);
532
+ if (!currentTransactionId) {
533
+ dispatch(setIsLoading(true));
534
+ currentTransactionId = await runStartTransaction();
535
+ }
550
536
 
551
- dispatch(setPackagingAccoResults(packageAccoSearchResults));
552
- const initialFilteredResults = applyFiltersToPackageAccoResults(packageAccoSearchResults, filters, null);
553
- dispatch(setFilteredPackagingAccoResults(initialFilteredResults));
537
+ if (!currentTransactionId) {
538
+ dispatch(setIsLoading(false));
539
+ return;
540
+ }
554
541
 
555
- dispatch(setIsLoading(false));
556
- } catch (err) {
557
- console.error('Search failed', err);
558
- dispatch(setIsLoading(false));
559
- }
560
- };
542
+ await runHotelSearch(currentTransactionId, seed);
543
+ };
561
544
 
562
- if (!context?.showMockup) {
563
- if (
564
- context?.searchConfiguration.qsmType === PortalQsmType.GroupTour ||
565
- (context?.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight && !context.searchConfiguration.enableManualPackaging)
566
- ) {
567
- runSearch();
568
- }
569
- if (context?.searchConfiguration.qsmType === PortalQsmType.Accommodation) {
570
- runHotelSearch();
545
+ // separate Search
546
+ useEffect(() => {
547
+ if (
548
+ context?.searchConfiguration.qsmType === PortalQsmType.GroupTour ||
549
+ (context?.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight && !context.searchConfiguration.enableManualPackaging)
550
+ ) {
551
+ runSearch();
552
+ }
553
+
554
+ if (context?.searchConfiguration.qsmType === PortalQsmType.Accommodation) {
555
+ const seed = activeSearchSeed;
556
+ if (seed) {
557
+ runAccommodationFlow(seed);
571
558
  }
572
- if (context?.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight && context.searchConfiguration.enableManualPackaging) {
573
- // Manual packaging flow.
574
- if (context.searchConfiguration.allowAccommodations) {
575
- runHotelSearch();
576
- }
559
+ }
560
+
561
+ if (
562
+ context?.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight &&
563
+ context.searchConfiguration.enableManualPackaging &&
564
+ context.searchConfiguration.allowAccommodations &&
565
+ !context?.packagingEntry
566
+ ) {
567
+ const seed = activeSearchSeed;
568
+ if (seed) {
569
+ runAccommodationFlow(seed);
577
570
  }
578
571
  }
579
- }, [location.search]);
572
+ }, [
573
+ location.search,
574
+ context?.showMockup,
575
+ context?.searchConfiguration.qsmType,
576
+ context?.searchConfiguration.enableManualPackaging,
577
+ context?.searchConfiguration.allowAccommodations,
578
+ context?.packagingEntry?.transactionId,
579
+ activeSearchSeed
580
+ ]);
580
581
 
581
- // Seperate detailsCall
582
+ useEffect(() => {
583
+ if (context?.packagingEntry) {
584
+ console.log('original packaging entry from context', context.packagingEntry);
585
+ dispatch(setEditablePackagingEntry(structuredClone(context.packagingEntry)));
586
+ dispatch(setTransactionId(context.packagingEntry.transactionId));
587
+ }
588
+ }, [context?.packagingEntry]);
589
+
590
+ // separate detailsCall
582
591
  useEffect(() => {
583
592
  const fetchDetails = async () => {
584
- setDetailsIsLoading(true);
585
- console.log('Fetching details for selected search result', selectedSearchResult);
586
593
  if (!selectedSearchResult || !context) return;
594
+ setDetailsIsLoading(true);
587
595
  if (context?.searchConfiguration.qsmType === PortalQsmType.Accommodation || context?.searchConfiguration.qsmType === PortalQsmType.GroupTour) {
588
596
  handleFlyInToggle(true);
589
597
  }
@@ -600,15 +608,13 @@ const SearchResultsContainer: React.FC = () => {
600
608
  return;
601
609
  }
602
610
 
603
- const params = new URLSearchParams(location.search);
604
- let entryId = getStringFromParams(params, 'entryId');
611
+ let requestRooms: BookingPackageRequestRoom[];
605
612
 
606
- let requestRooms;
607
- if (entry && entryId) {
608
- requestRooms = getRequestRoomsFromEntry(entry.rooms);
613
+ if (context?.packagingEntry) {
614
+ requestRooms = getRequestRoomsFromPackagingEntry(context.packagingEntry);
609
615
  } else {
610
- const rooms = getRoomsFromParams(params, 'rooms');
611
- requestRooms = getRequestRooms(rooms);
616
+ const seed = activeSearchSeed;
617
+ requestRooms = seed?.rooms?.length ? seed.rooms : getRequestRooms(null);
612
618
  }
613
619
 
614
620
  const detailsRequest: BookingPackageRequest<BookingPackageDetailsRequest> = {
@@ -632,21 +638,9 @@ const SearchResultsContainer: React.FC = () => {
632
638
  agentId: context.agentId
633
639
  };
634
640
 
635
- if (entry && entryId) {
636
- requestRooms = getRequestRoomsFromEntry(entry.rooms);
637
- const detailsResponse = await details(config, detailsRequest);
638
- console.log('Details:', detailsResponse);
639
- dispatch(setBookingPackageDetails({ details: detailsResponse?.payload }));
640
- } else {
641
- // const detailsWLResponse = await detailsWL(config, detailsRequest);
642
- // console.log('Details with entryLight:', detailsWLResponse);
643
- // dispatch(setBookingPackageDetails({ details: detailsWLResponse?.payload?.bookingPackage }));
644
- // dispatch(setEntry({ entry: detailsWLResponse?.payload?.entry }));
645
-
646
- const detailsResponse = await details(config, detailsRequest);
647
- dispatch(setBookingPackageDetails({ details: detailsResponse?.payload }));
648
- setDetailsIsLoading(false);
649
- }
641
+ const detailsResponse = await details(config, detailsRequest);
642
+ dispatch(setBookingPackageDetails({ details: detailsResponse?.payload }));
643
+ setDetailsIsLoading(false);
650
644
  } catch (err) {
651
645
  console.error('Failed to fetch package details', err);
652
646
  setDetailsIsLoading(false);
@@ -655,8 +649,12 @@ const SearchResultsContainer: React.FC = () => {
655
649
 
656
650
  const fetchPackagingAccoSearchDetails = async () => {
657
651
  if (!selectedPackagingAccoResultCode || !context) return;
658
-
659
- if (context?.searchConfiguration.qsmType === PortalQsmType.Accommodation || context?.searchConfiguration.qsmType === PortalQsmType.GroupTour) {
652
+ setDetailsIsLoading(true);
653
+ if (
654
+ context?.searchConfiguration.qsmType === PortalQsmType.Accommodation ||
655
+ context?.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight ||
656
+ context?.searchConfiguration.qsmType === PortalQsmType.GroupTour
657
+ ) {
660
658
  handleFlyInToggle(true);
661
659
  }
662
660
 
@@ -666,19 +664,15 @@ const SearchResultsContainer: React.FC = () => {
666
664
  apiKey: context.tideConnection.apiKey
667
665
  };
668
666
 
669
- console.log('selectedPackagingAccoResultCode', selectedPackagingAccoResultCode);
670
667
  const selectedItem = packagingAccoResults.find((r) => r.code === selectedPackagingAccoResultCode);
671
- console.log('Selected packaging acco item', selectedItem);
672
668
  if (!selectedItem) {
673
669
  // TODO: handle this case better, show an error message to the user
674
670
  return;
675
671
  }
676
672
 
677
- const params = new URLSearchParams(location.search);
678
- const rooms = getRoomsFromParams(params, 'rooms');
679
- let tagId = getNumberFromParams(params, 'tagId');
680
-
681
- let destinationAirport = getStringFromParams(params, 'destinationAirport');
673
+ const seed = activeSearchSeed;
674
+ const tagId = seed?.tagId ?? null;
675
+ const destinationAirport = seed?.destinationAirport ?? null;
682
676
 
683
677
  let destinationId: number | null = null;
684
678
  let destinationIsCountry = false;
@@ -706,6 +700,7 @@ const SearchResultsContainer: React.FC = () => {
706
700
  }
707
701
 
708
702
  const detailSearchRequest: PackagingAccommodationRequest = {
703
+ transactionId: transactionId ?? '',
709
704
  officeId: 1,
710
705
  portalId: context.portalId,
711
706
  agentId: context.agentId,
@@ -713,7 +708,7 @@ const SearchResultsContainer: React.FC = () => {
713
708
  searchConfigurationId: context!.searchConfiguration.id,
714
709
  vendorConfigurationId: selectedItem.vendorId,
715
710
  language: context!.languageCode ?? 'en-GB',
716
- serviceType: 3,
711
+ serviceType: ACCOMMODATION_SERVICE_TYPE,
717
712
  fromDate: selectedItem.fromDate,
718
713
  toDate: selectedItem.toDate,
719
714
  destination: {
@@ -726,15 +721,17 @@ const SearchResultsContainer: React.FC = () => {
726
721
  code: destinationCode
727
722
  } as PackagingDestination,
728
723
  productCode: selectedItem.code ? selectedItem.code : '',
729
- rooms: getPackagingRequestRooms(rooms),
724
+ rooms: getPackagingRequestRoomsFromBookingRooms(seed?.rooms ?? null),
730
725
  tagIds: tagId ? [tagId] : []
731
726
  };
732
727
 
733
728
  const packageAccoSearchDetails = await searchPackagingAccommodations(config, detailSearchRequest);
734
729
  console.log('Packaging Acco Search details', packageAccoSearchDetails);
735
730
  dispatch(setPackagingAccoSearchDetails(packageAccoSearchDetails));
731
+ setDetailsIsLoading(false);
736
732
  } catch (err) {
737
733
  console.error('Failed to fetch package details', err);
734
+ setDetailsIsLoading(false);
738
735
  }
739
736
  };
740
737
 
@@ -744,6 +741,7 @@ const SearchResultsContainer: React.FC = () => {
744
741
  if (selectedPackagingAccoResultCode) {
745
742
  fetchPackagingAccoSearchDetails();
746
743
  }
744
+ dispatch(setAccommodationFlyInStep('details'));
747
745
  }, [selectedSearchResult, selectedPackagingAccoResultCode]);
748
746
 
749
747
  useEffect(() => {
@@ -756,6 +754,53 @@ const SearchResultsContainer: React.FC = () => {
756
754
  }
757
755
  }, [filters, results, packagingAccoResults, selectedSortType]);
758
756
 
757
+ useEffect(() => {
758
+ setInitialFiltersSet(false);
759
+ }, [activeSearchSeed]);
760
+
761
+ const handleEditAccommodation = async (segments: PackagingEntryLine[]) => {
762
+ const sourceEntry = editablePackagingEntry ?? context?.packagingEntry;
763
+ if (!sourceEntry) return;
764
+
765
+ const seed = buildSearchSeedFromAccommodationSegments(sourceEntry, segments);
766
+ if (!seed) return;
767
+
768
+ setDetailsIsLoading(true);
769
+
770
+ setSelectedAccommodationSeed(seed);
771
+ dispatch(setAccommodationFlyInStep('results'));
772
+ handleFlyInToggle(true);
773
+
774
+ await runAccommodationFlow(seed);
775
+ setDetailsIsLoading(false);
776
+ };
777
+
778
+ const buildSearchSeedFromAccommodationSegments = (entry: PackagingEntry, segments: PackagingEntryLine[]): SearchSeed | null => {
779
+ if (!segments?.length) return null;
780
+
781
+ const sortedSegments = [...segments].sort((a, b) => new Date(a.from).getTime() - new Date(b.from).getTime());
782
+
783
+ const firstSegment = first(sortedSegments);
784
+ const lastSegment = last(sortedSegments);
785
+
786
+ if (!firstSegment || !lastSegment) return null;
787
+
788
+ return {
789
+ fromDate: toDateOnlyString(firstSegment.from),
790
+ toDate: toDateOnlyString(lastSegment.to),
791
+ country: firstSegment.country?.id ?? null,
792
+ region: firstSegment.region?.id ?? null,
793
+ oord: firstSegment.oord?.id ?? null,
794
+ location: firstSegment.location?.id ?? null,
795
+ hotel: parseHotelId(firstSegment),
796
+ hotelCode: firstSegment.productCode ?? null,
797
+ tagId: null,
798
+ destinationAirport: getDestinationAirportFromEntry(entry.lines ?? []),
799
+ departureAirport: getDepartureAirportFromEntry(entry.lines ?? []),
800
+ rooms: getRequestRoomsFromPackagingSegments(entry, sortedSegments)
801
+ };
802
+ };
803
+
759
804
  return (
760
805
  <div id="tide-booking" className="search__bg">
761
806
  {context && (
@@ -790,7 +835,12 @@ const SearchResultsContainer: React.FC = () => {
790
835
  />
791
836
  )}
792
837
  {context.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight && (
793
- <Itinerary isOpen={itineraryOpen} handleSetIsOpen={() => setItineraryOpen(!itineraryOpen)} isLoading={isLoading} />
838
+ <Itinerary
839
+ isOpen={itineraryOpen}
840
+ handleSetIsOpen={() => setItineraryOpen(!itineraryOpen)}
841
+ isLoading={isLoading}
842
+ onEditAccommodation={handleEditAccommodation}
843
+ />
794
844
  )}
795
845
  {/* ---------------- Results ---------------- */}
796
846
  <div className="search__results">
@@ -826,7 +876,7 @@ const SearchResultsContainer: React.FC = () => {
826
876
  )}
827
877
  <div className="search__result-row">
828
878
  <span className="search__result-row-text">
829
- {!isLoading && (
879
+ {!isLoading && !context.packagingEntry && (
830
880
  <>
831
881
  {((context.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight &&
832
882
  context.searchConfiguration.enableManualPackaging) ||
@@ -838,7 +888,7 @@ const SearchResultsContainer: React.FC = () => {
838
888
  </>
839
889
  )}
840
890
  </span>
841
- {!isMobile && sortByTypes && sortByTypes.length > 0 && (
891
+ {!context.packagingEntry && !isMobile && sortByTypes && sortByTypes.length > 0 && (
842
892
  <div className="search__result-row-filter">
843
893
  <ItemPicker
844
894
  items={sortByTypes}
@@ -855,21 +905,29 @@ const SearchResultsContainer: React.FC = () => {
855
905
  </div>
856
906
 
857
907
  <div className="search__results__wrapper">
858
- {context.showTabViews && <TabViews />}
908
+ {context.showTabViews &&
909
+ (context.searchConfiguration.qsmType === PortalQsmType.GroupTour ||
910
+ context.searchConfiguration.qsmType === PortalQsmType.Accommodation) && <TabViews />}
859
911
 
860
912
  {context.showRoundTripResults && context.showMockup && <RoundTripResults />}
861
913
 
862
914
  {context.searchConfiguration.qsmType === PortalQsmType.GroupTour && <GroupTourResults isLoading={isLoading} />}
863
915
 
864
916
  {context.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight &&
917
+ !context.packagingEntry &&
865
918
  context.showFlightResults &&
866
919
  bookingPackageDetails?.outwardFlights && <FlightResults flights={bookingPackageDetails?.outwardFlights} isDeparture={true} />}
867
920
 
868
- {context.showHotelAccommodationResults && <HotelAccommodationResults isLoading={isLoading} />}
921
+ {context.showHotelAccommodationResults && !context.packagingEntry && <HotelAccommodationResults isLoading={isLoading} />}
869
922
 
870
923
  {context.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight &&
924
+ !context.packagingEntry &&
871
925
  context.showFlightResults &&
872
926
  bookingPackageDetails?.returnFlights && <FlightResults flights={bookingPackageDetails?.returnFlights} isDeparture={false} />}
927
+
928
+ {context.searchConfiguration.qsmType === PortalQsmType.AccommodationAndFlight && context.packagingEntry && (
929
+ <span>TODO: Show Full Itinerary here</span>
930
+ )}
873
931
  </div>
874
932
  </div>
875
933
  {/* <button onClick={() => handleFlyInToggle(!flyInIsOpen)}>Toggle FlyIn</button> */}
@@ -878,8 +936,11 @@ const SearchResultsContainer: React.FC = () => {
878
936
  srpType={context.searchConfiguration.qsmType}
879
937
  isOpen={flyInIsOpen}
880
938
  setIsOpen={handleFlyInToggle}
939
+ handleConfirm={() => handleConfirmHotelSwap()}
881
940
  onPanelRef={(el) => (panelRef.current = el)}
882
941
  detailsLoading={detailsIsLoading}
942
+ accommodationStep={accommodationFlyInStep}
943
+ isPackageEditFlow={!!context.packagingEntry}
883
944
  />
884
945
  </>
885
946
  )}