@qite/tide-booking-component 1.4.29 → 1.4.31

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 (43) hide show
  1. package/build/build-cjs/index.js +621 -2822
  2. package/build/build-cjs/search-results/store/search-results-slice.d.ts +6 -3
  3. package/build/build-cjs/search-results/types.d.ts +9 -12
  4. package/build/build-esm/index.js +617 -2625
  5. package/build/build-esm/search-results/store/search-results-slice.d.ts +6 -3
  6. package/build/build-esm/search-results/types.d.ts +9 -12
  7. package/package.json +2 -3
  8. package/src/booking-product/components/dates.tsx +9 -4
  9. package/src/booking-wizard/components/step-indicator.tsx +11 -2
  10. package/src/booking-wizard/features/booking/booking-slice.ts +27 -2
  11. package/src/booking-wizard/features/booking/booking.tsx +32 -15
  12. package/src/booking-wizard/features/booking/selectors.ts +6 -0
  13. package/src/booking-wizard/features/flight-options/index.tsx +27 -3
  14. package/src/booking-wizard/features/product-options/option-room.tsx +1 -1
  15. package/src/booking-wizard/features/product-options/options-form.tsx +14 -4
  16. package/src/booking-wizard/features/room-options/room.tsx +1 -1
  17. package/src/booking-wizard/features/sidebar/index.tsx +4 -1
  18. package/src/booking-wizard/features/sidebar/sidebar-util.ts +1 -3
  19. package/src/booking-wizard/features/sidebar/sidebar.tsx +112 -104
  20. package/src/booking-wizard/features/travelers-form/travelers-form-slice.ts +1 -0
  21. package/src/booking-wizard/features/travelers-form/travelers-form.tsx +146 -10
  22. package/src/booking-wizard/settings-context.ts +2 -1
  23. package/src/booking-wizard/types.ts +1 -0
  24. package/src/qsm/components/search-input-group/index.tsx +17 -8
  25. package/src/search-results/components/hotel/hotel-accommodation-results.tsx +78 -83
  26. package/src/search-results/components/hotel/hotel-card.tsx +54 -24
  27. package/src/search-results/components/icon.tsx +13 -0
  28. package/src/search-results/components/item-picker/index.tsx +5 -7
  29. package/src/search-results/components/search-results-container/search-results-container.tsx +72 -117
  30. package/src/search-results/components/tab-views/index.tsx +22 -3
  31. package/src/search-results/features/flights/flight-search-results-self-contained.tsx +0 -13
  32. package/src/search-results/features/hotels/hotel-flight-search-results-self-contained.tsx +1 -8
  33. package/src/search-results/features/hotels/hotel-search-results-self-contained.tsx +1 -14
  34. package/src/search-results/features/roundtrips/roundtrip-search-results-self-contained.tsx +1 -9
  35. package/src/search-results/store/search-results-slice.ts +11 -4
  36. package/src/search-results/types.ts +11 -16
  37. package/src/shared/translations/en-GB.json +5 -1
  38. package/src/shared/translations/fr-BE.json +5 -1
  39. package/src/shared/translations/nl-BE.json +5 -1
  40. package/styles/components/_form.scss +51 -2
  41. package/styles/components/_passenger-picker.scss +3 -2
  42. package/styles/components/_qsm.scss +1 -1
  43. package/styles/qsm/_qsm.scss +67 -6
@@ -4,28 +4,20 @@ import { SearchResultsRootState } from '../../store/search-results-store';
4
4
  import SearchResultsConfigurationContext from '../../search-results-configuration-context';
5
5
 
6
6
  import { resetFilters, setSortKey, setResults, setIsLoading } from '../../store/search-results-slice';
7
- import { Filter, Sort } from '../../types';
7
+ import { Filter, SortingOption } from '../../types';
8
8
  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
12
  import { TideClientConfig, search } from '@qite/tide-client';
13
- import {
14
- BookingPackageDestination,
15
- BookingPackageItem,
16
- BookingPackagePax,
17
- BookingPackageRequestRoom,
18
- BookingPackageSearchRequest
19
- } from '@qite/tide-client/build/types';
13
+ import { BookingPackageDestination, BookingPackagePax, BookingPackageRequestRoom, BookingPackageSearchRequest } from '@qite/tide-client/build/types';
20
14
  import { getDateFromParams, getNumberFromParams, getRoomsFromParams } from '../../../shared/utils/query-string-util';
