@qite/tide-booking-component 1.4.36 → 1.4.37
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.
- package/build/build-cjs/index.js +905 -184
- package/build/build-cjs/qsm/types.d.ts +1 -0
- package/build/build-cjs/search-results/components/flight/flight-results.d.ts +1 -1
- package/build/build-cjs/search-results/types.d.ts +1 -0
- package/build/build-esm/index.js +905 -184
- package/build/build-esm/qsm/types.d.ts +1 -0
- package/build/build-esm/search-results/components/flight/flight-results.d.ts +1 -1
- package/build/build-esm/search-results/types.d.ts +1 -0
- package/package.json +2 -2
- package/src/qsm/components/mobile-filter-modal/index.tsx +67 -42
- package/src/qsm/components/search-input-group/index.tsx +16 -2
- package/src/qsm/types.ts +1 -0
- package/src/search-results/components/flight/flight-results.tsx +115 -113
- package/src/search-results/components/hotel/hotel-accommodation-results.tsx +85 -0
- package/src/search-results/components/search-results-container/search-results-container.tsx +294 -146
- package/src/search-results/types.ts +1 -1
|
@@ -9,16 +9,18 @@ import useMediaQuery from '../../../shared/utils/use-media-query-util';
|
|
|
9
9
|
import Filters from '../filters/filters';
|
|
10
10
|
import ItemPicker from '../item-picker';
|
|
11
11
|
|
|
12
|
-
import { TideClientConfig, detailsWL, search } from '@qite/tide-client';
|
|
12
|
+
import { TideClientConfig, details, detailsWL, getEntryLight, search } from '@qite/tide-client';
|
|
13
13
|
import {
|
|
14
14
|
BookingPackageDestination,
|
|
15
15
|
BookingPackageDetailsRequest,
|
|
16
16
|
BookingPackagePax,
|
|
17
17
|
BookingPackageRequest,
|
|
18
18
|
BookingPackageRequestRoom,
|
|
19
|
-
BookingPackageSearchRequest
|
|
19
|
+
BookingPackageSearchRequest,
|
|
20
|
+
EntryLight,
|
|
21
|
+
EntryRoom
|
|
20
22
|
} from '@qite/tide-client/build/types';
|
|
21
|
-
import { getDateFromParams, getNumberFromParams, getRoomsFromParams } from '../../../shared/utils/query-string-util';
|
|
23
|
+
import { getDateFromParams, getNumberFromParams, getRoomsFromParams, getStringFromParams } from '../../../shared/utils/query-string-util';
|
|
22
24
|
import { range } from 'lodash';
|
|
23
25
|
import { Room } from '../../../booking-wizard/types';
|
|
24
26
|
import Icon from '../icon';
|
|
@@ -29,17 +31,247 @@ import RoundTripResults from '../round-trip/round-trip-results';
|
|
|
29
31
|
import { enrichFiltersWithResults } from '../filters/utility';
|
|
30
32
|
import FlightResults from '../flight/flight-results';
|
|
31
33
|
import { getTranslations } from '../../../shared/utils/localization-util';
|
|
34
|
+
import filters from '../filters/filters';
|
|
35
|
+
import FlightAccommodationResults from '../flight/flight-accommodation-results';
|
|
32
36
|
|
|
33
37
|
const SearchResultsContainer: React.FC = () => {
|
|
34
|
-
const isMobile = useMediaQuery('(max-width: 1200px)');
|
|
35
38
|
const dispatch = useDispatch();
|
|
39
|
+
|
|
36
40
|
const context = useContext(SearchResultsConfigurationContext);
|
|
37
41
|
const translations = getTranslations(context?.languageCode ?? 'en-GB');
|
|
38
|
-
|
|
42
|
+
|
|
43
|
+
const { results, bookingPackageDetails, entry, isLoading, filters, sortKey, selectedHotelId } = useSelector(
|
|
44
|
+
(state: SearchResultsRootState) => state.searchResults
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const isMobile = useMediaQuery('(max-width: 1200px)');
|
|
39
48
|
|
|
40
49
|
const [searchTrigger, setSearchTrigger] = useState(0);
|
|
41
50
|
const [initialFiltersSet, setInitialFiltersSet] = useState(false);
|
|
42
51
|
const [initialFilters, setInitialFilters] = useState<Filter[]>([]);
|
|
52
|
+
const [filtersOpen, setFiltersOpen] = useState(false);
|
|
53
|
+
const [itineraryOpen, setItineraryOpen] = useState(false);
|
|
54
|
+
|
|
55
|
+
const sortingOptions: SortingOption[] = [
|
|
56
|
+
{ key: 'price-asc', label: translations.SRP.PRICE_ASC },
|
|
57
|
+
{ key: 'price-desc', label: translations.SRP.PRICE_DESC },
|
|
58
|
+
{ key: 'departure-date', label: translations.SRP.DEPARTURE_ASC }
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
const handleSortChange = (newSortKey: string) => {
|
|
62
|
+
dispatch(setSortKey(newSortKey));
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const buildSearchFromEntry = (entry: EntryLight): BookingPackageRequest<BookingPackageSearchRequest> => {
|
|
66
|
+
const from = new Date(Math.min(...entry.items.map((i) => i.startDate.getTime()))).toISOString();
|
|
67
|
+
const to = new Date(Math.max(...entry.items.map((i) => i.endDate.getTime()))).toISOString();
|
|
68
|
+
const rooms = entry.rooms;
|
|
69
|
+
|
|
70
|
+
const hotelItem = entry.items.find((i) => i.productType === 3);
|
|
71
|
+
|
|
72
|
+
let country = hotelItem ? hotelItem.countryId : null;
|
|
73
|
+
let region = hotelItem ? hotelItem.regionId : null;
|
|
74
|
+
let oord = hotelItem ? hotelItem.oordId : null;
|
|
75
|
+
let city = hotelItem ? hotelItem.locationId : null;
|
|
76
|
+
let hotel = hotelItem ? hotelItem.productCode : null;
|
|
77
|
+
|
|
78
|
+
if (typeof window !== 'undefined') {
|
|
79
|
+
window.scrollTo(0, 0);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let destinationId: number | null = null;
|
|
83
|
+
let destinationIsCountry = false;
|
|
84
|
+
let destinationIsRegion = false;
|
|
85
|
+
let destinationIsOord = false;
|
|
86
|
+
let destinationIsLocation = false;
|
|
87
|
+
|
|
88
|
+
if (country) {
|
|
89
|
+
destinationId = country;
|
|
90
|
+
destinationIsCountry = true;
|
|
91
|
+
} else if (region) {
|
|
92
|
+
destinationId = region;
|
|
93
|
+
destinationIsRegion = true;
|
|
94
|
+
} else if (oord) {
|
|
95
|
+
destinationId = oord;
|
|
96
|
+
destinationIsOord = true;
|
|
97
|
+
} else if (city) {
|
|
98
|
+
destinationId = city;
|
|
99
|
+
destinationIsLocation = true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
var searchRequest = {
|
|
103
|
+
officeId: 1,
|
|
104
|
+
payload: {
|
|
105
|
+
catalogueIds: context!.tideConnection.catalogueIds ?? [],
|
|
106
|
+
serviceType: context!.type === 'hotel' || context!.type === 'hotel-flight' ? 3 : context!.type === 'flight' ? 7 : context!.type === 'roundTrip' ? 1 : 0,
|
|
107
|
+
searchType: 0,
|
|
108
|
+
destination: {
|
|
109
|
+
id: Number(destinationId),
|
|
110
|
+
isCountry: destinationIsCountry,
|
|
111
|
+
isRegion: destinationIsRegion,
|
|
112
|
+
isOord: destinationIsOord,
|
|
113
|
+
isLocation: destinationIsLocation
|
|
114
|
+
} as BookingPackageDestination,
|
|
115
|
+
rooms: getRequestRoomsFromEntry(rooms),
|
|
116
|
+
fromDate: from,
|
|
117
|
+
toDate: to,
|
|
118
|
+
earliestFromOffset: 0,
|
|
119
|
+
latestToOffset: 0,
|
|
120
|
+
includeFlights: true,
|
|
121
|
+
regimeCodes: entry.items.map((i) => i.regimeCode) || [],
|
|
122
|
+
useExactDates: true,
|
|
123
|
+
onlyCachedResults: false,
|
|
124
|
+
includeAllAllotments: true,
|
|
125
|
+
productCodes: hotel ? [hotel] : []
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
return searchRequest;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const buildSearchFromQueryParams = (params: URLSearchParams): BookingPackageRequest<BookingPackageSearchRequest> => {
|
|
133
|
+
let from = getDateFromParams(params, 'fromDate');
|
|
134
|
+
let to = getDateFromParams(params, 'toDate');
|
|
135
|
+
const rooms = getRoomsFromParams(params, 'rooms');
|
|
136
|
+
let country = getNumberFromParams(params, 'country');
|
|
137
|
+
let region = getNumberFromParams(params, 'region');
|
|
138
|
+
let oord = getNumberFromParams(params, 'oord');
|
|
139
|
+
let city = getNumberFromParams(params, 'location');
|
|
140
|
+
let hotel = getNumberFromParams(params, 'hotel');
|
|
141
|
+
let tagId = getNumberFromParams(params, 'tagId');
|
|
142
|
+
|
|
143
|
+
// temp hardcoded params
|
|
144
|
+
if (!from || !to) {
|
|
145
|
+
from = '2026-04-07';
|
|
146
|
+
to = '2026-04-13';
|
|
147
|
+
}
|
|
148
|
+
if (!country && !region && !oord && !city) {
|
|
149
|
+
region = 1;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (typeof window !== 'undefined') {
|
|
153
|
+
window.scrollTo(0, 0);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let destinationId: number | null = null;
|
|
157
|
+
let destinationIsCountry = false;
|
|
158
|
+
let destinationIsRegion = false;
|
|
159
|
+
let destinationIsOord = false;
|
|
160
|
+
let destinationIsLocation = false;
|
|
161
|
+
|
|
162
|
+
if (country) {
|
|
163
|
+
destinationId = country;
|
|
164
|
+
destinationIsCountry = true;
|
|
165
|
+
} else if (region) {
|
|
166
|
+
destinationId = region;
|
|
167
|
+
destinationIsRegion = true;
|
|
168
|
+
} else if (oord) {
|
|
169
|
+
destinationId = oord;
|
|
170
|
+
destinationIsOord = true;
|
|
171
|
+
} else if (city) {
|
|
172
|
+
destinationId = city;
|
|
173
|
+
destinationIsLocation = true;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
var searchRequest = {
|
|
177
|
+
officeId: 1,
|
|
178
|
+
payload: {
|
|
179
|
+
catalogueIds: context!.tideConnection.catalogueIds ?? [],
|
|
180
|
+
serviceType: context!.type === 'hotel' || context!.type === 'hotel-flight' ? 3 : context!.type === 'flight' ? 7 : context!.type === 'roundTrip' ? 1 : 0,
|
|
181
|
+
searchType: 0,
|
|
182
|
+
destination: {
|
|
183
|
+
id: Number(destinationId),
|
|
184
|
+
isCountry: destinationIsCountry,
|
|
185
|
+
isRegion: destinationIsRegion,
|
|
186
|
+
isOord: destinationIsOord,
|
|
187
|
+
isLocation: destinationIsLocation
|
|
188
|
+
} as BookingPackageDestination,
|
|
189
|
+
rooms: getRequestRooms(rooms),
|
|
190
|
+
fromDate: from,
|
|
191
|
+
toDate: to,
|
|
192
|
+
earliestFromOffset: 0,
|
|
193
|
+
latestToOffset: 0,
|
|
194
|
+
includeFlights: true,
|
|
195
|
+
regimeCodes:
|
|
196
|
+
filters
|
|
197
|
+
.find((f) => f.property === 'regime')
|
|
198
|
+
?.options?.filter((o) => o.isChecked)
|
|
199
|
+
.flatMap((o) => o.value.toString()) || [],
|
|
200
|
+
minPrice: filters.find((f) => f.property === 'price')?.selectedMin,
|
|
201
|
+
maxPrice: filters.find((f) => f.property === 'price')?.selectedMax,
|
|
202
|
+
useExactDates: true,
|
|
203
|
+
onlyCachedResults: false,
|
|
204
|
+
includeAllAllotments: true,
|
|
205
|
+
productIds: hotel ? [hotel] : [],
|
|
206
|
+
productTagIds: tagId ? [tagId] : []
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
return searchRequest;
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const getRequestRoomsFromEntry = (rooms: EntryRoom[] | null) => {
|
|
214
|
+
if (!rooms) {
|
|
215
|
+
// Fall back to 2 adults
|
|
216
|
+
var room = { index: 0, pax: [] } as BookingPackageRequestRoom;
|
|
217
|
+
range(0, 2).forEach(() => {
|
|
218
|
+
room.pax.push({
|
|
219
|
+
age: 30
|
|
220
|
+
} as BookingPackagePax);
|
|
221
|
+
});
|
|
222
|
+
return [room];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const requestRooms = rooms?.map((x, i) => {
|
|
226
|
+
var room = { index: i, pax: [] } as BookingPackageRequestRoom;
|
|
227
|
+
x.travellers.forEach((p) => {
|
|
228
|
+
room.pax.push({
|
|
229
|
+
age: p.age,
|
|
230
|
+
dateOfBirth: p.dateOfBirth
|
|
231
|
+
} as BookingPackagePax);
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
return room;
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
return requestRooms;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const getRequestRooms = (rooms: Room[] | null) => {
|
|
241
|
+
if (!rooms) {
|
|
242
|
+
// Fall back to 2 adults
|
|
243
|
+
var room = { index: 0, pax: [] } as BookingPackageRequestRoom;
|
|
244
|
+
range(0, 2).forEach(() => {
|
|
245
|
+
room.pax.push({
|
|
246
|
+
age: 30
|
|
247
|
+
} as BookingPackagePax);
|
|
248
|
+
});
|
|
249
|
+
return [room];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const requestRooms = rooms?.map((x, i) => {
|
|
253
|
+
var room = { index: i, pax: [] } as BookingPackageRequestRoom;
|
|
254
|
+
range(0, x.adults).forEach(() => {
|
|
255
|
+
room.pax.push({
|
|
256
|
+
age: 30
|
|
257
|
+
} as BookingPackagePax);
|
|
258
|
+
});
|
|
259
|
+
x.childAges.forEach((x) => {
|
|
260
|
+
room.pax.push({
|
|
261
|
+
age: x
|
|
262
|
+
} as BookingPackagePax);
|
|
263
|
+
});
|
|
264
|
+
return room;
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
return requestRooms;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
if (typeof document !== 'undefined') {
|
|
272
|
+
document.body.classList.toggle('has-overlay', filtersOpen);
|
|
273
|
+
}
|
|
274
|
+
}, [filtersOpen]);
|
|
43
275
|
|
|
44
276
|
// seperate Search
|
|
45
277
|
useEffect(() => {
|
|
@@ -50,90 +282,27 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
50
282
|
return;
|
|
51
283
|
}
|
|
52
284
|
|
|
53
|
-
const params = new URLSearchParams(location.search);
|
|
54
|
-
let from = getDateFromParams(params, 'fromDate');
|
|
55
|
-
let to = getDateFromParams(params, 'toDate');
|
|
56
|
-
const rooms = getRoomsFromParams(params, 'rooms');
|
|
57
|
-
let country = getNumberFromParams(params, 'country');
|
|
58
|
-
let region = getNumberFromParams(params, 'region');
|
|
59
|
-
let oord = getNumberFromParams(params, 'oord');
|
|
60
|
-
let city = getNumberFromParams(params, 'location');
|
|
61
|
-
let hotel = getNumberFromParams(params, 'hotel');
|
|
62
|
-
let tagId = getNumberFromParams(params, 'tagId');
|
|
63
|
-
|
|
64
|
-
// temp hardcoded params
|
|
65
|
-
if (!from || !to) {
|
|
66
|
-
from = '2026-04-07';
|
|
67
|
-
to = '2026-04-13';
|
|
68
|
-
}
|
|
69
|
-
if (!country && !region && !oord && !city) {
|
|
70
|
-
region = 1;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (typeof window !== 'undefined') {
|
|
74
|
-
window.scrollTo(0, 0);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
let destinationId: number | null = null;
|
|
78
|
-
let destinationIsCountry = false;
|
|
79
|
-
let destinationIsRegion = false;
|
|
80
|
-
let destinationIsOord = false;
|
|
81
|
-
let destinationIsLocation = false;
|
|
82
|
-
|
|
83
|
-
if (country) {
|
|
84
|
-
destinationId = country;
|
|
85
|
-
destinationIsCountry = true;
|
|
86
|
-
} else if (region) {
|
|
87
|
-
destinationId = region;
|
|
88
|
-
destinationIsRegion = true;
|
|
89
|
-
} else if (oord) {
|
|
90
|
-
destinationId = oord;
|
|
91
|
-
destinationIsOord = true;
|
|
92
|
-
} else if (city) {
|
|
93
|
-
destinationId = city;
|
|
94
|
-
destinationIsLocation = true;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const searchRequest: BookingPackageRequest<BookingPackageSearchRequest> = {
|
|
98
|
-
officeId: 1,
|
|
99
|
-
payload: {
|
|
100
|
-
catalogueIds: context.tideConnection.catalogueIds ?? [],
|
|
101
|
-
serviceType:
|
|
102
|
-
context?.type === 'hotel' || context?.type === 'hotel-flight' ? 3 : context?.type === 'flight' ? 7 : context?.type === 'roundTrip' ? 1 : 0,
|
|
103
|
-
searchType: 0,
|
|
104
|
-
destination: {
|
|
105
|
-
id: Number(destinationId),
|
|
106
|
-
isCountry: destinationIsCountry,
|
|
107
|
-
isRegion: destinationIsRegion,
|
|
108
|
-
isOord: destinationIsOord,
|
|
109
|
-
isLocation: destinationIsLocation
|
|
110
|
-
} as BookingPackageDestination,
|
|
111
|
-
rooms: getRequestRooms(rooms),
|
|
112
|
-
fromDate: from,
|
|
113
|
-
toDate: to,
|
|
114
|
-
earliestFromOffset: 0,
|
|
115
|
-
latestToOffset: 0,
|
|
116
|
-
includeFlights: true,
|
|
117
|
-
regimeCodes:
|
|
118
|
-
filters
|
|
119
|
-
.find((f) => f.property === 'regime')
|
|
120
|
-
?.options?.filter((o) => o.isChecked)
|
|
121
|
-
.flatMap((o) => o.value.toString()) || [],
|
|
122
|
-
minPrice: filters.find((f) => f.property === 'price')?.selectedMin,
|
|
123
|
-
maxPrice: filters.find((f) => f.property === 'price')?.selectedMax,
|
|
124
|
-
useExactDates: true,
|
|
125
|
-
onlyCachedResults: false,
|
|
126
|
-
includeAllAllotments: true,
|
|
127
|
-
productIds: hotel ? [hotel] : [],
|
|
128
|
-
productTagIds: tagId ? [tagId] : []
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
|
|
132
285
|
const config: TideClientConfig = {
|
|
133
286
|
host: context.tideConnection.host,
|
|
134
287
|
apiKey: context.tideConnection.apiKey
|
|
135
288
|
};
|
|
136
289
|
|
|
290
|
+
const params = new URLSearchParams(location.search);
|
|
291
|
+
let entryId = getStringFromParams(params, 'entryId');
|
|
292
|
+
let entryLight: EntryLight | null = null;
|
|
293
|
+
// 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
|
|
294
|
+
|
|
295
|
+
let searchRequest: BookingPackageRequest<BookingPackageSearchRequest>;
|
|
296
|
+
|
|
297
|
+
if (entryId) {
|
|
298
|
+
entryLight = await getEntryLight(config, entryId);
|
|
299
|
+
// populate itinerary store
|
|
300
|
+
dispatch(setEntry({ entry: entryLight }));
|
|
301
|
+
searchRequest = buildSearchFromEntry(entryLight);
|
|
302
|
+
} else {
|
|
303
|
+
searchRequest = buildSearchFromQueryParams(params);
|
|
304
|
+
}
|
|
305
|
+
|
|
137
306
|
const packageSearchResults = await search(config, searchRequest);
|
|
138
307
|
|
|
139
308
|
console.log('Search results', packageSearchResults);
|
|
@@ -147,8 +316,17 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
147
316
|
|
|
148
317
|
dispatch(setResults({ results: packageSearchResults }));
|
|
149
318
|
if (packageSearchResults?.length > 0) {
|
|
150
|
-
|
|
319
|
+
if (entryId) {
|
|
320
|
+
const matching = packageSearchResults.find((r) => r.productId === entry?.id);
|
|
321
|
+
|
|
322
|
+
if (matching) {
|
|
323
|
+
dispatch(setSelectedHotel(matching.productId));
|
|
324
|
+
}
|
|
325
|
+
} else {
|
|
326
|
+
dispatch(setSelectedHotel(packageSearchResults[0]?.productId));
|
|
327
|
+
}
|
|
151
328
|
}
|
|
329
|
+
|
|
152
330
|
dispatch(setIsLoading(false));
|
|
153
331
|
} catch (err) {
|
|
154
332
|
console.error('Search failed', err);
|
|
@@ -156,7 +334,9 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
156
334
|
}
|
|
157
335
|
};
|
|
158
336
|
|
|
159
|
-
|
|
337
|
+
if (!context?.showMockup) {
|
|
338
|
+
runSearch();
|
|
339
|
+
}
|
|
160
340
|
}, [location.search, searchTrigger]);
|
|
161
341
|
|
|
162
342
|
// Seperate detailsCall
|
|
@@ -171,11 +351,21 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
171
351
|
};
|
|
172
352
|
|
|
173
353
|
const selectedItem = results.find((r) => r.productId === selectedHotelId);
|
|
174
|
-
if (!selectedItem)
|
|
354
|
+
if (!selectedItem) {
|
|
355
|
+
// TODO: handle this case better, show an error message to the user
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
175
358
|
|
|
176
359
|
const params = new URLSearchParams(location.search);
|
|
177
|
-
|
|
178
|
-
|
|
360
|
+
let entryId = getStringFromParams(params, 'entryId');
|
|
361
|
+
|
|
362
|
+
let requestRooms;
|
|
363
|
+
if (entry && entryId) {
|
|
364
|
+
requestRooms = getRequestRoomsFromEntry(entry.rooms);
|
|
365
|
+
} else {
|
|
366
|
+
const rooms = getRoomsFromParams(params, 'rooms');
|
|
367
|
+
requestRooms = getRequestRooms(rooms);
|
|
368
|
+
}
|
|
179
369
|
|
|
180
370
|
const detailsRequest: BookingPackageRequest<BookingPackageDetailsRequest> = {
|
|
181
371
|
officeId: 1,
|
|
@@ -197,10 +387,17 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
197
387
|
}
|
|
198
388
|
};
|
|
199
389
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
390
|
+
if (entry && entryId) {
|
|
391
|
+
requestRooms = getRequestRoomsFromEntry(entry.rooms);
|
|
392
|
+
const detailsResponse = await details(config, detailsRequest);
|
|
393
|
+
console.log('Details:', detailsResponse);
|
|
394
|
+
dispatch(setBookingPackageDetails({ details: detailsResponse?.payload }));
|
|
395
|
+
} else {
|
|
396
|
+
const detailsWLResponse = await detailsWL(config, detailsRequest);
|
|
397
|
+
console.log('Details with entryLight:', detailsWLResponse);
|
|
398
|
+
dispatch(setBookingPackageDetails({ details: detailsWLResponse?.payload?.bookingPackage }));
|
|
399
|
+
dispatch(setEntry({ entry: detailsWLResponse?.payload?.entry }));
|
|
400
|
+
}
|
|
204
401
|
} catch (err) {
|
|
205
402
|
console.error('Failed to fetch package details', err);
|
|
206
403
|
}
|
|
@@ -209,55 +406,6 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
209
406
|
fetchPackageDetails();
|
|
210
407
|
}, [selectedHotelId]);
|
|
211
408
|
|
|
212
|
-
const getRequestRooms = (rooms: Room[] | null) => {
|
|
213
|
-
if (!rooms) {
|
|
214
|
-
// Fall back to 2 adults
|
|
215
|
-
var room = { index: 0, pax: [] } as BookingPackageRequestRoom;
|
|
216
|
-
range(0, 2).forEach(() => {
|
|
217
|
-
room.pax.push({
|
|
218
|
-
age: 30
|
|
219
|
-
} as BookingPackagePax);
|
|
220
|
-
});
|
|
221
|
-
return [room];
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const requestRooms = rooms?.map((x, i) => {
|
|
225
|
-
var room = { index: i, pax: [] } as BookingPackageRequestRoom;
|
|
226
|
-
range(0, x.adults).forEach(() => {
|
|
227
|
-
room.pax.push({
|
|
228
|
-
age: 30
|
|
229
|
-
} as BookingPackagePax);
|
|
230
|
-
});
|
|
231
|
-
x.childAges.forEach((x) => {
|
|
232
|
-
room.pax.push({
|
|
233
|
-
age: x
|
|
234
|
-
} as BookingPackagePax);
|
|
235
|
-
});
|
|
236
|
-
return room;
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
return requestRooms;
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
const [filtersOpen, setFiltersOpen] = useState(false);
|
|
243
|
-
const [itineraryOpen, setItineraryOpen] = useState(false);
|
|
244
|
-
|
|
245
|
-
const handleSortChange = (newSortKey: string) => {
|
|
246
|
-
dispatch(setSortKey(newSortKey));
|
|
247
|
-
};
|
|
248
|
-
|
|
249
|
-
useEffect(() => {
|
|
250
|
-
if (typeof document !== 'undefined') {
|
|
251
|
-
document.body.classList.toggle('has-overlay', filtersOpen);
|
|
252
|
-
}
|
|
253
|
-
}, [filtersOpen]);
|
|
254
|
-
|
|
255
|
-
const sortingOptions: SortingOption[] = [
|
|
256
|
-
{ key: 'price-asc', label: translations.SRP.PRICE_ASC },
|
|
257
|
-
{ key: 'price-desc', label: translations.SRP.PRICE_DESC },
|
|
258
|
-
{ key: 'departure-date', label: translations.SRP.DEPARTURE_ASC }
|
|
259
|
-
];
|
|
260
|
-
|
|
261
409
|
return (
|
|
262
410
|
<div id="tide-booking" className="search__bg">
|
|
263
411
|
{context && (
|
|
@@ -329,17 +477,17 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
329
477
|
<div className="search__results__wrapper">
|
|
330
478
|
{context.showTabViews && <TabViews />}
|
|
331
479
|
|
|
332
|
-
{
|
|
480
|
+
{context.showRoundTripResults && context.showMockup && <RoundTripResults />}
|
|
333
481
|
|
|
334
482
|
{context.showFlightResults && bookingPackageDetails?.outwardFlights && (
|
|
335
|
-
<FlightResults flights={bookingPackageDetails
|
|
483
|
+
<FlightResults flights={bookingPackageDetails?.outwardFlights} isDeparture={true} />
|
|
336
484
|
)}
|
|
337
485
|
|
|
338
486
|
{context.showHotelAccommodationResults && <HotelAccommodationResults isLoading={isLoading} context={context} />}
|
|
339
|
-
{
|
|
487
|
+
{context.showFlightAccommodationResults && context.showMockup && <FlightAccommodationResults />}
|
|
340
488
|
|
|
341
489
|
{context.showFlightResults && bookingPackageDetails?.returnFlights && (
|
|
342
|
-
<FlightResults flights={bookingPackageDetails
|
|
490
|
+
<FlightResults flights={bookingPackageDetails?.returnFlights} isDeparture={false} />
|
|
343
491
|
)}
|
|
344
492
|
</div>
|
|
345
493
|
</div>
|
|
@@ -27,7 +27,7 @@ export interface SearchResultsConfiguration {
|
|
|
27
27
|
showRoundTripResults?: boolean;
|
|
28
28
|
showCustomCards?: boolean;
|
|
29
29
|
customCardRenderer?: (result: SearchResult) => ReactNode;
|
|
30
|
-
|
|
30
|
+
showMockup?: boolean;
|
|
31
31
|
// Map view
|
|
32
32
|
// not supported for now
|
|
33
33
|
showMapView?: boolean;
|