@qite/tide-booking-component 1.4.34 → 1.4.35
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 +1627 -374
- package/build/build-cjs/qsm/types.d.ts +0 -1
- package/build/build-cjs/search-results/components/filters/filters.d.ts +2 -2
- package/build/build-cjs/search-results/components/flight/flight-results.d.ts +2 -0
- package/build/build-cjs/search-results/components/hotel/hotel-card.d.ts +1 -0
- package/build/build-cjs/search-results/components/itinerary/index.d.ts +2 -2
- package/build/build-cjs/search-results/store/search-results-slice.d.ts +11 -2
- package/build/build-cjs/search-results/types.d.ts +0 -14
- package/build/build-esm/index.js +1627 -374
- package/build/build-esm/qsm/types.d.ts +0 -1
- package/build/build-esm/search-results/components/filters/filters.d.ts +2 -2
- package/build/build-esm/search-results/components/flight/flight-results.d.ts +2 -0
- package/build/build-esm/search-results/components/hotel/hotel-card.d.ts +1 -0
- package/build/build-esm/search-results/components/itinerary/index.d.ts +2 -2
- package/build/build-esm/search-results/store/search-results-slice.d.ts +11 -2
- package/build/build-esm/search-results/types.d.ts +0 -14
- package/package.json +2 -2
- package/src/booking-wizard/features/booking/booking-self-contained.tsx +0 -1
- package/src/booking-wizard/features/travelers-form/controls/gender-control.tsx +5 -5
- package/src/booking-wizard/features/travelers-form/travelers-form.tsx +10 -10
- package/src/content/components/icon.tsx +1 -1
- package/src/content/features/content-page/content-page-self-contained.tsx +0 -1
- package/src/qsm/components/QSMContainer/qsm-container.tsx +15 -13
- package/src/qsm/components/mobile-filter-modal/index.tsx +12 -10
- package/src/qsm/components/travel-class-picker/index.tsx +5 -3
- package/src/qsm/components/travel-input/index.tsx +15 -12
- package/src/qsm/components/travel-input-group/index.tsx +14 -3
- package/src/qsm/components/travel-nationality-picker/index.tsx +5 -3
- package/src/qsm/components/travel-type-picker/index.tsx +5 -3
- package/src/qsm/qsm-configuration-context.ts +0 -1
- package/src/qsm/types.ts +0 -1
- package/src/search-results/components/filters/filters.tsx +15 -16
- package/src/search-results/components/flight/flight-results.tsx +168 -1099
- package/src/search-results/components/hotel/hotel-accommodation-results.tsx +21 -24
- package/src/search-results/components/hotel/hotel-card.tsx +4 -3
- package/src/search-results/components/icon.tsx +1 -1
- package/src/search-results/components/itinerary/index.tsx +229 -129
- package/src/search-results/components/round-trip/round-trip-results.tsx +1 -1
- package/src/search-results/components/search-results-container/search-results-container.tsx +45 -33
- package/src/search-results/components/spinner/spinner.tsx +3 -1
- package/src/search-results/components/tab-views/index.tsx +13 -7
- package/src/search-results/features/flights/flight-search-results-self-contained.tsx +1 -14
- package/src/search-results/features/hotels/hotel-search-results-self-contained.tsx +1 -14
- package/src/search-results/store/search-results-slice.ts +37 -3
- package/src/search-results/types.ts +0 -15
- package/src/shared/translations/ar-SA.json +70 -0
- package/src/shared/translations/da-DK.json +70 -0
- package/src/shared/translations/de-DE.json +70 -0
- package/src/shared/translations/en-GB.json +71 -1
- package/src/shared/translations/es-ES.json +70 -0
- package/src/shared/translations/fr-BE.json +71 -1
- package/src/shared/translations/fr-FR.json +70 -0
- package/src/shared/translations/is-IS.json +72 -2
- package/src/shared/translations/it-IT.json +70 -0
- package/src/shared/translations/ja-JP.json +72 -2
- package/src/shared/translations/nl-BE.json +70 -0
- package/src/shared/translations/nl-NL.json +70 -0
- package/src/shared/translations/no-NO.json +72 -2
- package/src/shared/translations/pl-PL.json +70 -0
- package/src/shared/translations/pt-PT.json +70 -0
- package/src/shared/translations/sv-SE.json +72 -2
- package/styles/components/_search.scss +7 -1
|
@@ -3,13 +3,13 @@ import { useDispatch, useSelector } from 'react-redux';
|
|
|
3
3
|
import { SearchResultsRootState } from '../../store/search-results-store';
|
|
4
4
|
import SearchResultsConfigurationContext from '../../search-results-configuration-context';
|
|
5
5
|
|
|
6
|
-
import { resetFilters, setSortKey, setResults, setIsLoading, setSelectedHotel } from '../../store/search-results-slice';
|
|
6
|
+
import { resetFilters, setSortKey, setResults, setIsLoading, setSelectedHotel, setBookingPackageDetails, setEntry } from '../../store/search-results-slice';
|
|
7
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
|
-
import { TideClientConfig,
|
|
12
|
+
import { TideClientConfig, detailsWL, search } from '@qite/tide-client';
|
|
13
13
|
import {
|
|
14
14
|
BookingPackageDestination,
|
|
15
15
|
BookingPackageDetailsRequest,
|
|
@@ -27,17 +27,21 @@ import TabViews from '../tab-views';
|
|
|
27
27
|
import HotelAccommodationResults from '../hotel/hotel-accommodation-results';
|
|
28
28
|
import RoundTripResults from '../round-trip/round-trip-results';
|
|
29
29
|
import { enrichFiltersWithResults } from '../filters/utility';
|
|
30
|
+
import FlightResults from '../flight/flight-results';
|
|
31
|
+
import { getTranslations } from '../../../shared/utils/localization-util';
|
|
30
32
|
|
|
31
33
|
const SearchResultsContainer: React.FC = () => {
|
|
32
34
|
const isMobile = useMediaQuery('(max-width: 1200px)');
|
|
33
35
|
const dispatch = useDispatch();
|
|
34
36
|
const context = useContext(SearchResultsConfigurationContext);
|
|
35
|
-
const
|
|
37
|
+
const translations = getTranslations(context?.languageCode ?? 'en-GB');
|
|
38
|
+
const { results, bookingPackageDetails, isLoading, filters, sortKey, selectedHotelId } = useSelector((state: SearchResultsRootState) => state.searchResults);
|
|
36
39
|
|
|
37
40
|
const [searchTrigger, setSearchTrigger] = useState(0);
|
|
38
41
|
const [initialFiltersSet, setInitialFiltersSet] = useState(false);
|
|
39
42
|
const [initialFilters, setInitialFilters] = useState<Filter[]>([]);
|
|
40
43
|
|
|
44
|
+
// seperate Search
|
|
41
45
|
useEffect(() => {
|
|
42
46
|
const runSearch = async () => {
|
|
43
47
|
dispatch(setIsLoading(true));
|
|
@@ -155,6 +159,7 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
155
159
|
runSearch();
|
|
156
160
|
}, [location.search, searchTrigger]);
|
|
157
161
|
|
|
162
|
+
// Seperate detailsCall
|
|
158
163
|
useEffect(() => {
|
|
159
164
|
const fetchPackageDetails = async () => {
|
|
160
165
|
if (!selectedHotelId || !context) return;
|
|
@@ -192,12 +197,10 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
192
197
|
}
|
|
193
198
|
};
|
|
194
199
|
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
// TODO: store flights / details in redux
|
|
200
|
-
// dispatch(setSelectedHotelDetails(details));
|
|
200
|
+
const detailsWLResponse = await detailsWL(config, detailsRequest);
|
|
201
|
+
console.log('Details with entryLight:', detailsWLResponse);
|
|
202
|
+
dispatch(setBookingPackageDetails({ details: detailsWLResponse?.payload?.bookingPackage }));
|
|
203
|
+
dispatch(setEntry({ entry: detailsWLResponse?.payload?.entry }));
|
|
201
204
|
} catch (err) {
|
|
202
205
|
console.error('Failed to fetch package details', err);
|
|
203
206
|
}
|
|
@@ -236,26 +239,23 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
236
239
|
return requestRooms;
|
|
237
240
|
};
|
|
238
241
|
|
|
239
|
-
const [
|
|
242
|
+
const [filtersOpen, setFiltersOpen] = useState(false);
|
|
243
|
+
const [itineraryOpen, setItineraryOpen] = useState(false);
|
|
240
244
|
|
|
241
245
|
const handleSortChange = (newSortKey: string) => {
|
|
242
246
|
dispatch(setSortKey(newSortKey));
|
|
243
247
|
};
|
|
244
248
|
|
|
245
|
-
const handleSetIsMobileFiltersOpen = () => {
|
|
246
|
-
setIsMobileFiltersOpen(!isMobileFiltersOpen);
|
|
247
|
-
};
|
|
248
|
-
|
|
249
249
|
useEffect(() => {
|
|
250
250
|
if (typeof document !== 'undefined') {
|
|
251
|
-
document.body.classList.toggle('has-overlay',
|
|
251
|
+
document.body.classList.toggle('has-overlay', filtersOpen);
|
|
252
252
|
}
|
|
253
|
-
}, [
|
|
253
|
+
}, [filtersOpen]);
|
|
254
254
|
|
|
255
255
|
const sortingOptions: SortingOption[] = [
|
|
256
|
-
{ key: 'price-asc', label:
|
|
257
|
-
{ key: 'price-desc', label:
|
|
258
|
-
{ key: 'departure-date', label:
|
|
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
259
|
];
|
|
260
260
|
|
|
261
261
|
return (
|
|
@@ -266,29 +266,37 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
266
266
|
{context.showFilters && (
|
|
267
267
|
<Filters
|
|
268
268
|
filters={filters}
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
isOpen={filtersOpen}
|
|
270
|
+
handleSetIsOpen={() => setFiltersOpen(!filtersOpen)}
|
|
271
271
|
handleApplyFilters={() => setSearchTrigger((prev) => prev + 1)}
|
|
272
272
|
isLoading={isLoading}
|
|
273
273
|
/>
|
|
274
274
|
)}
|
|
275
275
|
{context.type === 'hotel-flight' && (
|
|
276
|
-
<Itinerary
|
|
276
|
+
<Itinerary isOpen={itineraryOpen} handleSetIsOpen={() => setItineraryOpen(!itineraryOpen)} isLoading={isLoading} />
|
|
277
277
|
)}
|
|
278
278
|
{/* ---------------- Results ---------------- */}
|
|
279
279
|
<div className="search__results">
|
|
280
280
|
{isMobile && (
|
|
281
281
|
<div className="search__result-row">
|
|
282
|
-
<div className="
|
|
283
|
-
|
|
284
|
-
|
|
282
|
+
<div className="search__results__actions">
|
|
283
|
+
{context.showFilters && (
|
|
284
|
+
<div className="cta cta--filter" onClick={() => setFiltersOpen(true)}>
|
|
285
|
+
<Icon name="ui-filter" className="mobile-filters-button__icon" height={16} />
|
|
286
|
+
{translations.SRP.FILTERS}
|
|
287
|
+
</div>
|
|
288
|
+
)}
|
|
289
|
+
<div className="cta cta--filter" onClick={() => setItineraryOpen(true)}>
|
|
290
|
+
<Icon name="ui-calendar" className="mobile-filters-button__icon" height={16} />
|
|
291
|
+
{translations.SRP.SHOW_ITINERARY}
|
|
292
|
+
</div>
|
|
285
293
|
</div>
|
|
286
294
|
{sortingOptions && sortingOptions.length > 0 && (
|
|
287
295
|
<ItemPicker
|
|
288
296
|
items={sortingOptions}
|
|
289
297
|
selection={sortKey || undefined}
|
|
290
|
-
label=
|
|
291
|
-
placeholder=
|
|
298
|
+
label={translations.SRP.SORTBY}
|
|
299
|
+
placeholder={translations.SRP.SORTBY}
|
|
292
300
|
classModifier="travel-class-picker__items"
|
|
293
301
|
onPick={handleSortChange}
|
|
294
302
|
/>
|
|
@@ -300,7 +308,7 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
300
308
|
<span className="search__result-row-text">
|
|
301
309
|
{!isLoading && (
|
|
302
310
|
<>
|
|
303
|
-
{results?.length ?? 4} {
|
|
311
|
+
{results?.length ?? 4} {translations.SRP.TOTAL_RESULTS_LABEL}
|
|
304
312
|
</>
|
|
305
313
|
)}
|
|
306
314
|
</span>
|
|
@@ -309,8 +317,8 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
309
317
|
<ItemPicker
|
|
310
318
|
items={sortingOptions}
|
|
311
319
|
selection={sortKey || undefined}
|
|
312
|
-
label=
|
|
313
|
-
placeholder=
|
|
320
|
+
label={translations.SRP.SORTBY}
|
|
321
|
+
placeholder={translations.SRP.SORTBY}
|
|
314
322
|
classModifier="travel-class-picker__items"
|
|
315
323
|
onPick={handleSortChange}
|
|
316
324
|
/>
|
|
@@ -321,14 +329,18 @@ const SearchResultsContainer: React.FC = () => {
|
|
|
321
329
|
<div className="search__results__wrapper">
|
|
322
330
|
{context.showTabViews && <TabViews />}
|
|
323
331
|
|
|
324
|
-
{context.showRoundTripResults && <RoundTripResults />}
|
|
332
|
+
{/* {context.showRoundTripResults && <RoundTripResults />} */}
|
|
325
333
|
|
|
326
|
-
{
|
|
334
|
+
{context.showFlightResults && bookingPackageDetails?.outwardFlights && (
|
|
335
|
+
<FlightResults flights={bookingPackageDetails.outwardFlights} isDeparture={true} />
|
|
336
|
+
)}
|
|
327
337
|
|
|
328
338
|
{context.showHotelAccommodationResults && <HotelAccommodationResults isLoading={isLoading} context={context} />}
|
|
329
339
|
{/* {context.showFlightAccommodationResults && <FlightAccommodationResults />} */}
|
|
330
340
|
|
|
331
|
-
{
|
|
341
|
+
{context.showFlightResults && bookingPackageDetails?.returnFlights && (
|
|
342
|
+
<FlightResults flights={bookingPackageDetails.returnFlights} isDeparture={false} />
|
|
343
|
+
)}
|
|
332
344
|
</div>
|
|
333
345
|
</div>
|
|
334
346
|
</div>
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import SearchResultsConfigurationContext from '../../search-results-configuration-context';
|
|
3
|
+
import { getTranslations } from '../../../shared/utils/localization-util';
|
|
3
4
|
|
|
4
5
|
const Spinner: React.FC = () => {
|
|
5
6
|
const context = useContext(SearchResultsConfigurationContext);
|
|
7
|
+
const translations = getTranslations(context?.languageCode ?? 'en-GB');
|
|
6
8
|
return (
|
|
7
9
|
<div className="spinner__container">
|
|
8
10
|
<span className="spinner__icon" />
|
|
9
|
-
<span className="spinner__label">{
|
|
11
|
+
<span className="spinner__label">{translations?.SRP.LOADING}</span>
|
|
10
12
|
</div>
|
|
11
13
|
);
|
|
12
14
|
};
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
2
|
import Icon from '../icon';
|
|
3
3
|
import { useDispatch, useSelector } from 'react-redux';
|
|
4
4
|
import { SearchResultsRootState } from '../../store/search-results-store';
|
|
5
5
|
import { setActiveTab } from '../../store/search-results-slice';
|
|
6
|
+
import { getTranslations } from '../../../shared/utils/localization-util';
|
|
7
|
+
import SearchResultsConfigurationContext from '../../search-results-configuration-context';
|
|
6
8
|
|
|
7
9
|
interface TabViewsProps {}
|
|
8
10
|
|
|
9
11
|
const TabViews: React.FC<TabViewsProps> = () => {
|
|
12
|
+
const context = useContext(SearchResultsConfigurationContext);
|
|
13
|
+
const translations = getTranslations(context?.languageCode ?? 'en-GB');
|
|
14
|
+
|
|
10
15
|
const dispatch = useDispatch();
|
|
16
|
+
|
|
11
17
|
const { activeTab } = useSelector((state: SearchResultsRootState) => state.searchResults);
|
|
12
18
|
|
|
13
19
|
const handleSortChange = (tab: string) => {
|
|
@@ -21,21 +27,21 @@ const TabViews: React.FC<TabViewsProps> = () => {
|
|
|
21
27
|
className={`search__results__tab-view ${activeTab === 'extended' ? 'search__results__tab-view--active' : ''}`}
|
|
22
28
|
onClick={() => handleSortChange('extended')}>
|
|
23
29
|
<Icon name="ui-extended" height={16} />
|
|
24
|
-
|
|
30
|
+
{translations.SRP.EXTENDED}
|
|
25
31
|
</button>
|
|
26
32
|
<button
|
|
27
33
|
type="button"
|
|
28
34
|
className={`search__results__tab-view ${activeTab === 'compact' ? 'search__results__tab-view--active' : ''}`}
|
|
29
35
|
onClick={() => handleSortChange('compact')}>
|
|
30
36
|
<Icon name="ui-compact" height={16} />
|
|
31
|
-
|
|
37
|
+
{translations.SRP.COMPACT}
|
|
32
38
|
</button>
|
|
33
39
|
<button
|
|
34
40
|
type="button"
|
|
35
|
-
className={`search__results__tab-view ${activeTab === '
|
|
36
|
-
onClick={() => handleSortChange('
|
|
37
|
-
<Icon name="ui-
|
|
38
|
-
|
|
41
|
+
className={`search__results__tab-view ${activeTab === 'list' ? 'search__results__tab-view--active' : ''}`}
|
|
42
|
+
onClick={() => handleSortChange('list')}>
|
|
43
|
+
<Icon name="ui-list" height={16} />
|
|
44
|
+
{translations.SRP.LIST}
|
|
39
45
|
</button>
|
|
40
46
|
</div>
|
|
41
47
|
);
|
|
@@ -245,23 +245,10 @@ const FlightSearchResultsSelfContained: React.FC<FlightSearchResultsSelfContaine
|
|
|
245
245
|
// Pagination
|
|
246
246
|
|
|
247
247
|
// State & UI
|
|
248
|
-
noResultsLabel: 'No products found.',
|
|
249
248
|
isLoading: false,
|
|
250
249
|
customSpinner: null,
|
|
251
250
|
|
|
252
|
-
|
|
253
|
-
filters: 'Filters',
|
|
254
|
-
filterTitle: 'Filter resultaten',
|
|
255
|
-
resetButton: 'Reset',
|
|
256
|
-
sortBy: 'Sorteren op',
|
|
257
|
-
noResults: 'Geen resultaten gevonden.',
|
|
258
|
-
totalResultsLabel: 'resultaten gevonden',
|
|
259
|
-
luggageIncluded: 'Bagage inbegrepen',
|
|
260
|
-
apply: 'Toepassen',
|
|
261
|
-
loading: 'Laden...',
|
|
262
|
-
cancel: 'Annuleren',
|
|
263
|
-
searchResultCTA: 'Bekijk details'
|
|
264
|
-
}
|
|
251
|
+
languageCode: 'en-GB'
|
|
265
252
|
};
|
|
266
253
|
|
|
267
254
|
return (
|
|
@@ -171,23 +171,10 @@ const HotelSearchResultsSelfContained: React.FC<HotelSearchResultsSelfContainedP
|
|
|
171
171
|
// },
|
|
172
172
|
|
|
173
173
|
// State & UI
|
|
174
|
-
noResultsLabel: 'No products found.',
|
|
175
174
|
isLoading: false,
|
|
176
175
|
customSpinner: null,
|
|
177
176
|
|
|
178
|
-
|
|
179
|
-
filters: 'Filters',
|
|
180
|
-
filterTitle: 'Filter resultaten',
|
|
181
|
-
resetButton: 'Reset',
|
|
182
|
-
sortBy: 'Sorteren op',
|
|
183
|
-
noResults: 'Geen resultaten gevonden.',
|
|
184
|
-
totalResultsLabel: 'resultaten gevonden',
|
|
185
|
-
luggageIncluded: 'Bagage inbegrepen',
|
|
186
|
-
apply: 'Toepassen',
|
|
187
|
-
loading: 'Laden...',
|
|
188
|
-
cancel: 'Annuleren',
|
|
189
|
-
searchResultCTA: 'Bekijk details'
|
|
190
|
-
}
|
|
177
|
+
languageCode: 'en-GB'
|
|
191
178
|
};
|
|
192
179
|
|
|
193
180
|
return (
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
|
2
2
|
import { Filter } from '../types';
|
|
3
|
-
import { BookingPackageItem } from '@qite/tide-client/build/types';
|
|
3
|
+
import { BookingPackage, BookingPackageItem, EntryLight } from '@qite/tide-client/build/types';
|
|
4
4
|
|
|
5
5
|
export interface SearchResultsState {
|
|
6
6
|
results: BookingPackageItem[];
|
|
7
7
|
selectedHotelId: number | null;
|
|
8
|
+
bookingPackageDetails: BookingPackage | null;
|
|
9
|
+
entry: EntryLight | null;
|
|
8
10
|
isLoading: boolean;
|
|
9
11
|
filters: Filter[];
|
|
10
12
|
sortKey: string | null;
|
|
@@ -15,6 +17,8 @@ export interface SearchResultsState {
|
|
|
15
17
|
const initialState: SearchResultsState = {
|
|
16
18
|
results: [],
|
|
17
19
|
selectedHotelId: null,
|
|
20
|
+
bookingPackageDetails: null,
|
|
21
|
+
entry: null,
|
|
18
22
|
isLoading: false,
|
|
19
23
|
filters: [],
|
|
20
24
|
sortKey: null,
|
|
@@ -32,6 +36,24 @@ const searchResultsSlice = createSlice({
|
|
|
32
36
|
setSelectedHotel(state, action: PayloadAction<number | null>) {
|
|
33
37
|
state.selectedHotelId = action.payload;
|
|
34
38
|
},
|
|
39
|
+
setBookingPackageDetails(state, action: PayloadAction<{ details: BookingPackage }>) {
|
|
40
|
+
state.bookingPackageDetails = action.payload.details;
|
|
41
|
+
},
|
|
42
|
+
setEntry(state, action: PayloadAction<{ entry: EntryLight }>) {
|
|
43
|
+
state.entry = action.payload.entry;
|
|
44
|
+
},
|
|
45
|
+
selectFlight(state, action: PayloadAction<{ flightOptionId: string; isDeparture: boolean }>) {
|
|
46
|
+
if (!state.bookingPackageDetails) return;
|
|
47
|
+
|
|
48
|
+
const { flightOptionId, isDeparture } = action.payload;
|
|
49
|
+
|
|
50
|
+
const flightKey = isDeparture ? 'outwardFlights' : 'returnFlights';
|
|
51
|
+
|
|
52
|
+
state.bookingPackageDetails[flightKey] = state.bookingPackageDetails[flightKey].map((flight) => ({
|
|
53
|
+
...flight,
|
|
54
|
+
isSelected: flight.flightOptionId === flightOptionId
|
|
55
|
+
}));
|
|
56
|
+
},
|
|
35
57
|
setIsLoading(state, action: PayloadAction<boolean>) {
|
|
36
58
|
state.isLoading = action.payload;
|
|
37
59
|
},
|
|
@@ -70,7 +92,19 @@ const searchResultsSlice = createSlice({
|
|
|
70
92
|
}
|
|
71
93
|
});
|
|
72
94
|
|
|
73
|
-
export const {
|
|
74
|
-
|
|
95
|
+
export const {
|
|
96
|
+
setResults,
|
|
97
|
+
setSelectedHotel,
|
|
98
|
+
setBookingPackageDetails,
|
|
99
|
+
setEntry,
|
|
100
|
+
selectFlight,
|
|
101
|
+
setIsLoading,
|
|
102
|
+
setFilters,
|
|
103
|
+
resetFilters,
|
|
104
|
+
setSortKey,
|
|
105
|
+
setActiveTab,
|
|
106
|
+
setCurrentPage,
|
|
107
|
+
resetSearchState
|
|
108
|
+
} = searchResultsSlice.actions;
|
|
75
109
|
|
|
76
110
|
export default searchResultsSlice.reducer;
|
|
@@ -37,24 +37,9 @@ export interface SearchResultsConfiguration {
|
|
|
37
37
|
// pagination?: PaginationConfig;
|
|
38
38
|
|
|
39
39
|
// State
|
|
40
|
-
noResultsLabel?: string;
|
|
41
40
|
isLoading?: boolean;
|
|
42
41
|
customSpinner?: ReactNode;
|
|
43
42
|
|
|
44
|
-
translations?: {
|
|
45
|
-
filters?: string;
|
|
46
|
-
filterTitle?: string;
|
|
47
|
-
resetButton?: string;
|
|
48
|
-
sortBy?: string;
|
|
49
|
-
noResults?: string;
|
|
50
|
-
totalResultsLabel?: string;
|
|
51
|
-
luggageIncluded?: string;
|
|
52
|
-
cancel?: string;
|
|
53
|
-
apply?: string;
|
|
54
|
-
loading?: string;
|
|
55
|
-
searchResultCTA?: string;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
43
|
cmsHotelData?: any[];
|
|
59
44
|
languageCode?: string;
|
|
60
45
|
}
|
|
@@ -134,8 +134,11 @@
|
|
|
134
134
|
"CHILD": "طفل",
|
|
135
135
|
"CHILDREN": "أطفال",
|
|
136
136
|
"GENDER": "اللقب",
|
|
137
|
+
"GENDER_ID": "الجنس حسب جواز السفر/بطاقة الهوية",
|
|
137
138
|
"MALE": "السيد",
|
|
139
|
+
"MALE_GENDER": "ذكر",
|
|
138
140
|
"FEMALE": "السيدة",
|
|
141
|
+
"FEMALE_GENDER": "أنثى",
|
|
139
142
|
"OTHER": "آخر",
|
|
140
143
|
"MAIN_BOOKER": "الحاجز الرئيسي",
|
|
141
144
|
"FIRST_NAME": "الاسم الأول",
|
|
@@ -245,5 +248,72 @@
|
|
|
245
248
|
"LABEL_IDLE": "طباعة العرض",
|
|
246
249
|
"LABEL_CREATING": "جارٍ إنشاء العرض…",
|
|
247
250
|
"LABEL_PRINTING": "جارٍ إنشاء ملف PDF…"
|
|
251
|
+
},
|
|
252
|
+
"QSM": {
|
|
253
|
+
"MULTIDESTINATION": "وجهات متعددة",
|
|
254
|
+
"PACKAGES": "باقات",
|
|
255
|
+
"TRANSPORT_HOTEL": "النقل + الفندق",
|
|
256
|
+
"ACCOMMODATION": "الإقامة",
|
|
257
|
+
"TRANSPORTS": "وسائل النقل",
|
|
258
|
+
"TICKET_ONLY": "تذكرة فقط",
|
|
259
|
+
"RENT_A_CAR": "تأجير سيارة",
|
|
260
|
+
"TRANSFERS": "خدمات النقل",
|
|
261
|
+
"CRUISES": "رحلات بحرية",
|
|
262
|
+
"ONE_ACCOMMODATION": "إقامة واحدة",
|
|
263
|
+
"MULTIPLE_ACCOMMODATIONS": "إقامات متعددة",
|
|
264
|
+
"TRAVEL_CLASS_LABEL": "درجة السفر",
|
|
265
|
+
"TRAVEL_CLASS_PLACEHOLDER": "اختر درجة السفر",
|
|
266
|
+
"TRAVEL_TYPE_LABEL": "نوع السفر",
|
|
267
|
+
"TRAVEL_TYPE_PLACEHOLDER": "اختر نوع السفر",
|
|
268
|
+
"NATIONALITY_LABEL": "الجنسية",
|
|
269
|
+
"NATIONALITY_PLACEHOLDER": "اختر الجنسية",
|
|
270
|
+
"TRAVELERS_LABEL": "من المسافر؟",
|
|
271
|
+
"ADD_ROOM": "إضافة غرفة",
|
|
272
|
+
"REMOVE_ROOM": "إزالة غرفة",
|
|
273
|
+
"MAX_TRAVELERS_REACHED": "لقد وصلت إلى الحد الأقصى لعدد المسافرين",
|
|
274
|
+
"ADULTS": "البالغون",
|
|
275
|
+
"CHILDREN": "الأطفال",
|
|
276
|
+
"BABIES": "الرضع",
|
|
277
|
+
"CHOOSE_DATES": "اختر التواريخ",
|
|
278
|
+
"DEPARTURE_DATE": "تاريخ المغادرة",
|
|
279
|
+
"RETURN_DATE": "تاريخ العودة",
|
|
280
|
+
"CONFIRM": "تأكيد",
|
|
281
|
+
"TRAVELERS": "المسافرون"
|
|
282
|
+
},
|
|
283
|
+
"SRP": {
|
|
284
|
+
"NO_RESULTS": "لم يتم العثور على نتائج.",
|
|
285
|
+
"TOTAL_RESULTS_LABEL": "تم العثور على باقات",
|
|
286
|
+
"RESET": "إعادة تعيين",
|
|
287
|
+
"LUGGAGEINCLUDED": "الأمتعة مشمولة",
|
|
288
|
+
"CANCEL": "إلغاء",
|
|
289
|
+
"APPLY": "تطبيق",
|
|
290
|
+
"LOADING": "جارٍ التحميل...",
|
|
291
|
+
"SEARCHRESULTCTA": "عرض التفاصيل",
|
|
292
|
+
"SORTBY": "ترتيب حسب",
|
|
293
|
+
"PRICE_ASC": "السعر (من الأقل إلى الأعلى)",
|
|
294
|
+
"PRICE_DESC": "السعر (من الأعلى إلى الأقل)",
|
|
295
|
+
"DEPARTURE_ASC": "تاريخ المغادرة (الأقرب أولاً)",
|
|
296
|
+
"FILTERS": "عوامل التصفية",
|
|
297
|
+
"SHOW_ITINERARY": "عرض خط سير الرحلة",
|
|
298
|
+
"ITINERARY_TITLE": "ملخص رحلتك",
|
|
299
|
+
"DOSSIER_NUMBER": "رقم الملف",
|
|
300
|
+
"PACKAGE_PRICE_PER_PERSON": "سعر الباقة للشخص الواحد",
|
|
301
|
+
"TOTAL": "الإجمالي",
|
|
302
|
+
"DAY_BY_DAY": "رحلتك يوماً بيوم",
|
|
303
|
+
"START": "البداية",
|
|
304
|
+
"END": "النهاية",
|
|
305
|
+
"EXTENDED": "موسع",
|
|
306
|
+
"COMPACT": "مضغوط",
|
|
307
|
+
"LIST": "قائمة",
|
|
308
|
+
"SELECT": "اختيار",
|
|
309
|
+
"DEPARTURE": "المغادرة",
|
|
310
|
+
"RETURN": "العودة",
|
|
311
|
+
"DIRECT": "مباشر",
|
|
312
|
+
"STOPS": "محطات",
|
|
313
|
+
"STOP": "محطة",
|
|
314
|
+
"STOP_TIME": "مدة التوقف",
|
|
315
|
+
"ACCOMMODATION": "الإقامة",
|
|
316
|
+
"VIEW_DETAILS": "عرض التفاصيل",
|
|
317
|
+
"NIGHTS": "ليالٍ"
|
|
248
318
|
}
|
|
249
319
|
}
|
|
@@ -134,8 +134,11 @@
|
|
|
134
134
|
"CHILD": "barn",
|
|
135
135
|
"CHILDREN": "børn",
|
|
136
136
|
"GENDER": "Tiltaleform",
|
|
137
|
+
"GENDER_ID": "Køn ifølge pas/ID-kort",
|
|
137
138
|
"MALE": "Hr.",
|
|
139
|
+
"MALE_GENDER": "Mand",
|
|
138
140
|
"FEMALE": "Fr.",
|
|
141
|
+
"FEMALE_GENDER": "Kvinde",
|
|
139
142
|
"OTHER": "Andet",
|
|
140
143
|
"MAIN_BOOKER": "Hovedbooker",
|
|
141
144
|
"FIRST_NAME": "Fornavn",
|
|
@@ -245,5 +248,72 @@
|
|
|
245
248
|
"LABEL_IDLE": "Print tilbud",
|
|
246
249
|
"LABEL_CREATING": "Genererer tilbud…",
|
|
247
250
|
"LABEL_PRINTING": "Genererer PDF…"
|
|
251
|
+
},
|
|
252
|
+
"QSM": {
|
|
253
|
+
"MULTIDESTINATION": "Flere destinationer",
|
|
254
|
+
"PACKAGES": "Pakkerejser",
|
|
255
|
+
"TRANSPORT_HOTEL": "Transport + hotel",
|
|
256
|
+
"ACCOMMODATION": "Indkvartering",
|
|
257
|
+
"TRANSPORTS": "Transport",
|
|
258
|
+
"TICKET_ONLY": "Kun billet",
|
|
259
|
+
"RENT_A_CAR": "Lej en bil",
|
|
260
|
+
"TRANSFERS": "Transportservice",
|
|
261
|
+
"CRUISES": "Krydstogter",
|
|
262
|
+
"ONE_ACCOMMODATION": "Én indkvartering",
|
|
263
|
+
"MULTIPLE_ACCOMMODATIONS": "Flere indkvarteringer",
|
|
264
|
+
"TRAVEL_CLASS_LABEL": "Rejseklasse",
|
|
265
|
+
"TRAVEL_CLASS_PLACEHOLDER": "Vælg rejseklasse",
|
|
266
|
+
"TRAVEL_TYPE_LABEL": "Rejsetype",
|
|
267
|
+
"TRAVEL_TYPE_PLACEHOLDER": "Vælg rejsetype",
|
|
268
|
+
"NATIONALITY_LABEL": "Nationalitet",
|
|
269
|
+
"NATIONALITY_PLACEHOLDER": "Vælg nationalitet",
|
|
270
|
+
"TRAVELERS_LABEL": "Hvem rejser?",
|
|
271
|
+
"ADD_ROOM": "Tilføj værelse",
|
|
272
|
+
"REMOVE_ROOM": "Fjern værelse",
|
|
273
|
+
"MAX_TRAVELERS_REACHED": "Du har nået det maksimale antal rejsende",
|
|
274
|
+
"ADULTS": "Voksne",
|
|
275
|
+
"CHILDREN": "Børn",
|
|
276
|
+
"BABIES": "Spædbørn",
|
|
277
|
+
"CHOOSE_DATES": "Vælg datoer",
|
|
278
|
+
"DEPARTURE_DATE": "Afrejsedato",
|
|
279
|
+
"RETURN_DATE": "Hjemrejsedato",
|
|
280
|
+
"CONFIRM": "Bekræft",
|
|
281
|
+
"TRAVELERS": "Rejsende"
|
|
282
|
+
},
|
|
283
|
+
"SRP": {
|
|
284
|
+
"NO_RESULTS": "Ingen resultater fundet.",
|
|
285
|
+
"TOTAL_RESULTS_LABEL": "Fundne pakker",
|
|
286
|
+
"RESET": "Nulstil",
|
|
287
|
+
"LUGGAGEINCLUDED": "Bagage inkluderet",
|
|
288
|
+
"CANCEL": "Annuller",
|
|
289
|
+
"APPLY": "Anvend",
|
|
290
|
+
"LOADING": "Indlæser...",
|
|
291
|
+
"SEARCHRESULTCTA": "Se detaljer",
|
|
292
|
+
"SORTBY": "Sorter efter",
|
|
293
|
+
"PRICE_ASC": "Pris (lav til høj)",
|
|
294
|
+
"PRICE_DESC": "Pris (høj til lav)",
|
|
295
|
+
"DEPARTURE_ASC": "Afrejsedato (snarest først)",
|
|
296
|
+
"FILTERS": "Filtre",
|
|
297
|
+
"SHOW_ITINERARY": "Vis rejseplan",
|
|
298
|
+
"ITINERARY_TITLE": "Din rejseoversigt",
|
|
299
|
+
"DOSSIER_NUMBER": "Sagsnummer",
|
|
300
|
+
"PACKAGE_PRICE_PER_PERSON": "pakkepris pr. person",
|
|
301
|
+
"TOTAL": "i alt",
|
|
302
|
+
"DAY_BY_DAY": "Din rejse dag for dag",
|
|
303
|
+
"START": "start",
|
|
304
|
+
"END": "slut",
|
|
305
|
+
"EXTENDED": "Udvidet",
|
|
306
|
+
"COMPACT": "Kompakt",
|
|
307
|
+
"LIST": "Liste",
|
|
308
|
+
"SELECT": "Vælg",
|
|
309
|
+
"DEPARTURE": "Afrejse",
|
|
310
|
+
"RETURN": "Hjemrejse",
|
|
311
|
+
"DIRECT": "Direkte",
|
|
312
|
+
"STOPS": "stop",
|
|
313
|
+
"STOP": "stop",
|
|
314
|
+
"STOP_TIME": "Skiftetid",
|
|
315
|
+
"ACCOMMODATION": "Indkvartering",
|
|
316
|
+
"VIEW_DETAILS": "Se detaljer",
|
|
317
|
+
"NIGHTS": "nætter"
|
|
248
318
|
}
|
|
249
319
|
}
|
|
@@ -134,8 +134,11 @@
|
|
|
134
134
|
"CHILD": "Kind",
|
|
135
135
|
"CHILDREN": "Kinder",
|
|
136
136
|
"GENDER": "Anrede",
|
|
137
|
+
"GENDER_ID": "Geschlecht laut Reisepass/Personalausweis",
|
|
137
138
|
"MALE": "Herr",
|
|
139
|
+
"MALE_GENDER": "Männlich",
|
|
138
140
|
"FEMALE": "Frau",
|
|
141
|
+
"FEMALE_GENDER": "Weiblich",
|
|
139
142
|
"OTHER": "Andere",
|
|
140
143
|
"MAIN_BOOKER": "Hauptbucher",
|
|
141
144
|
"FIRST_NAME": "Vorname",
|
|
@@ -245,5 +248,72 @@
|
|
|
245
248
|
"LABEL_IDLE": "Angebot drucken",
|
|
246
249
|
"LABEL_CREATING": "Angebot wird erstellt…",
|
|
247
250
|
"LABEL_PRINTING": "PDF wird erstellt…"
|
|
251
|
+
},
|
|
252
|
+
"QSM": {
|
|
253
|
+
"MULTIDESTINATION": "Mehrere Reiseziele",
|
|
254
|
+
"PACKAGES": "Reisepakete",
|
|
255
|
+
"TRANSPORT_HOTEL": "Transport + Hotel",
|
|
256
|
+
"ACCOMMODATION": "Unterkunft",
|
|
257
|
+
"TRANSPORTS": "Transport",
|
|
258
|
+
"TICKET_ONLY": "Nur Ticket",
|
|
259
|
+
"RENT_A_CAR": "Mietwagen",
|
|
260
|
+
"TRANSFERS": "Transfers",
|
|
261
|
+
"CRUISES": "Kreuzfahrten",
|
|
262
|
+
"ONE_ACCOMMODATION": "Eine Unterkunft",
|
|
263
|
+
"MULTIPLE_ACCOMMODATIONS": "Mehrere Unterkünfte",
|
|
264
|
+
"TRAVEL_CLASS_LABEL": "Reiseklasse",
|
|
265
|
+
"TRAVEL_CLASS_PLACEHOLDER": "Reiseklasse auswählen",
|
|
266
|
+
"TRAVEL_TYPE_LABEL": "Reiseart",
|
|
267
|
+
"TRAVEL_TYPE_PLACEHOLDER": "Reiseart auswählen",
|
|
268
|
+
"NATIONALITY_LABEL": "Staatsangehörigkeit",
|
|
269
|
+
"NATIONALITY_PLACEHOLDER": "Staatsangehörigkeit auswählen",
|
|
270
|
+
"TRAVELERS_LABEL": "Wer reist?",
|
|
271
|
+
"ADD_ROOM": "Zimmer hinzufügen",
|
|
272
|
+
"REMOVE_ROOM": "Zimmer entfernen",
|
|
273
|
+
"MAX_TRAVELERS_REACHED": "Sie haben die maximale Anzahl an Reisenden erreicht",
|
|
274
|
+
"ADULTS": "Erwachsene",
|
|
275
|
+
"CHILDREN": "Kinder",
|
|
276
|
+
"BABIES": "Babys",
|
|
277
|
+
"CHOOSE_DATES": "Daten auswählen",
|
|
278
|
+
"DEPARTURE_DATE": "Abreisedatum",
|
|
279
|
+
"RETURN_DATE": "Rückreisedatum",
|
|
280
|
+
"CONFIRM": "Bestätigen",
|
|
281
|
+
"TRAVELERS": "Reisende"
|
|
282
|
+
},
|
|
283
|
+
"SRP": {
|
|
284
|
+
"NO_RESULTS": "Keine Ergebnisse gefunden.",
|
|
285
|
+
"TOTAL_RESULTS_LABEL": "Gefundene Pakete",
|
|
286
|
+
"RESET": "Zurücksetzen",
|
|
287
|
+
"LUGGAGEINCLUDED": "Gepäck inklusive",
|
|
288
|
+
"CANCEL": "Abbrechen",
|
|
289
|
+
"APPLY": "Anwenden",
|
|
290
|
+
"LOADING": "Wird geladen...",
|
|
291
|
+
"SEARCHRESULTCTA": "Details anzeigen",
|
|
292
|
+
"SORTBY": "Sortieren nach",
|
|
293
|
+
"PRICE_ASC": "Preis (aufsteigend)",
|
|
294
|
+
"PRICE_DESC": "Preis (absteigend)",
|
|
295
|
+
"DEPARTURE_ASC": "Abreisedatum (früheste zuerst)",
|
|
296
|
+
"FILTERS": "Filter",
|
|
297
|
+
"SHOW_ITINERARY": "Reiseverlauf anzeigen",
|
|
298
|
+
"ITINERARY_TITLE": "Ihre Reiseübersicht",
|
|
299
|
+
"DOSSIER_NUMBER": "Vorgangsnummer",
|
|
300
|
+
"PACKAGE_PRICE_PER_PERSON": "Paketpreis pro Person",
|
|
301
|
+
"TOTAL": "Gesamt",
|
|
302
|
+
"DAY_BY_DAY": "Ihre Reise Tag für Tag",
|
|
303
|
+
"START": "Start",
|
|
304
|
+
"END": "Ende",
|
|
305
|
+
"EXTENDED": "Erweitert",
|
|
306
|
+
"COMPACT": "Kompakt",
|
|
307
|
+
"LIST": "Liste",
|
|
308
|
+
"SELECT": "Auswählen",
|
|
309
|
+
"DEPARTURE": "Abreise",
|
|
310
|
+
"RETURN": "Rückreise",
|
|
311
|
+
"DIRECT": "Direkt",
|
|
312
|
+
"STOPS": "Stopps",
|
|
313
|
+
"STOP": "Stopp",
|
|
314
|
+
"STOP_TIME": "Umsteigezeit",
|
|
315
|
+
"ACCOMMODATION": "Unterkunft",
|
|
316
|
+
"VIEW_DETAILS": "Details anzeigen",
|
|
317
|
+
"NIGHTS": "Nächte"
|
|
248
318
|
}
|
|
249
319
|
}
|