21
15
  import { range } from 'lodash';
22
16
  import { Room } from '../../../booking-wizard/types';
23
17
  import Icon from '../icon';
24
18
  import Itinerary from '../itinerary';
25
19
  import TabViews from '../tab-views';
26
- import FlightResults from '../flight/flight-results';
27
20
  import HotelAccommodationResults from '../hotel/hotel-accommodation-results';
28
- import FlightAccommodationResults from '../flight/flight-accommodation-results';
29
21
  import RoundTripResults from '../round-trip/round-trip-results';
30
22
  import { enrichFiltersWithResults } from '../filters/utility';
31
23
 
@@ -48,20 +40,32 @@ const SearchResultsContainer: React.FC = () => {
48
40
  }
49
41
 
50
42
  const params = new URLSearchParams(location.search);
51
- const from = getDateFromParams(params, 'from');
52
- const to = getDateFromParams(params, 'to');
43
+ let from = getDateFromParams(params, 'from');
44
+ let to = getDateFromParams(params, 'to');
53
45
  const rooms = getRoomsFromParams(params, 'rooms');
54
- const country = getNumberFromParams(params, 'country');
55
- const region = getNumberFromParams(params, 'region');
46
+ let country = getNumberFromParams(params, 'country');
47
+ let region = getNumberFromParams(params, 'region');
48
+ let oord = getNumberFromParams(params, 'oord');
49
+ let city = getNumberFromParams(params, 'location');
50
+
51
+ // temp hardcoded params
52
+ if (!from || !to) {
53
+ from = '2026-04-07';
54
+ to = '2026-04-13';
55
+ }
56
+ if (!country && !region && !oord && !city) {
57
+ region = 1;
58
+ }
56
59
 
57
60
  if (typeof window !== 'undefined') {
58
61
  window.scrollTo(0, 0);
59
62
  }
60
63
 
61
- // Determine destination
62
64
  let destinationId: number | null = null;
63
65
  let destinationIsCountry = false;
64
66
  let destinationIsRegion = false;
67
+ let destinationIsOord = false;
68
+ let destinationIsLocation = false;
65
69
 
66
70
  if (country) {
67
71
  destinationId = country;
@@ -69,20 +73,27 @@ const SearchResultsContainer: React.FC = () => {
69
73
  } else if (region) {
70
74
  destinationId = region;
71
75
  destinationIsRegion = true;
76
+ } else if (oord) {
77
+ destinationId = oord;
78
+ destinationIsOord = true;
79
+ } else if (city) {
80
+ destinationId = city;
81
+ destinationIsLocation = true;
72
82
  }
73
83
 
74
84
  const searchRequest = {
75
85
  officeId: 1,
76
86
  payload: {
77
87
  catalogueIds: context.tideConnection.catalogueIds,
78
- serviceType: context?.type === 'hotel' ? 3 : context?.type === 'flight' ? 7 : context?.type === 'roundTrip' ? 1 : 0,
88
+ serviceType:
89
+ context?.type === 'hotel' || context?.type === 'hotel-flight' ? 3 : context?.type === 'flight' ? 7 : context?.type === 'roundTrip' ? 1 : 0,
79
90
  searchType: 0,
80
91
  destination: {
81
92
  id: Number(destinationId),
82
93
  isCountry: destinationIsCountry,
83
94
  isRegion: destinationIsRegion,
84
- isOord: false,
85
- isLocation: false
95
+ isOord: destinationIsOord,
96
+ isLocation: destinationIsLocation
86
97
  } as BookingPackageDestination,
87
98
  rooms: getRequestRooms(rooms),
88
99
  fromDate: from,
@@ -110,7 +121,8 @@ const SearchResultsContainer: React.FC = () => {
110
121
 
111
122
  const packageSearchResults = await search(config, searchRequest);
112
123
 
113
- const finalResults = createSearchResults(packageSearchResults);
124
+ console.log('Search results', packageSearchResults);
125
+
114
126
  const enrichedFilters = enrichFiltersWithResults(packageSearchResults, context.filters);
115
127
  if (!initialFiltersSet) {
116
128
  dispatch(resetFilters(enrichedFilters));
@@ -118,7 +130,7 @@ const SearchResultsContainer: React.FC = () => {
118
130
  setInitialFiltersSet(true);
119
131
  }
120
132
 
121
- dispatch(setResults({ results: finalResults }));
133
+ dispatch(setResults({ results: packageSearchResults }));
122
134
  dispatch(setIsLoading(false));
123
135
  } catch (err) {
124
136
  console.error('Search failed', err);
@@ -126,9 +138,8 @@ const SearchResultsContainer: React.FC = () => {
126
138
  }
127
139
  };
128
140
 
129
- // nog statisch werken voorlopig
130
- // runSearch();
131
- }, [location.search, searchTrigger, sortKey]);
141
+ runSearch();
142
+ }, [location.search, searchTrigger]);
132
143
 
