@qite/tide-booking-component 1.4.103 → 1.4.104

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 (31) hide show
  1. package/build/build-cjs/index.js +2167 -1400
  2. package/build/build-cjs/src/search-results/components/filters/filters.d.ts +2 -0
  3. package/build/build-cjs/src/search-results/components/hotel/hotel-accommodation-results.d.ts +1 -0
  4. package/build/build-cjs/src/search-results/store/search-results-selectors.d.ts +424 -0
  5. package/build/build-cjs/src/search-results/store/search-results-slice.d.ts +27 -8
  6. package/build/build-cjs/src/search-results/types.d.ts +14 -2
  7. package/build/build-cjs/src/search-results/utils/search-results-utils.d.ts +8 -6
  8. package/build/build-cjs/src/shared/components/flyin/flyin.d.ts +3 -3
  9. package/build/build-cjs/src/shared/components/flyin/packaging-flights-flyin.d.ts +7 -0
  10. package/build/build-esm/index.js +2152 -1395
  11. package/build/build-esm/src/search-results/components/filters/filters.d.ts +2 -0
  12. package/build/build-esm/src/search-results/components/hotel/hotel-accommodation-results.d.ts +1 -0
  13. package/build/build-esm/src/search-results/store/search-results-selectors.d.ts +424 -0
  14. package/build/build-esm/src/search-results/store/search-results-slice.d.ts +27 -8
  15. package/build/build-esm/src/search-results/types.d.ts +14 -2
  16. package/build/build-esm/src/search-results/utils/search-results-utils.d.ts +8 -6
  17. package/build/build-esm/src/shared/components/flyin/flyin.d.ts +3 -3
  18. package/build/build-esm/src/shared/components/flyin/packaging-flights-flyin.d.ts +7 -0
  19. package/package.json +1 -1
  20. package/src/booking-wizard/features/flight-options/index.tsx +6 -2
  21. package/src/search-results/components/filters/filters.tsx +8 -9
  22. package/src/search-results/components/hotel/hotel-accommodation-results.tsx +81 -24
  23. package/src/search-results/components/search-results-container/search-results-container.tsx +118 -102
  24. package/src/search-results/store/search-results-selectors.ts +73 -0
  25. package/src/search-results/store/search-results-slice.ts +94 -14
  26. package/src/search-results/types.ts +14 -2
  27. package/src/search-results/utils/search-results-utils.ts +310 -58
  28. package/src/shared/components/flyin/flyin.tsx +102 -19
  29. package/src/shared/components/flyin/packaging-flights-flyin.tsx +164 -0
  30. package/styles/components/_flyin.scss +16 -0
  31. package/styles/components/_search.scss +4 -1
@@ -1,6 +1,9 @@
1
- import { BookingPackageItem, PackagingAccommodationResponse } from '@qite/tide-client';
1
+ import { BookingPackageItem, PackagingAccommodationResponse, PackagingFlightResponse } from '@qite/tide-client';
2
2
  import { Filter, SortByType, TideTag } from '../types';
3
- import { first, flatMap } from 'lodash';
3
+ import { filter, flatMap, orderBy } from 'lodash';
4
+ import { getArrivalSegment, getDepartureRangeName, getDepartureSegment, getNumberOfStops } from './flight-utils';
5
+ import { DepartureRange } from '../../shared/types';
6
+ import { durationInTicksInMinutes, rangeFromDateTimeInMinutes } from '../../shared/utils/localization-util';
4
7
 
5
8
  export const enrichFiltersWithResults = (results: BookingPackageItem[], filters: Filter[] | undefined, tags: TideTag[]): Filter[] => {
6
9
  if (!results || results.length === 0 || !filters) {
@@ -79,76 +82,237 @@ export const enrichFiltersWithResults = (results: BookingPackageItem[], filters:
79
82
  });
80
83
  };
81
84
 