133
144
  const getRequestRooms = (rooms: Room[] | null) => {
134
145
  if (!rooms) {
@@ -160,53 +171,11 @@ const SearchResultsContainer: React.FC = () => {
160
171
  return requestRooms;
161
172
  };
162
173
 
163
- const createSearchResults = (searchResults: BookingPackageItem[]) => {
164
- return searchResults.map((searchResult) => {
165
- return {
166
- type: context?.type,
167
- id: searchResult.code,
168
- title: searchResult.name,
169
- image: getPlaceholderImage(), // TODO: We should not be using a placeholder image, but a result-specific image
170
- description: `${searchResult.accommodationName}`,
171
- location: `${searchResult.locationName}, ${searchResult.countryName}`,
172
- price: formatPrice(searchResult.price),
173
- ctaText: context?.translations?.searchResultCTA,
174
- days: calculateNights(searchResult.stayFromDate, searchResult.stayToDate),
175
- flightInfo: searchResult.flightDescription || null,
176
- accommodation: searchResult.accommodationName || null,
177
- regime: searchResult.regimeCode || null,
178
- stars: searchResult.hotelStars
179
- };
180
- });
181
- };
182
-
183
- const getPlaceholderImage = () => {
184
- // Placeholder image URL
185
- return 'https://images.unsplash.com/photo-1573790387438-4da905039392?q=80&w=1925&auto=format&fit=crop';
186
- };
187
-
188
- const formatPrice = (price: number) => {
189
- if (!price) {
190
- return 'Price unavailable';
191
- }
192
- return `$${Math.round(price).toLocaleString()}`;
193
- };
194
-
195
- const calculateNights = (fromDate: Date, toDate: Date): string => {
196
- const from = new Date(fromDate).getTime(); // returns a number
197
- const to = new Date(toDate).getTime(); // returns a number
198
- const diffTime = Math.abs(to - from);
199
- const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
200
- return `${diffDays} nights`;
201
- };
202
-
203
174
  const [isMobileFiltersOpen, setIsMobileFiltersOpen] = useState(false);
204
175
 
205
176
  const handleSortChange = (newSortKey: string) => {
177
+ console.log('Sort changed to:', newSortKey);
206
178
  dispatch(setSortKey(newSortKey));
207
- if (context) {
208
- context.onSortChange?.(newSortKey);
209
- }
210
179
  };
211
180
 
212
181
  const handleSetIsMobileFiltersOpen = () => {
@@ -219,31 +188,32 @@ const SearchResultsContainer: React.FC = () => {
219
188
  }
220
189
  }, [isMobileFiltersOpen]);
221
190
 
222
- const getFilteredResults = () => {
223
- const filteredResults = results.filter((result) => {
224
- // Apply frontend filters here
191
+ // const getFilteredResults = () => {
192
+ // const filteredResults = results.filter((result) => {
193
+ // // Apply frontend filters here
225
194
 
226
- const ratingFilter = filters.find((f) => f.property === 'rating' && f.selectedRating != null);
227
- if (ratingFilter) {
228
- const minRating = ratingFilter.selectedRating!;
229
- const hotelStars = result.stars ?? 0;
230
- if (hotelStars < minRating) {
231
- return false;
232
- }
233
- }
234
-
235
- // Add more frontend filters if needed
236
- return true;
237
- });
195
+ // const ratingFilter = filters.find((f) => f.property === 'rating' && f.selectedRating != null);
196
+ // if (ratingFilter) {
197
+ // const minRating = ratingFilter.selectedRating!;
198
+ // const hotelStars = result.stars ?? 0;
199
+ // if (hotelStars < minRating) {
200
+ // return false;
201
+ // }
202
+ // }
238
203
 
239
- return filteredResults;
240
- };
204
+ // // Add more frontend filters if needed
205
+ // return true;
206
+ // });
241
207
 
242
- const Sorts: Sort[] = [{ label: 'Price: low to high' }, { label: 'Price: high to low' }, { label: 'Top rated' }];
208
+ // return filteredResults;
209
+ // };
243
210
 
244
- const [selectedTravelClass, setSelectedTravelClass] = useState<string | undefined>(undefined);
211
+ const sortingOptions: SortingOption[] = [
212
+ { key: 'price-asc', label: 'Price: Low to High' },
213
+ { key: 'price-desc', label: 'Price: High to Low' },
214
+ { key: 'departure-date', label: 'Departure Date' }
215
+ ];
245
216
 
246
- console.log('SearchResultsContainer render', context);
247
217
  return (
248
218
  <div id="tide-booking" className="search__bg">
249
219
  {context && (
@@ -269,21 +239,14 @@ const SearchResultsContainer: React.FC = () => {
269
239
  <Icon name="ui-filter" className="mobile-filters-button__icon" height={16} />
270
240
  {context.translations?.filters}
271
241
  </div>
272
- {context.sortingOptions && context.sortingOptions.length > 0 && (
273
- // <select className="search__result-row-button" value={sortKey ?? ''} onChange={(e) => handleSortChange(e.target.value)}>
274
- // {context.sortingOptions.map((opt) => (
275
- // <option key={opt.key} value={opt.key}>
276
- // {opt.label}
277
- // </option>
278
- // ))}
279
- // </select>
242
+ {sortingOptions && sortingOptions.length > 0 && (
280
243
  <ItemPicker
281
- items={Sorts}
282
- selection={selectedTravelClass}
283
- label="Sorteren op"
284
- placeholder="Sorteer"
244
+ items={sortingOptions}
245
+ selection={sortKey || undefined}
246
+ label="Sort by"
247
+ placeholder="Sort by"
285
248
  classModifier="travel-class-picker__items"
286
- onPick={setSelectedTravelClass}
249
+ onPick={handleSortChange}
287
250
  />
288
251
  )}
289
252
  </div>
@@ -293,27 +256,19 @@ const SearchResultsContainer: React.FC = () => {
293
256
  <span className="search__result-row-text">
294
257
  {!isLoading && (
295
258
  <>
296
- {getFilteredResults()?.length ?? 4} {context.translations?.totalResultsLabel}
259
+ {results?.length ?? 4} {context.translations?.totalResultsLabel}
297
260
  </>
298
261
  )}
299
262
  </span>
300
- {!isMobile && context.sortingOptions && context.sortingOptions.length > 0 && (
263
+ {!isMobile && sortingOptions && sortingOptions.length > 0 && (
301
264
  <div className="search__result-row-filter">
302
- {/* <span className="search__result-row-text">{context.translations?.sortBy}</span>
303
- <select className="search__result-row-button" value={sortKey ?? ''} onChange={(e) => handleSortChange(e.target.value)}>
304
- {context.sortingOptions.map((opt) => (
305
- <option key={opt.key} value={opt.key}>
306
- {opt.label}
307
- </option>
308
- ))}
309
- </select> */}
310
265
  <ItemPicker
311
- items={Sorts}
312
- selection={selectedTravelClass}
313
- label="Sorteren op"
314
- placeholder="Sorteer"
266
+ items={sortingOptions}
267
+ selection={sortKey || undefined}
268
+ label="Sort by"
269
+ placeholder="Sort by"
315
270
  classModifier="travel-class-picker__items"
316
- onPick={setSelectedTravelClass}
271
+ onPick={handleSortChange}
317
272
  />
318
273
  </div>
319
274
  )}
@@ -324,12 +279,12 @@ const SearchResultsContainer: React.FC = () => {
324
279
 
325
280
  {context.showRoundTripResults && <RoundTripResults />}
326
281
 
327
- {context.showFlightResults && <FlightResults isDeparture={true} />}
282
+ {/* {context.showFlightResults && <FlightResults isDeparture={true} />} */}
328
283
 
329
284
  {context.showHotelAccommodationResults && <HotelAccommodationResults isLoading={isLoading} context={context} />}
330
- {context.showFlightAccommodationResults && <FlightAccommodationResults />}
285
+ {/* {context.showFlightAccommodationResults && <FlightAccommodationResults />} */}
331
286
 
332
- {context.showFlightResults && <FlightResults isDeparture={false} />}
287
+ {/* {context.showFlightResults && <FlightResults isDeparture={false} />} */}
333
288
  </div>
334
289
  </div>
335
290
  </div>
@@ -1,20 +1,39 @@
1
1
  import React from 'react';
2
2
  import Icon from '../icon';
3
+ import { useDispatch, useSelector } from 'react-redux';
4
+ import { SearchResultsRootState } from '../../store/search-results-store';
5
+ import { setActiveTab } from '../../store/search-results-slice';
3
6
 
4
7
  interface TabViewsProps {}
5
8
 
6
9
  const TabViews: React.FC<TabViewsProps> = () => {
10
+ const dispatch = useDispatch();
11
+ const { activeTab } = useSelector((state: SearchResultsRootState) => state.searchResults);
12
+
13
+ const handleSortChange = (tab: string) => {
14
+ dispatch(setActiveTab(tab));
15
+ };
16
+
7
17
  return (
8
18
  <div className="search__results__tab-views">
9
- <button type="button" className="search__results__tab-view search__results__tab-view--active">
19
+ <button
20
+ type="button"
21
+ className={`search__results__tab-view ${activeTab === 'extended' ? 'search__results__tab-view--active' : ''}`}
22
+ onClick={() => handleSortChange('extended')}>
10
23
  <Icon name="ui-extended" height={16} />
11
24
  Extended
12
25
  </button>
13
- <button type="button" className="search__results__tab-view">
26
+ <button
27
+ type="button"
28
+ className={`search__results__tab-view ${activeTab === 'compact' ? 'search__results__tab-view--active' : ''}`}
29
+ onClick={() => handleSortChange('compact')}>
14
30
  <Icon name="ui-compact" height={16} />
15
31
  Compact
16
32
  </button>
17
- <button type="button" className="search__results__tab-view">
33
+ <button
34
+ type="button"
35
+ className={`search__results__tab-view ${activeTab === 'comparator' ? 'search__results__tab-view--active' : ''}`}
36
+ onClick={() => handleSortChange('comparator')}>
18
37
  <Icon name="ui-comparator" height={16} />
19
38
  Comparator
20
39
  </button>
@@ -48,14 +48,6 @@ const FlightSearchResultsSelfContained: React.FC<FlightSearchResultsSelfContaine
48
48
  }
49
49
  ];
50
50
 
51
- // Sorting options
52
- const sortingOptions: SortingOption[] = [
53
- { key: 'price-asc', label: 'Prijs oplopend' },
54
- { key: 'price-desc', label: 'Prijs aflopend' }
55
- // { key: 'departuretime-desc', label: 'Vertrektijd oplopend' },
56
- // { key: 'departuretime-desc', label: 'Vertrektijd aflopend' }
57
- ];
58
-
59
51
  const customCardRenderer = (result: SearchResult): ReactNode => {
60
52
  switch (result.type) {
61
53
  case 'flight':
@@ -248,12 +240,7 @@ const FlightSearchResultsSelfContained: React.FC<FlightSearchResultsSelfContaine
248
240
  console.log('Clicked on card with id:', id);
249
241
  },
250
242
 
251
- // Sorting
252
- sortingOptions,
253
243
  filters,
254
- onSortChange: (sortKey) => {
255
- console.log('Sort changed to:', sortKey);
256
- },
257
244
 
258
245
  // Map View
259
246
  showMapView: false,
@@ -1,5 +1,5 @@
1
1
  import React, { ReactNode } from 'react';
2
- import { SearchResult, SearchResultsConfiguration, SortingOption } from '../../types';
2
+ import { SearchResult, SearchResultsConfiguration } from '../../types';
3
3
  import SearchResults from '../..';
4
4
  import { Navbar, Footer } from '../../../../src';
5
5
  import { TideLogo, language, languages, topLinks, navItems } from '../../../../src/content/navbar/placeholderData';
@@ -8,12 +8,6 @@ import Icon from '../../components/icon';
8
8
  interface HotelFlightSearchResultsSelfContainedProps {}
9
9
 
10
10
  const HotelFlightSearchResultsSelfContained: React.FC<HotelFlightSearchResultsSelfContainedProps> = () => {
11
- const sortingOptions: SortingOption[] = [
12
- { key: 'price-asc', label: 'Price: Low to High' },
13
- { key: 'price-desc', label: 'Price: High to Low' },
14
- { key: 'rating-desc', label: 'Top Rated' }
15
- ];
16
-
17
11
  const customCardRenderer = (result: SearchResult): ReactNode => {
18
12
  switch (result.type) {
19
13
  case 'hotel':
@@ -99,7 +93,6 @@ const HotelFlightSearchResultsSelfContained: React.FC<HotelFlightSearchResultsSe
99
93
  apiKey: 'e9b95d79-de4c-41d6-ab7e-3dd429873058',
100
94
  catalogueIds: [1, 2]
101
95
  },
102
- sortingOptions: sortingOptions,
103
96
  showTabViews: true,
104
97
  showFlightResults: true,
105
98
  showHotelAccommodationResults: true,
@@ -1,5 +1,5 @@
1
1
  import React, { ReactNode } from 'react';
2
- import { Filter, SearchResult, SearchResultsConfiguration, SortingOption } from '../../types';
2
+ import { Filter, SearchResult, SearchResultsConfiguration } from '../../types';
3
3
  import SearchResults from '../..';
4
4
  import { Navbar, Footer } from '../../../../src';
5
5
  import { TideLogo, language, languages, topLinks, navItems } from '../../../../src/content/navbar/placeholderData';
@@ -48,13 +48,6 @@ const HotelSearchResultsSelfContained: React.FC<HotelSearchResultsSelfContainedP
48
48
  }
49
49
  ];
50
50
 
51
- // Sorting options
52
- const sortingOptions: SortingOption[] = [
53
- { key: 'price-asc', label: 'Price: Low to High' },
54
- { key: 'price-desc', label: 'Price: High to Low' },
55
- { key: 'rating-desc', label: 'Top Rated' }
56
- ];
57
-
58
51
  const customCardRenderer = (result: SearchResult): ReactNode => {
59
52
  switch (result.type) {
60
53
  case 'hotel':
@@ -168,12 +161,6 @@ const HotelSearchResultsSelfContained: React.FC<HotelSearchResultsSelfContainedP
168
161
  },
169
162
  customCardRenderer,
170
163
 
171
- // Sorting
172
- sortingOptions,
173
- onSortChange: (sortKey) => {
174
- console.log('Sort changed to:', sortKey);
175
- },
176
-
177
164
  // Map View
178
165
  showMapView: false,
179
166
 
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { SearchResultsConfiguration, SortingOption } from '../../types';
2
+ import { SearchResultsConfiguration } from '../../types';
3
3
  import SearchResults from '../..';
4
4
  import { Navbar, Footer } from '../../../../src';
5
5
  import { TideLogo, language, languages, topLinks, navItems } from '../../../../src/content/navbar/placeholderData';
@@ -7,13 +7,6 @@ import { TideLogo, language, languages, topLinks, navItems } from '../../../../s
7
7
  interface RoundtripSearchResultsSelfContainedProps {}
8
8
 
9
9
  const RoundtripSearchResultsSelfContained: React.FC<RoundtripSearchResultsSelfContainedProps> = () => {
10
- // Sorting options
11
- const sortingOptions: SortingOption[] = [
12
- { key: 'price-asc', label: 'Price: Low to High' },
13
- { key: 'price-desc', label: 'Price: High to Low' },
14
- { key: 'rating-desc', label: 'Top Rated' }
15
- ];
16
-
17
10
  const configuration: SearchResultsConfiguration = {
18
11
  type: 'roundTrip',
19
12
  showFilters: true,
@@ -22,7 +15,6 @@ const RoundtripSearchResultsSelfContained: React.FC<RoundtripSearchResultsSelfCo
22
15
  apiKey: 'e9b95d79-de4c-41d6-ab7e-3dd429873058',
23
16
  catalogueIds: [1, 2]
24
17
  },
25
- sortingOptions: sortingOptions,
26
18
  showTabViews: false,
27
19
  showFlightResults: false,
28
20
  showHotelAccommodationResults: false,
@@ -1,11 +1,13 @@
1
1
  import { createSlice, PayloadAction } from '@reduxjs/toolkit';
2
- import { Filter, SearchResult } from '../types';
2
+ import { Filter } from '../types';
3
+ import { BookingPackageItem } from '@qite/tide-client/build/types';
3
4
 
4
5
  export interface SearchResultsState {
5
- results: SearchResult[];
6
+ results: BookingPackageItem[];
6
7
  isLoading: boolean;
7
8
  filters: Filter[];
8
9
  sortKey: string | null;
10
+ activeTab: string | null;
9
11
  currentPage: number;
10
12
  }
11
13
 
@@ -14,6 +16,7 @@ const initialState: SearchResultsState = {
14
16
  isLoading: false,
15
17
  filters: [],
16
18
  sortKey: null,
19
+ activeTab: 'compact',
17
20
  currentPage: 1
18
21
  };
19
22
 
@@ -21,7 +24,7 @@ const searchResultsSlice = createSlice({
21
24
  name: 'searchResults',
22
25
  initialState,
23
26
  reducers: {
24
- setResults(state, action: PayloadAction<{ results: any[] }>) {
27
+ setResults(state, action: PayloadAction<{ results: BookingPackageItem[] }>) {
25
28
  state.results = action.payload.results;
26
29
  },
27
30
  setIsLoading(state, action: PayloadAction<boolean>) {
@@ -45,6 +48,9 @@ const searchResultsSlice = createSlice({
45
48
  setSortKey(state, action: PayloadAction<string | null>) {
46
49
  state.sortKey = action.payload;
47
50
  },
51
+ setActiveTab(state, action: PayloadAction<string | null>) {
52
+ state.activeTab = action.payload;
53
+ },
48
54
  setCurrentPage(state, action: PayloadAction<number>) {
49
55
  state.currentPage = action.payload;
50
56
  },
@@ -53,11 +59,12 @@ const searchResultsSlice = createSlice({
53
59
  state.isLoading = false;
54
60
  state.filters = [];
55
61
  state.sortKey = null;
62
+ state.activeTab = 'compact';
56
63
  state.currentPage = 1;
57
64
  }
58
65
  }
59
66
  });
60
67
 
61
- export const { setResults, setIsLoading, setFilters, resetFilters, setSortKey, setCurrentPage, resetSearchState } = searchResultsSlice.actions;
68
+ export const { setResults, setIsLoading, setFilters, resetFilters, setSortKey, setActiveTab, setCurrentPage, resetSearchState } = searchResultsSlice.actions;
62
69
 
63
70
  export default searchResultsSlice.reducer;
@@ -29,10 +29,6 @@ export interface SearchResultsConfiguration {
29
29
  customCardRenderer?: (result: SearchResult) => ReactNode;
30
30
  onResultClick?: (id: string) => void;
31
31
 
32
- // Sorting
33
- sortingOptions?: SortingOption[];
34
- onSortChange?: (sortKey: string) => void;
35
-
36
32
  // Map view
37
33
  // not supported for now
38
34
  showMapView?: boolean;
@@ -59,6 +55,8 @@ export interface SearchResultsConfiguration {
59
55
  loading?: string;
60
56
  searchResultCTA?: string;
61
57
  };
58
+
59
+ cmsHotelData?: any[];
62
60
  }
63
61
 
64
62
  export type FilterType = 'checkbox' | 'toggle' | 'slider' | 'star-rating';
@@ -86,17 +84,6 @@ export interface Filter {
86
84
  selectedRating?: number; // For star-rating type
87
85
  }
88
86
 
89
- export interface Sort {
90
- label: string;
91
- icon?: ReactNode;
92
- }
93
-
94
- export interface SortingOption {
95
- key: 'price-asc' | 'price-desc' | 'duration-asc' | 'duration-desc' | 'rating-asc' | 'rating-desc';
96
- label: string;
97
- icon?: ReactNode;
98
- }
99
-
100
87
  export interface PaginationConfig {
101
88
  totalResults: number;
102
89
  currentPage: number;
@@ -112,9 +99,11 @@ export interface BaseSearchResult {
112
99
  description?: string;
113
100
  location?: string;
114
101
  tags?: Tag[];
115
- price: string;
102
+ price: string | number;
116
103
  ctaText: string;
117
104
  stars?: number;
105
+ accommodation?: string;
106
+ regime?: string;
118
107
  }
119
108
 
120
109
  export interface HotelResult extends BaseSearchResult {
@@ -159,3 +148,9 @@ export interface TravelClass {
159
148
  label: string;
160
149
  icon?: ReactNode;
161
150
  }
151
+
152
+ export interface SortingOption {
153
+ key: 'price-asc' | 'price-desc' | 'departure-date' | 'duration-asc' | 'duration-desc' | 'rating-asc' | 'rating-desc';
154
+ label: string;
155
+ icon?: ReactNode;
156
+ }
@@ -122,7 +122,8 @@
122
122
  "FLIGHT_DEPARTURE": "Departure",
123
123
  "FLIGHT_ARRIVAL": "Arrival",
124
124
  "ON_REQUEST": "On request",
125
- "CHANGES": "transfers"
125
+ "CHANGES": "transfers",
126
+ "PACKAGE_NOT_AVAILABLE": "Package not available"
126
127
  },
127
128
  "TRAVELERS_FORM": {
128
129
  "AGE": "Age",
@@ -155,6 +156,9 @@
155
156
  "BOOK_WITH_AGENT": "I want to book through my local travel agent",
156
157
  "CHOOSE_OFFICE": "I choose an office",
157
158
  "PERSON": "Person",
159
+ "REMOVE_TRAVELER": "Remove traveler",
160
+ "ADD_TRAVELER": "Add traveler",
161
+ "ADD_ROOM": "Add travel party",
158
162
  "COUNTRIES": {
159
163
  "BELGIUM": "Belgium",
160
164
  "NETHERLANDS": "Netherlands",
@@ -122,7 +122,8 @@
122
122
  "FLIGHT_DEPARTURE": "Départ",
123
123
  "FLIGHT_ARRIVAL": "Arrivée",
124
124
  "ON_REQUEST": "Sur demande",
125
- "CHANGES": "correspondances"
125
+ "CHANGES": "correspondances",
126
+ "PACKAGE_NOT_AVAILABLE": "Forfait non disponible"
126
127
  },
127
128
  "TRAVELERS_FORM": {
128
129
  "AGE": "Age",
@@ -155,6 +156,9 @@
155
156
  "BOOK_WITH_AGENT": "Je souhaite réserver auprès de mon agent de voyage local",
156
157
  "CHOOSE_OFFICE": "Je choisis une agence",
157
158
  "PERSON": "Personne",
159
+ "REMOVE_TRAVELER": "Supprimer le voyageur",
160
+ "ADD_TRAVELER": "Ajouter un voyageur",
161
+ "ADD_ROOM": "Ajouter un groupe de voyageurs",
158
162
  "COUNTRIES": {
159
163
  "BELGIUM": "Belgique",
160
164
  "NETHERLANDS": "Pays-Bas",
@@ -122,7 +122,8 @@
122
122
  "FLIGHT_DEPARTURE": "Vertrek",
123
123
  "FLIGHT_ARRIVAL": "Aankomst",
124
124
  "ON_REQUEST": "Op aanvraag",
125
- "CHANGES": "overstappen"
125
+ "CHANGES": "overstappen",
126
+ "PACKAGE_NOT_AVAILABLE": "Pakket niet beschikbaar"
126
127
  },
127
128
  "TRAVELERS_FORM": {
128
129
  "AGE": "Leeftijd",
@@ -155,6 +156,9 @@
155
156
  "BOOK_WITH_AGENT": "Ik wens te boeken bij mijn lokale reisagent",
156
157
  "CHOOSE_OFFICE": "Ik kies een kantoor",
157
158
  "PERSON": "Persoon",
159
+ "REMOVE_TRAVELER": "Verwijder reiziger",
160
+ "ADD_TRAVELER": "Voeg reiziger toe",
161
+ "ADD_ROOM": "Voeg reisgezelschap toe",
158
162
  "COUNTRIES": {
159
163
  "BELGIUM": "België",
160
164
  "NETHERLANDS": "Nederland",