82
- export const enrichFiltersWithPackageAccoResults = (results: PackagingAccommodationResponse[], filters: Filter[] | undefined, tags: TideTag[]): Filter[] => {
83
- if (!results || results.length === 0 || !filters) {
84
- return filters ?? [];
85
+ export const enrichFiltersWithPackageAccoResults = (results: PackagingAccommodationResponse[], tags: TideTag[]): Filter[] => {
86
+ const filters: Filter[] = [];
87
+ if (!results || results.length === 0) {
88
+ return filters;
85
89
  }
86
90
 
87
- return filters.map((filter) => {
88
- let updatedFilter = { ...filter };
89
-
90
- if (filter.property === 'price' && (filter.min == null || filter.max == null)) {
91
- const prices = results.map((r) => r.price ?? 0).filter((p) => p > 0);
92
- if (prices.length > 0) {
93
- updatedFilter.min = Math.floor(Math.min(...prices));
94
- updatedFilter.max = Math.ceil(Math.max(...prices));
95
- }
91
+ const regimeFilter: Filter = {
92
+ property: 'regime',
93
+ label: 'Regime',
94
+ type: 'checkbox',
95
+ options: [],
96
+ isFrontendFilter: true
97
+ };
98
+ const map = new Map<string, { name?: string; code: string }>();
99
+
100
+ results.forEach((r) => {
101
+ const rooms = flatMap(r.rooms);
102
+ if (rooms) {
103
+ rooms.map((room) => {
104
+ room.options.map((option) => {
105
+ if (option.regimeCode) {
106
+ map.set(option.regimeCode, {
107
+ name: option.regimeName,
108
+ code: option.regimeCode
109
+ });
110
+ }
111
+ });
112
+ });
96
113
  }
114
+ });
97
115
 
98
- if (filter.property === 'accommodation') {
99
- const map = new Map<string, { name?: string; code: string }>();
116
+ regimeFilter.options = Array.from(map.values()).map((regime) => ({
117
+ label: regime.name ?? regime.code,
118
+ value: regime.code,
119
+ isChecked: false
120
+ }));
121
+ filters.push(regimeFilter);
122
+
123
+ const priceFilter: Filter = {
124
+ property: 'price',
125
+ label: 'Prijs',
126
+ type: 'slider',
127
+ isFrontendFilter: true
128
+ };
129
+ const prices = results.map((r) => r.price ?? 0).filter((p) => p > 0);
130
+ priceFilter.min = Math.floor(Math.min(...prices));
131
+ priceFilter.max = Math.ceil(Math.max(...prices));
132
+
133
+ filters.push(priceFilter);
134
+
135
+ return filters;
136
+ };
100
137
 
101
- results.forEach((r) => {
102
- const rooms = flatMap(r.rooms);
103
- if (rooms) {
104
- rooms.map((room) => {
105
- room.options.map((option) => {
106
- if (option.accommodationCode) {
107
- map.set(option.accommodationCode, {
108
- name: option.accommodationName,
109
- code: option.accommodationCode
110
- });
111
- }
112
- });
113
- });
114
- }
138
+ export const enrichFiltersWithPackageFlightResults = (results: PackagingFlightResponse[], tags: TideTag[], translations: any): Filter[] => {
139
+ const filters: Filter[] = [];
140
+ if (!results || results.length === 0) {
141
+ return filters;
142
+ }
143
+
144
+ // Airlines
145
+ const airlinesFilter: Filter = {
146
+ label: 'Airlines',
147
+ property: 'airline',
148
+ type: 'checkbox',
149
+ isFrontendFilter: true,
150
+ options: []
151
+ };
152
+ const airlinesFilterMap = new Map<string, { name?: string; code: string }>();
153
+
154
+ results.map((r) => {
155
+ const airlineCode = r.airlineCode;
156
+ const airlineName = r.airlineName;
157
+ if (airlineCode && airlineName) {
158
+ airlinesFilterMap.set(airlineCode, {
159
+ name: airlineName,
160
+ code: airlineCode
115
161
  });
162
+ }
163
+ });
116
164
 
117
- updatedFilter.options = Array.from(map.values()).map((accommodation) => ({
118
- label: accommodation.name ?? accommodation.code,
119
- value: accommodation.code,
120
- isChecked: false
121
- }));
165
+ airlinesFilter.options = Array.from(airlinesFilterMap.values()).map((airline) => ({
166
+ label: airline.name ?? airline.code,
167
+ value: airline.code,
168
+ isChecked: false
169
+ }));
170
+
171
+ filters.push(airlinesFilter);
172
+
173
+ // Number of stops
174
+ const stopsFilter: Filter = {
175
+ label: 'Number of Stops',
176
+ property: 'numberOfStops',
177
+ type: 'checkbox',
178
+ isFrontendFilter: true,
179
+ options: []
180
+ };
181
+ const stopsMap = new Map<number, { numberOfStops: number }>();
182
+
183
+ results.map((result) => {
184
+ let numberOfStops = getNumberOfStops(result.outward);
185
+ if (!stopsMap.has(numberOfStops)) {
186
+ stopsMap.set(numberOfStops, { numberOfStops });
122
187
  }
188
+ });
123
189
 
124
- if (filter.property === 'regime') {
125
- const map = new Map<string, { name?: string; code: string }>();
190
+ stopsFilter.options = Array.from(stopsMap.values()).map((stop) => ({
191
+ label: `${stop.numberOfStops == 0 ? 'direct' : stop.numberOfStops + ` Stop${stop.numberOfStops !== 1 ? 's' : ''}`}`,
192
+ value: stop.numberOfStops,
193
+ isChecked: false
194
+ }));
195
+
196
+ filters.push(stopsFilter);
197
+
198
+ // Departure range
199
+ const departureRangeFilter: Filter = {
200
+ label: 'Departure Range',
201
+ property: 'departureRange',
202
+ type: 'checkbox',
203
+ isFrontendFilter: true,
204
+ options: []
205
+ };
206
+ const departureRangeMap = new Map<DepartureRange, DepartureRange>();
207
+ results.map((result) => {
208
+ const departureRange = rangeFromDateTimeInMinutes(getDepartureSegment(result.outward)?.departureDateTime);
209
+ if (!departureRangeMap.has(departureRange)) {
210
+ departureRangeMap.set(departureRange, departureRange);
211
+ }
212
+ });
126
213
 
127
- results.forEach((r) => {
128
- const rooms = flatMap(r.rooms);
129
- if (rooms) {
130
- rooms.map((room) => {
131
- room.options.map((option) => {
132
- if (option.regimeCode) {
133
- map.set(option.regimeCode, {
134
- name: option.regimeName,
135
- code: option.regimeCode
136
- });
137
- }
138
- });
139
- });
140
- }
214
+ departureRangeFilter.options = orderBy(Array.from(departureRangeMap.values()), ['id'], ['asc']).map((range) => ({
215
+ label: getDepartureRangeName(translations, range),
216
+ value: range,
217
+ isChecked: false
218
+ }));
219
+
220
+ filters.push(departureRangeFilter);
221
+
222
+ // Departure Airport
223
+ const departureAirportFilter: Filter = {
224
+ label: 'Departure Airport',
225
+ property: 'departureAirport',
226
+ type: 'checkbox',
227
+ isFrontendFilter: true,
228
+ options: []
229
+ };
230
+ const departureAirportsMap = new Map<string, { name?: string; code: string }>();
231
+
232
+ results.map((result) => {
233
+ const departureSegment = getDepartureSegment(result.outward);
234
+ const departureAirport = departureSegment?.departureAirportCode;
235
+ if (departureAirport && !departureAirportsMap.has(departureAirport)) {
236
+ departureAirportsMap.set(departureAirport, {
237
+ name: departureSegment?.departureAirportName + ' (' + departureAirport + ')',
238
+ code: departureAirport
141
239
  });
142
-
143
- updatedFilter.options = Array.from(map.values()).map((regime) => ({
144
- label: regime.name ?? regime.code,
145
- value: regime.code,
146
- isChecked: false
147
- }));
148
240
  }
241
+ });
149
242
 
150
- return updatedFilter;
243
+ departureAirportFilter.options = Array.from(departureAirportsMap.values()).map((airport) => ({
244
+ label: airport.name ?? airport.code,
245
+ value: airport.code,
246
+ isChecked: false
247
+ }));
248
+
249
+ filters.push(departureAirportFilter);
250
+
251
+ // Arrival Airport
252
+ const arrivalAirportFilter: Filter = {
253
+ label: 'Arrival Airport',
254
+ property: 'arrivalAirport',
255
+ type: 'checkbox',
256
+ isFrontendFilter: true,
257
+ options: []
258
+ };
259
+ const arrivalAirportsMap = new Map<string, { name?: string; code: string }>();
260
+
261
+ results.map((result) => {
262
+ const arrivalSegment = getArrivalSegment(result.outward);
263
+ const arrivalAirport = arrivalSegment?.arrivalAirportCode;
264
+ if (arrivalAirport && !arrivalAirportsMap.has(arrivalAirport)) {
265
+ arrivalAirportsMap.set(arrivalAirport, {
266
+ name: arrivalSegment?.arrivalAirportName + ' (' + arrivalAirport + ')',
267
+ code: arrivalAirport
268
+ });
269
+ }
151
270
  });
271
+
272
+ arrivalAirportFilter.options = Array.from(arrivalAirportsMap.values()).map((airport) => ({
273
+ label: airport.name ?? airport.code,
274
+ value: airport.code,
275
+ isChecked: false
276
+ }));
277
+
278
+ filters.push(arrivalAirportFilter);
279
+
280
+ // Price
281
+ const priceFilter: Filter = {
282
+ label: 'Price',
283
+ property: 'price',
284
+ type: 'slider',
285
+ isFrontendFilter: true
286
+ };
287
+
288
+ const prices = results.map((r) => r.price ?? 0).filter((p) => p > 0);
289
+ if (prices.length > 0) {
290
+ priceFilter.min = Math.floor(Math.min(...prices));
291
+ priceFilter.max = Math.ceil(Math.max(...prices));
292
+ }
293
+
294
+ filters.push(priceFilter);
295
+
296
+ // Travel duration
297
+ const travelDurationFilter: Filter = {
298
+ label: 'Travel Duration',
299
+ property: 'travelDuration',
300
+ type: 'slider',
301
+ isFrontendFilter: true
302
+ };
303
+
304
+ const minTravelTimeDuration = Math.min(...results.map((result) => result.outward.durationInTicks));
305
+ const maxTravelTimeDuration = Math.max(...results.map((result) => result.outward.durationInTicks));
306
+ const minTravelTimeValue = durationInTicksInMinutes(minTravelTimeDuration);
307
+ const maxTravelTimeValue = durationInTicksInMinutes(maxTravelTimeDuration);
308
+ if (minTravelTimeValue != null && maxTravelTimeValue != null) {
309
+ travelDurationFilter.min = minTravelTimeValue;
310
+ travelDurationFilter.max = maxTravelTimeValue;
311
+ }
312
+
313
+ filters.push(travelDurationFilter);
314
+
315
+ return filters;
152
316
  };
153
317
 
154
318
  export const applyFilters = (results: BookingPackageItem[], filters: Filter[], sortBy: SortByType | null) => {
@@ -249,3 +413,91 @@ export const applyFiltersToPackageAccoResults = (results: PackagingAccommodation
249
413
  return 0;
250
414
  });
251
415
  };
416
+
417
+ export const applyFiltersToPackageFlightResults = (results: PackagingFlightResponse[], filters: Filter[], sortBy: SortByType | null) => {
418
+ const filtered = results.filter((result) => {
419
+ return filters.every((filter) => {
420
+ if (!filter.isFrontendFilter) return true;
421
+
422
+ // Airline
423
+ if (filter.property === 'airline') {
424
+ const selected = filter.options?.filter((o) => o.isChecked).map((o) => o.value);
425
+ if (!selected || selected.length === 0) return true;
426
+ return selected.includes(result.airlineCode);
427
+ }
428
+
429
+ // Stops
430
+ if (filter.property === 'numberOfStops') {
431
+ const selected = filter.options?.filter((o) => o.isChecked).map((o) => o.value);
432
+ if (!selected || selected.length === 0) return true;
433
+ return selected.includes(getNumberOfStops(result.outward)) && selected.includes(getNumberOfStops(result.return));
434
+ }
435
+
436
+ // Departure range
437
+ if (filter.property === 'departureRange') {
438
+ const selected = filter.options?.filter((o) => o.isChecked).map((o) => o.value);
439
+ if (!selected || selected.length === 0) return true;
440
+ return selected.includes(rangeFromDateTimeInMinutes(getDepartureSegment(result.outward)?.departureDateTime));
441
+ }
442
+
443
+ // Departure airport
444
+ if (filter.property === 'departureAirport') {
445
+ const selected = filter.options?.filter((o) => o.isChecked).map((o) => o.value);
446
+ if (!selected || selected.length === 0) return true;
447
+
448
+ const departureAirportCode = getDepartureSegment(result.outward)?.departureAirportCode;
449
+ if (!departureAirportCode) return false;
450
+
451
+ return selected.includes(departureAirportCode);
452
+ }
453
+
454
+ // Arrival airport
455
+ if (filter.property === 'arrivalAirport') {
456
+ const selected = filter.options?.filter((o) => o.isChecked).map((o) => o.value);
457
+ if (!selected || selected.length === 0) return true;
458
+
459
+ const arrivalAirportCode = getArrivalSegment(result.outward)?.arrivalAirportCode;
460
+ if (!arrivalAirportCode) return false;
461
+
462
+ return selected.includes(arrivalAirportCode);
463
+ }
464
+
465
+ // PRICE
466
+ if (filter.property === 'price') {
467
+ if (filter.selectedMin != null && result.price < filter.selectedMin) return false;
468
+ if (filter.selectedMax != null && result.price > filter.selectedMax) return false;
469
+ return true;
470
+ }
471
+
472
+ // Travel times
473
+ if (filter.property === 'travelDuration') {
474
+ if (filter.selectedMin != null && durationInTicksInMinutes(result.outward?.durationInTicks) < filter.selectedMin) return false;
475
+ if (filter.selectedMax != null && durationInTicksInMinutes(result.outward?.durationInTicks) > filter.selectedMax) return false;
476
+ return true;
477
+ }
478
+
479
+ return true;
480
+ });
481
+ });
482
+
483
+ // SORTING
484
+ if (!sortBy || sortBy.label === 'default') {
485
+ return filtered;
486
+ }
487
+
488
+ if (sortBy.label === 'departureTime') {
489
+ return orderBy(
490
+ results,
491
+ [(result) => getDepartureSegment(result.outward)?.departureDateTime],
492
+ [sortBy.direction] // or "desc"
493
+ );
494
+ } else if (sortBy.label === 'durationInTicks') {
495
+ return orderBy(
496
+ results,
497
+ [(result) => durationInTicksInMinutes(result.outward?.durationInTicks ?? 0)],
498
+ [sortBy.direction] // or "desc"
499
+ );
500
+ } else {
501
+ return orderBy(results, [sortBy.label], [sortBy.direction]);
502
+ }
503
+ };
@@ -1,23 +1,31 @@
1
- import React, { useEffect, useRef } from 'react';
1
+ import React, { useContext, useEffect, useRef } from 'react';
2
2
  import Icon from '../icon';
3
3
  import { useFlightSearch } from '../../../search-results/components/flight/flight-search-context';
4
- import { useDispatch } from 'react-redux';
4
+ import { useDispatch, useSelector } from 'react-redux';
5
5
  import {
6
- setAccommodationFlyInStep,
6
+ resetFilters,
7
+ setFilters,
8
+ setFlyInType,
7
9
  setSelectedFlight,
8
10
  setSelectedFlightDetails,
9
11
  setSelectedPackagingAccoResult,
10
- setSelectedSearchResult
12
+ setSelectedSearchResult,
13
+ setSortType
11
14
  } from '../../../search-results/store/search-results-slice';
12
15
  import FlightsFlyIn from './flights-flyin';
13
16
  import AccommodationFlyIn from './accommodation-flyin';
14
17
  import { PortalQsmType } from '@qite/tide-client';
15
18
  import GroupTourFlyIn from './group-tour-flyin';
16
- import { AccommodationFlyInStep } from '../../../search-results/types';
19
+ import { FlyInType, SortByType } from '../../../search-results/types';
17
20
  import HotelAccommodationResults from '../../../search-results/components/hotel/hotel-accommodation-results';
21
+ import PackageingFlightsFlyIn from './packaging-flights-flyin';
22
+ import SearchResultsConfigurationContext from '../../../search-results/search-results-configuration-context';
23
+ import { findSortByType, getSortingName, getTranslations } from '../../utils/localization-util';
24
+ import Filters from '../../../search-results/components/filters/filters';
25
+ import { SearchResultsRootState } from '../../../search-results/store/search-results-store';
26
+ import ItemPicker from '../../../search-results/components/item-picker';
18
27
 
19
28
  type FlyInProps = {
20
- title: string;
21
29
  srpType: PortalQsmType;
22
30
  isOpen: boolean;
23
31
  setIsOpen: (open: boolean) => void;
@@ -25,23 +33,32 @@ type FlyInProps = {
25
33
  onPanelRef?: (el: HTMLDivElement | null) => void;
26
34
  detailsLoading: boolean;
27
35
  handleConfirm?: () => void;
28
- accommodationStep?: AccommodationFlyInStep;
36
+ flyInType?: FlyInType | null;
29
37
  isPackageEditFlow?: boolean;
38
+ sortByTypes?: SortByType[];
30
39
  };
31
40
 
32
41
  const FlyIn: React.FC<FlyInProps> = ({
33
- title,
34
42
  srpType,
35
43
  isOpen,
36
44
  setIsOpen,
37
45
  className = '',
38
46
  onPanelRef,
39
47
  detailsLoading,
40
- accommodationStep,
48
+ flyInType,
41
49
  isPackageEditFlow,
42
- handleConfirm
50
+ handleConfirm,
51
+ sortByTypes
43
52
  }) => {
44
53
  const dispatch = useDispatch();
54
+ const context = useContext(SearchResultsConfigurationContext);
55
+ const language = context?.languageCode ?? 'en-GB';
56
+ const translations = getTranslations(language);
57
+
58
+ const { isLoading, initialFilters, filters, filteredPackagingAccoResults, selectedSortType } = useSelector(
59
+ (state: SearchResultsRootState) => state.searchResults
60
+ );
61
+
45
62
  const { onCancelSearch } = useFlightSearch();
46
63
  const panelRef = useRef<HTMLDivElement>(null);
47
64
 
@@ -81,26 +98,52 @@ const FlyIn: React.FC<FlyInProps> = ({
81
98
  dispatch(setSelectedSearchResult(null));
82
99
  dispatch(setSelectedPackagingAccoResult(null));
83
100
  }
84
- dispatch(setAccommodationFlyInStep('details'));
101
+ dispatch(setFlyInType('acco-details'));
85
102
  setIsOpen(false);
86
103
  }
87
104
  };
88
105
 
89
106
  const handleGoBack = () => {
90
- dispatch(setAccommodationFlyInStep('results'));
107
+ dispatch(setFlyInType('acco-results'));
108
+ };
109
+
110
+ const handleSortChange = (newSortKey: string, direction?: string) => {
111
+ if (sortByTypes === undefined) return;
112
+ const newSortByType = findSortByType(sortByTypes, newSortKey, direction ?? 'asc');
113
+ if (newSortByType) {
114
+ dispatch(setSortType(newSortByType));
115
+ }
91
116
  };
92
117
 
93
118
  return (
94
- <div className={`flyin ${isOpen ? 'flyin--active' : ''} ${className} ${isPackageEditFlow ? 'flyin--large' : ''}`}>
119
+ <div
120
+ className={`flyin ${isOpen ? 'flyin--active' : ''} ${className} ${
121
+ isPackageEditFlow || flyInType === 'flight-outward-results' || flyInType === 'flight-return-results' || flyInType === 'acco-results'
122
+ ? 'flyin--large'
123
+ : ''
124
+ }`}>
95
125
  <div className={`flyin__panel ${isOpen ? 'flyin__panel--active' : ''}`} ref={panelRef}>
96
126
  <div className="flyin__content">
97
127
  <div className="flyin__content-title-row">
98
- <h3 className="flyin__content-title">{title}</h3>
128
+ <h3 className="flyin__content-title">
129
+ {srpType === PortalQsmType.Flight && 'Select your fare'}
130
+ {srpType === PortalQsmType.Accommodation ||
131
+ (srpType === PortalQsmType.AccommodationAndFlight &&
132
+ (flyInType === 'acco-results' || flyInType === 'acco-details') &&
133
+ `${translations.SRP.SELECT} ${translations.SRP.ACCOMMODATION}`)}
134
+ {srpType === PortalQsmType.AccommodationAndFlight &&
135
+ flyInType === 'flight-outward-results' &&
136
+ `${translations.SRP.SELECT} ${translations.FLIGHTS_FORM.OUTWARD_FLIGHT}`}
137
+ {srpType === PortalQsmType.AccommodationAndFlight &&
138
+ flyInType === 'flight-return-results' &&
139
+ `${translations.SRP.SELECT} ${translations.FLIGHTS_FORM.RETURN_FLIGHT}`}
140
+ {srpType === PortalQsmType.AccommodationAndFlight && flyInType === 'flight-details' && 'Select your fare'}
141
+ </h3>
99
142
  <span className="flyin__close" onClick={() => handleClose()}>
100
143
  <Icon name="ui-close" width={30} height={30} aria-hidden="true" />
101
144
  </span>
102
145
  </div>
103
- {isPackageEditFlow && accommodationStep === 'details' && (
146
+ {isPackageEditFlow && flyInType === 'acco-details' && (
104
147
  <div className="flyin__content-title-row">
105
148
  <div onClick={handleGoBack} className="flyin__content-title__back">
106
149
  <Icon name="ui-chevron" width={14} height={14} aria-hidden="true" />
@@ -111,16 +154,56 @@ const FlyIn: React.FC<FlyInProps> = ({
111
154
  </div>
112
155
  {srpType === PortalQsmType.Flight && <FlightsFlyIn isOpen={isOpen} setIsOpen={setIsOpen} />}
113
156
 
114
- {(srpType === PortalQsmType.Accommodation || srpType === PortalQsmType.AccommodationAndFlight) && accommodationStep === 'results' && (
115
- <div className="flyin__content">
116
- <HotelAccommodationResults isLoading={detailsLoading} />
157
+ {(srpType === PortalQsmType.Accommodation || srpType === PortalQsmType.AccommodationAndFlight) && flyInType === 'acco-results' && (
158
+ <div className="flyin__content flyin__content--columns">
159
+ <Filters
160
+ initialFilters={initialFilters}
161
+ filters={filters}
162
+ isOpen={false}
163
+ handleSetIsOpen={() => {}}
164
+ // handleApplyFilters={() => setSearchTrigger((prev) => prev + 1)}
165
+ isLoading={isLoading}
166
+ setFilters={(filters) => dispatch(setFilters(filters))}
167
+ resetFilters={(filters) => dispatch(resetFilters(filters))}
168
+ />
169
+ <div className="search__results__wrapper">
170
+ <div className="search__result-row">
171
+ <span className="search__result-row-text">
172
+ {!isLoading && (
173
+ <>
174
+ {filteredPackagingAccoResults?.length && filteredPackagingAccoResults.length}
175
+ &nbsp;{translations.SRP.TOTAL_RESULTS_LABEL}
176
+ </>
177
+ )}
178
+ </span>
179
+ {sortByTypes && sortByTypes.length > 0 && (
180
+ <div className="search__result-row-filter">
181
+ <ItemPicker
182
+ items={sortByTypes}
183
+ selection={selectedSortType?.label || undefined}
184
+ selectedSortByType={selectedSortType}
185
+ label={translations.SRP.SORTBY}
186
+ placeholder={translations.SRP.SORTBY}
187
+ classModifier="travel-class-picker__items"
188
+ valueFormatter={(value, direction) => getSortingName(translations, findSortByType(sortByTypes, value, direction ?? 'asc'))}
189
+ onPick={(newSortKey, direction) => handleSortChange(newSortKey, direction)}
190
+ />
191
+ </div>
192
+ )}
193
+ </div>
194
+ <HotelAccommodationResults isLoading={detailsLoading} isFlyIn={true} />
195
+ </div>
117
196
  </div>
118
197
  )}
119
198
 
120
- {(srpType === PortalQsmType.Accommodation || srpType === PortalQsmType.AccommodationAndFlight) && accommodationStep === 'details' && (
199
+ {(srpType === PortalQsmType.Accommodation || srpType === PortalQsmType.AccommodationAndFlight) && flyInType === 'acco-details' && (
121
200
  <AccommodationFlyIn isLoading={detailsLoading} handleConfirm={handleConfirm!} />
122
201
  )}
123
202
 
203
+ {srpType === PortalQsmType.AccommodationAndFlight && (flyInType === 'flight-outward-results' || flyInType === 'flight-return-results') && (
204
+ <PackageingFlightsFlyIn isOpen={isOpen} setIsOpen={setIsOpen} />
205
+ )}
206
+
124
207
  {srpType === PortalQsmType.GroupTour && <GroupTourFlyIn isLoading={detailsLoading} isOpen={isOpen} setIsOpen={setIsOpen} />}
125
208
  </div>
126
209
  </div>