@qite/tide-booking-component 1.4.103 → 1.4.105
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 +2782 -1052
- package/build/build-cjs/src/search-results/components/excursions/day-by-day-excursions.d.ts +4 -0
- package/build/build-cjs/src/search-results/components/excursions/excursion-details.d.ts +3 -0
- package/build/build-cjs/src/search-results/components/excursions/excursion-results.d.ts +8 -0
- package/build/build-cjs/src/search-results/components/filters/filters.d.ts +2 -0
- package/build/build-cjs/src/search-results/components/hotel/hotel-accommodation-results.d.ts +1 -0
- package/build/build-cjs/src/search-results/store/search-results-selectors.d.ts +546 -0
- package/build/build-cjs/src/search-results/store/search-results-slice.d.ts +55 -8
- package/build/build-cjs/src/search-results/types.d.ts +40 -2
- package/build/build-cjs/src/search-results/utils/query-utils.d.ts +1 -0
- package/build/build-cjs/src/search-results/utils/search-results-utils.d.ts +8 -6
- package/build/build-cjs/src/shared/components/flyin/flyin.d.ts +4 -3
- package/build/build-cjs/src/shared/components/flyin/packaging-flights-flyin.d.ts +7 -0
- package/build/build-cjs/src/shared/utils/localization-util.d.ts +3 -0
- package/build/build-cjs/src/shared/utils/tide-api-utils.d.ts +6 -0
- package/build/build-esm/index.js +2735 -1023
- package/build/build-esm/src/search-results/components/excursions/day-by-day-excursions.d.ts +4 -0
- package/build/build-esm/src/search-results/components/excursions/excursion-details.d.ts +3 -0
- package/build/build-esm/src/search-results/components/excursions/excursion-results.d.ts +8 -0
- package/build/build-esm/src/search-results/components/filters/filters.d.ts +2 -0
- package/build/build-esm/src/search-results/components/hotel/hotel-accommodation-results.d.ts +1 -0
- package/build/build-esm/src/search-results/store/search-results-selectors.d.ts +546 -0
- package/build/build-esm/src/search-results/store/search-results-slice.d.ts +55 -8
- package/build/build-esm/src/search-results/types.d.ts +40 -2
- package/build/build-esm/src/search-results/utils/query-utils.d.ts +1 -0
- package/build/build-esm/src/search-results/utils/search-results-utils.d.ts +8 -6
- package/build/build-esm/src/shared/components/flyin/flyin.d.ts +4 -3
- package/build/build-esm/src/shared/components/flyin/packaging-flights-flyin.d.ts +7 -0
- package/build/build-esm/src/shared/utils/localization-util.d.ts +3 -0
- package/build/build-esm/src/shared/utils/tide-api-utils.d.ts +6 -0
- package/package.json +2 -2
- package/src/booking-wizard/features/flight-options/index.tsx +6 -2
- package/src/search-results/components/excursions/day-by-day-excursions.tsx +169 -0
- package/src/search-results/components/excursions/excursion-details.tsx +340 -0
- package/src/search-results/components/excursions/excursion-results.tsx +186 -0
- package/src/search-results/components/filters/filters.tsx +8 -9
- package/src/search-results/components/hotel/hotel-accommodation-results.tsx +81 -24
- package/src/search-results/components/hotel/hotel-card.tsx +0 -3
- package/src/search-results/components/icon.tsx +1 -4
- package/src/search-results/components/search-results-container/search-results-container.tsx +208 -130
- package/src/search-results/store/search-results-selectors.ts +84 -0
- package/src/search-results/store/search-results-slice.ts +138 -15
- package/src/search-results/types.ts +55 -2
- package/src/search-results/utils/query-utils.ts +1 -0
- package/src/search-results/utils/search-results-utils.ts +310 -58
- package/src/shared/components/flyin/accommodation-flyin.tsx +4 -2
- package/src/shared/components/flyin/flights-flyin.tsx +3 -1
- package/src/shared/components/flyin/flyin.tsx +116 -21
- package/src/shared/components/flyin/group-tour-flyin.tsx +3 -1
- package/src/shared/components/flyin/packaging-flights-flyin.tsx +164 -0
- package/src/shared/translations/ar-SA.json +4 -2
- package/src/shared/translations/da-DK.json +4 -2
- package/src/shared/translations/de-DE.json +4 -2
- package/src/shared/translations/en-GB.json +4 -2
- package/src/shared/translations/es-ES.json +4 -2
- package/src/shared/translations/fr-BE.json +4 -2
- package/src/shared/translations/fr-FR.json +4 -2
- package/src/shared/translations/is-IS.json +4 -2
- package/src/shared/translations/it-IT.json +4 -2
- package/src/shared/translations/ja-JP.json +4 -2
- package/src/shared/translations/nl-BE.json +4 -2
- package/src/shared/translations/nl-NL.json +4 -2
- package/src/shared/translations/no-NO.json +4 -2
- package/src/shared/translations/pl-PL.json +4 -2
- package/src/shared/translations/pt-PT.json +4 -2
- package/src/shared/translations/sv-SE.json +4 -2
- package/src/shared/utils/localization-util.ts +14 -0
- package/src/shared/utils/tide-api-utils.ts +8 -0
- package/styles/components/_flyin.scss +16 -0
- package/styles/components/_search.scss +15 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExcursionSearchParams, ExtendedFlightSearchResponseItem, Filter, FlyInType, SortByType } from '../types';
|
|
2
2
|
import {
|
|
3
3
|
BookingPackage,
|
|
4
4
|
BookingPackageItem,
|
|
@@ -17,22 +17,32 @@ export interface SearchResultsState {
|
|
|
17
17
|
packagingAccoSearchDetails: PackagingAccommodationResponse[];
|
|
18
18
|
selectedPackagingAccoResultCode: string | null;
|
|
19
19
|
packagingFlightResults: PackagingFlightResponse[];
|
|
20
|
+
filteredPackagingFlightResults: PackagingFlightResponse[];
|
|
20
21
|
selectedPackagingFlight: PackagingFlightResponse | null;
|
|
22
|
+
selectedOutwardKey: string | null;
|
|
23
|
+
selectedReturnKey: string | null;
|
|
21
24
|
selectedFlight: ExtendedFlightSearchResponseItem | null;
|
|
22
25
|
selectedFlightDetails: ExtendedFlightSearchResponseItem | null;
|
|
23
26
|
bookingPackageDetails: BookingPackage | null;
|
|
27
|
+
priceDetails: BookingPriceDetails | null;
|
|
24
28
|
isLoading: boolean;
|
|
25
29
|
flightsLoading: boolean;
|
|
26
|
-
filters: Filter[];
|
|
27
30
|
selectedSortType: SortByType | null;
|
|
31
|
+
selectedFlightSortType: SortByType | null;
|
|
32
|
+
filters: Filter[];
|
|
33
|
+
initialFilters: Filter[];
|
|
34
|
+
flightFilters: Filter[];
|
|
35
|
+
initialFlightFilters: Filter[];
|
|
28
36
|
activeTab: string | null;
|
|
29
37
|
currentPage: number;
|
|
30
|
-
flyInIsOpen: boolean;
|
|
31
|
-
editablePackagingEntry: PackagingEntry | null;
|
|
32
38
|
transactionId: string | null;
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
flyInIsOpen: boolean;
|
|
40
|
+
flyInType: FlyInType | null;
|
|
35
41
|
itinerary: ClientPortalItinerary | null;
|
|
42
|
+
editablePackagingEntry: PackagingEntry | null;
|
|
43
|
+
excursionSearchParams: ExcursionSearchParams | null;
|
|
44
|
+
selectedExcursionSearchResult: PackagingAccommodationResponse | null;
|
|
45
|
+
confirmedExcursionsByDay: Record<string, PackagingAccommodationResponse[]>;
|
|
36
46
|
}
|
|
37
47
|
export declare const setResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<BookingPackageItem[], 'searchResults/setResults'>,
|
|
38
48
|
setFilteredResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<BookingPackageItem[], 'searchResults/setFilteredResults'>,
|
|
@@ -42,6 +52,10 @@ export declare const setResults: import('@reduxjs/toolkit').ActionCreatorWithPay
|
|
|
42
52
|
PackagingAccommodationResponse[],
|
|
43
53
|
'searchResults/setFilteredPackagingAccoResults'
|
|
44
54
|
>,
|
|
55
|
+
setFilteredPackagingFlightResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<
|
|
56
|
+
PackagingFlightResponse[],
|
|
57
|
+
'searchResults/setFilteredPackagingFlightResults'
|
|
58
|
+
>,
|
|
45
59
|
setPackagingAccoSearchDetails: import('@reduxjs/toolkit').ActionCreatorWithPayload<
|
|
46
60
|
PackagingAccommodationResponse[],
|
|
47
61
|
'searchResults/setPackagingAccoSearchDetails'
|
|
@@ -69,17 +83,50 @@ export declare const setResults: import('@reduxjs/toolkit').ActionCreatorWithPay
|
|
|
69
83
|
>,
|
|
70
84
|
setIsLoading: import('@reduxjs/toolkit').ActionCreatorWithPayload<boolean, 'searchResults/setIsLoading'>,
|
|
71
85
|
setFlightsLoading: import('@reduxjs/toolkit').ActionCreatorWithPayload<boolean, 'searchResults/setFlightsLoading'>,
|
|
86
|
+
setInitialFilters: import('@reduxjs/toolkit').ActionCreatorWithPayload<Filter[], 'searchResults/setInitialFilters'>,
|
|
72
87
|
setFilters: import('@reduxjs/toolkit').ActionCreatorWithPayload<Filter[], 'searchResults/setFilters'>,
|
|
73
88
|
resetFilters: import('@reduxjs/toolkit').ActionCreatorWithPayload<Filter[], 'searchResults/resetFilters'>,
|
|
89
|
+
setInitialFlightFilters: import('@reduxjs/toolkit').ActionCreatorWithPayload<Filter[], 'searchResults/setInitialFlightFilters'>,
|
|
90
|
+
setFlightFilters: import('@reduxjs/toolkit').ActionCreatorWithPayload<Filter[], 'searchResults/setFlightFilters'>,
|
|
91
|
+
resetFlightFilters: import('@reduxjs/toolkit').ActionCreatorWithPayload<Filter[], 'searchResults/resetFlightFilters'>,
|
|
74
92
|
setSortType: import('@reduxjs/toolkit').ActionCreatorWithPayload<SortByType | null, 'searchResults/setSortType'>,
|
|
93
|
+
setFlightSortType: import('@reduxjs/toolkit').ActionCreatorWithPayload<SortByType | null, 'searchResults/setFlightSortType'>,
|
|
75
94
|
setActiveTab: import('@reduxjs/toolkit').ActionCreatorWithPayload<string | null, 'searchResults/setActiveTab'>,
|
|
76
95
|
setCurrentPage: import('@reduxjs/toolkit').ActionCreatorWithPayload<number, 'searchResults/setCurrentPage'>,
|
|
77
96
|
resetSearchState: import('@reduxjs/toolkit').ActionCreatorWithoutPayload<'searchResults/resetSearchState'>,
|
|
78
97
|
setFlyInIsOpen: import('@reduxjs/toolkit').ActionCreatorWithPayload<boolean, 'searchResults/setFlyInIsOpen'>,
|
|
79
98
|
setEditablePackagingEntry: import('@reduxjs/toolkit').ActionCreatorWithPayload<PackagingEntry | null, 'searchResults/setEditablePackagingEntry'>,
|
|
80
99
|
setTransactionId: import('@reduxjs/toolkit').ActionCreatorWithPayload<string | null, 'searchResults/setTransactionId'>,
|
|
81
|
-
|
|
100
|
+
setFlyInType: import('@reduxjs/toolkit').ActionCreatorWithPayload<FlyInType | null, 'searchResults/setFlyInType'>,
|
|
82
101
|
setPriceDetails: import('@reduxjs/toolkit').ActionCreatorWithPayload<BookingPriceDetails | null, 'searchResults/setPriceDetails'>,
|
|
83
|
-
setItinerary: import('@reduxjs/toolkit').ActionCreatorWithPayload<ClientPortalItinerary | null, 'searchResults/setItinerary'
|
|
102
|
+
setItinerary: import('@reduxjs/toolkit').ActionCreatorWithPayload<ClientPortalItinerary | null, 'searchResults/setItinerary'>,
|
|
103
|
+
setSelectedOutwardKey: import('@reduxjs/toolkit').ActionCreatorWithPayload<string | null, 'searchResults/setSelectedOutwardKey'>,
|
|
104
|
+
setSelectedReturnKey: import('@reduxjs/toolkit').ActionCreatorWithPayload<string | null, 'searchResults/setSelectedReturnKey'>,
|
|
105
|
+
resetFlightSelection: import('@reduxjs/toolkit').ActionCreatorWithoutPayload<'searchResults/resetFlightSelection'>,
|
|
106
|
+
setExcursionSearchParams: import('@reduxjs/toolkit').ActionCreatorWithPayload<ExcursionSearchParams, 'searchResults/setExcursionSearchParams'>,
|
|
107
|
+
setSelectedExcursionSearchResult: import('@reduxjs/toolkit').ActionCreatorWithPayload<
|
|
108
|
+
PackagingAccommodationResponse | null,
|
|
109
|
+
'searchResults/setSelectedExcursionSearchResult'
|
|
110
|
+
>,
|
|
111
|
+
confirmExcursionForDay: import('@reduxjs/toolkit').ActionCreatorWithPayload<
|
|
112
|
+
{
|
|
113
|
+
dayKey: string;
|
|
114
|
+
excursion: PackagingAccommodationResponse;
|
|
115
|
+
},
|
|
116
|
+
'searchResults/confirmExcursionForDay'
|
|
117
|
+
>,
|
|
118
|
+
removeConfirmedExcursionForDay: import('@reduxjs/toolkit').ActionCreatorWithPayload<
|
|
119
|
+
{
|
|
120
|
+
dayKey: string;
|
|
121
|
+
excursionCode: string;
|
|
122
|
+
},
|
|
123
|
+
'searchResults/removeConfirmedExcursionForDay'
|
|
124
|
+
>,
|
|
125
|
+
clearConfirmedExcursionsForDay: import('@reduxjs/toolkit').ActionCreatorWithPayload<
|
|
126
|
+
{
|
|
127
|
+
dayKey: string;
|
|
128
|
+
},
|
|
129
|
+
'searchResults/clearConfirmedExcursionsForDay'
|
|
130
|
+
>;
|
|
84
131
|
declare const _default: import('@reduxjs/toolkit').Reducer<SearchResultsState>;
|
|
85
132
|
export default _default;
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
BookingPackage,
|
|
3
3
|
BookingPackageRequestRoom,
|
|
4
4
|
FlightSearchResponseItem,
|
|
5
|
+
PackageMainRoom,
|
|
5
6
|
PackagingEntry,
|
|
6
7
|
WebsiteConfigurationSearchConfiguration
|
|
7
8
|
} from '@qite/tide-client';
|
|
@@ -45,7 +46,19 @@ export interface SearchResultsConfiguration {
|
|
|
45
46
|
packagingEntry?: PackagingEntry | null;
|
|
46
47
|
}
|
|
47
48
|
export type FilterType = 'checkbox' | 'toggle' | 'slider' | 'star-rating';
|
|
48
|
-
export type FilterProperty =
|
|
49
|
+
export type FilterProperty =
|
|
50
|
+
| 'regime'
|
|
51
|
+
| 'accommodation'
|
|
52
|
+
| 'max-duration'
|
|
53
|
+
| 'price'
|
|
54
|
+
| 'rating'
|
|
55
|
+
| 'theme'
|
|
56
|
+
| 'airline'
|
|
57
|
+
| 'numberOfStops'
|
|
58
|
+
| 'departureRange'
|
|
59
|
+
| 'departureAirport'
|
|
60
|
+
| 'arrivalAirport'
|
|
61
|
+
| 'travelDuration';
|
|
49
62
|
export interface FilterOption {
|
|
50
63
|
label: string;
|
|
51
64
|
value: string | number | string[] | number[];
|
|
@@ -166,4 +179,29 @@ export type SearchSeed = {
|
|
|
166
179
|
destinationAirport?: string | null;
|
|
167
180
|
rooms: BookingPackageRequestRoom[];
|
|
168
181
|
};
|
|
169
|
-
export type
|
|
182
|
+
export type FlyInType =
|
|
183
|
+
| 'flight-outward-results'
|
|
184
|
+
| 'flight-return-results'
|
|
185
|
+
| 'flight-details'
|
|
186
|
+
| 'acco-results'
|
|
187
|
+
| 'acco-details'
|
|
188
|
+
| 'excursion-results'
|
|
189
|
+
| 'excursion-details';
|
|
190
|
+
export interface ExcursionSearchParams {
|
|
191
|
+
date: string;
|
|
192
|
+
fromDate: string;
|
|
193
|
+
toDate: string;
|
|
194
|
+
countryId?: number | null;
|
|
195
|
+
regionId?: number | null;
|
|
196
|
+
oordId?: number | null;
|
|
197
|
+
locationId?: number | null;
|
|
198
|
+
locationName?: string;
|
|
199
|
+
hotelCode: string;
|
|
200
|
+
hotelName: string;
|
|
201
|
+
accommodationCode: string | null;
|
|
202
|
+
accommodationName: string | null;
|
|
203
|
+
rooms?: PackageMainRoom[];
|
|
204
|
+
currencyCode?: string;
|
|
205
|
+
languageCode?: string;
|
|
206
|
+
source?: 'day-by-day-excursions';
|
|
207
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PackagingEntryLine, PackagingEntry, BookingPackageRequestRoom, PackagingRoom } from '@qite/tide-client';
|
|
2
2
|
export declare const GROUP_TOUR_SERVICE_TYPE = 1;
|
|
3
3
|
export declare const ACCOMMODATION_SERVICE_TYPE = 3;
|
|
4
|
+
export declare const EXCURSION_SERVICE_TYPE = 4;
|
|
4
5
|
export declare const FLIGHT_SERVICE_TYPE = 7;
|
|
5
6
|
export declare const toDateOnlyString: (value: string | Date) => string;
|
|
6
7
|
export declare const getPrimaryAccommodationLine: (lines: PackagingEntryLine[]) => PackagingEntryLine | undefined;
|
|
@@ -1,14 +1,16 @@
|
|
|
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
3
|
export declare const enrichFiltersWithResults: (results: BookingPackageItem[], filters: Filter[] | undefined, tags: TideTag[]) => Filter[];
|
|
4
|
-
export declare const enrichFiltersWithPackageAccoResults: (
|
|
5
|
-
|
|
6
|
-
filters: Filter[] | undefined,
|
|
7
|
-
tags: TideTag[]
|
|
8
|
-
) => Filter[];
|
|
4
|
+
export declare const enrichFiltersWithPackageAccoResults: (results: PackagingAccommodationResponse[], tags: TideTag[]) => Filter[];
|
|
5
|
+
export declare const enrichFiltersWithPackageFlightResults: (results: PackagingFlightResponse[], tags: TideTag[], translations: any) => Filter[];
|
|
9
6
|
export declare const applyFilters: (results: BookingPackageItem[], filters: Filter[], sortBy: SortByType | null) => BookingPackageItem[];
|
|
10
7
|
export declare const applyFiltersToPackageAccoResults: (
|
|
11
8
|
results: PackagingAccommodationResponse[],
|
|
12
9
|
filters: Filter[],
|
|
13
10
|
sortBy: SortByType | null
|
|
14
11
|
) => PackagingAccommodationResponse[];
|
|
12
|
+
export declare const applyFiltersToPackageFlightResults: (
|
|
13
|
+
results: PackagingFlightResponse[],
|
|
14
|
+
filters: Filter[],
|
|
15
|
+
sortBy: SortByType | null
|
|
16
|
+
) => PackagingFlightResponse[];
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { PortalQsmType } from '@qite/tide-client';
|
|
3
|
-
import {
|
|
3
|
+
import { FlyInType, SearchSeed, SortByType } from '../../../search-results/types';
|
|
4
4
|
type FlyInProps = {
|
|
5
|
-
title: string;
|
|
6
5
|
srpType: PortalQsmType;
|
|
7
6
|
isOpen: boolean;
|
|
8
7
|
setIsOpen: (open: boolean) => void;
|
|
@@ -10,8 +9,10 @@ type FlyInProps = {
|
|
|
10
9
|
onPanelRef?: (el: HTMLDivElement | null) => void;
|
|
11
10
|
detailsLoading: boolean;
|
|
12
11
|
handleConfirm?: () => void;
|
|
13
|
-
|
|
12
|
+
flyInType?: FlyInType | null;
|
|
14
13
|
isPackageEditFlow?: boolean;
|
|
14
|
+
sortByTypes?: SortByType[];
|
|
15
|
+
activeSearchSeed?: SearchSeed | null;
|
|
15
16
|
};
|
|
16
17
|
declare const FlyIn: React.FC<FlyInProps>;
|
|
17
18
|
export default FlyIn;
|
|
@@ -335,6 +335,7 @@ export declare const getTranslations: (language: string) => {
|
|
|
335
335
|
CONFIRM: string;
|
|
336
336
|
TRAVELERS: string;
|
|
337
337
|
GROUP_TOUR: string;
|
|
338
|
+
ALL_TRAVELERS: string;
|
|
338
339
|
};
|
|
339
340
|
SRP: {
|
|
340
341
|
SHOW_MORE: string;
|
|
@@ -386,6 +387,7 @@ export declare const getTranslations: (language: string) => {
|
|
|
386
387
|
DURATION_ASC: string;
|
|
387
388
|
DURATION_DESC: string;
|
|
388
389
|
TRAVEL_GROUP: string;
|
|
390
|
+
EXCURSION: string;
|
|
389
391
|
};
|
|
390
392
|
};
|
|
391
393
|
export declare const locales: {
|
|
@@ -422,3 +424,4 @@ export declare const calculateNights: (fromDate: Date, toDate: Date) => number;
|
|
|
422
424
|
export declare const calculateDays: (fromDate: Date, toDate: Date) => number;
|
|
423
425
|
export declare const getSortingName: (translations: any, sortByType: SortByType) => string;
|
|
424
426
|
export declare const findSortByType: (sortByTypes: SortByType[], sortKey: string, direction: string) => SortByType;
|
|
427
|
+
export declare const getDatesBetween: (fromDate: string, toDate: string) => Date[];
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { TideClientConfig } from '@qite/tide-client';
|
|
2
2
|
import { ApiSettingsState } from '../types';
|
|
3
|
+
export declare const tideConnection: {
|
|
4
|
+
host: string;
|
|
5
|
+
apiKey: string;
|
|
6
|
+
catalogueIds: number[];
|
|
7
|
+
officeId: number;
|
|
8
|
+
};
|
|
3
9
|
export declare function buildTideClientConfig(settings?: ApiSettingsState): TideClientConfig;
|
|
4
10
|
export declare const selectAgentToken: () => string | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qite/tide-booking-component",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.105",
|
|
4
4
|
"description": "React Booking wizard & Booking product component for Tide",
|
|
5
5
|
"main": "build/build-cjs/index.js",
|
|
6
6
|
"types": "build/build-cjs/src/index.d.ts",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@jsonurl/jsonurl": "^1.1.4",
|
|
31
31
|
"@popperjs/core": "^2.10.2",
|
|
32
|
-
"@qite/tide-client": "^1.1.
|
|
32
|
+
"@qite/tide-client": "^1.1.166",
|
|
33
33
|
"@reduxjs/toolkit": "^2.8.2",
|
|
34
34
|
"@rollup/plugin-commonjs": "^19.0.1",
|
|
35
35
|
"@rollup/plugin-json": "^4.1.0",
|
|
@@ -8,7 +8,7 @@ import SettingsContext from '../../settings-context';
|
|
|
8
8
|
import { useAppDispatch } from '../../store';
|
|
9
9
|
import { FlightFilterOptions, GroupedFlights } from '../../types';
|
|
10
10
|
import { setCurrentStep, setFlights, setPackage } from '../booking/booking-slice';
|
|
11
|
-
import { ROOM_OPTIONS_FORM_STEP, TRAVELERS_FORM_STEP } from '../booking/constants';
|
|
11
|
+
import { OPTIONS_FORM_STEP, ROOM_OPTIONS_FORM_STEP, TRAVELERS_FORM_STEP } from '../booking/constants';
|
|
12
12
|
import {
|
|
13
13
|
selectBookingQueryString,
|
|
14
14
|
selectIsFetchingProductOptions,
|
|
@@ -43,7 +43,11 @@ const FlightOptionsForm: React.FC<FlightOptionsFormProps> = () => {
|
|
|
43
43
|
|
|
44
44
|
const handleSubmit: React.FormEventHandler<HTMLFormElement> = (e) => {
|
|
45
45
|
if (settings.skipRouter) {
|
|
46
|
-
|
|
46
|
+
if (settings.roomOptions.isHidden) {
|
|
47
|
+
dispatch(setCurrentStep(OPTIONS_FORM_STEP));
|
|
48
|
+
} else {
|
|
49
|
+
dispatch(setCurrentStep(ROOM_OPTIONS_FORM_STEP));
|
|
50
|
+
}
|
|
47
51
|
} else {
|
|
48
52
|
if (settings.roomOptions.isHidden) {
|
|
49
53
|
navigate(`${!settings.skipBasePathInRouting ? settings.basePath : ''}${settings.options.pathSuffix}?${bookingQueryString}`);
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import React, { useContext, useMemo } from 'react';
|
|
2
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
3
|
+
import { SearchResultsRootState } from '../../store/search-results-store';
|
|
4
|
+
import SearchResultsConfigurationContext from '../../search-results-configuration-context';
|
|
5
|
+
import { getDatesBetween, getTranslations } from '../../../shared/utils/localization-util';
|
|
6
|
+
import { selectSelectedPackagingAccoResult } from '../../store/search-results-selectors';
|
|
7
|
+
import { removeConfirmedExcursionForDay, setExcursionSearchParams, setFlyInIsOpen, setFlyInType } from '../../store/search-results-slice';
|
|
8
|
+
import { ExcursionSearchParams } from '../../types';
|
|
9
|
+
import { format } from 'date-fns';
|
|
10
|
+
import he from 'he';
|
|
11
|
+
import Icon from '../icon';
|
|
12
|
+
import { PackagingAccommodationResponse } from '@qite/tide-client';
|
|
13
|
+
|
|
14
|
+
interface DayByDayExcursionsProps {}
|
|
15
|
+
|
|
16
|
+
const getExcursionContentWithUpdatedPrice = (contents: string | null | undefined, totalPrice: number, currencyCode?: string | null) => {
|
|
17
|
+
if (!contents) return '';
|
|
18
|
+
|
|
19
|
+
const decodedHtml = he.decode(contents);
|
|
20
|
+
const parser = new DOMParser();
|
|
21
|
+
const doc = parser.parseFromString(decodedHtml, 'text/html');
|
|
22
|
+
|
|
23
|
+
const priceElement = doc.querySelector('[data-excursion-price]');
|
|
24
|
+
|
|
25
|
+
if (priceElement) {
|
|
26
|
+
priceElement.textContent = new Intl.NumberFormat('nl-BE', {
|
|
27
|
+
style: 'currency',
|
|
28
|
+
currency: currencyCode ?? 'EUR'
|
|
29
|
+
}).format(totalPrice);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return doc.body.innerHTML;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const DayByDayExcursions: React.FC<DayByDayExcursionsProps> = () => {
|
|
36
|
+
const context = useContext(SearchResultsConfigurationContext);
|
|
37
|
+
const translations = getTranslations(context?.languageCode ?? 'en-GB');
|
|
38
|
+
const dispatch = useDispatch();
|
|
39
|
+
|
|
40
|
+
const { confirmedExcursionsByDay } = useSelector((state: SearchResultsRootState) => state.searchResults);
|
|
41
|
+
const selectedPackagingAccoResult = useSelector(selectSelectedPackagingAccoResult);
|
|
42
|
+
|
|
43
|
+
const stayDates = useMemo(() => {
|
|
44
|
+
if (!selectedPackagingAccoResult?.fromDate || !selectedPackagingAccoResult?.toDate) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return getDatesBetween(selectedPackagingAccoResult.fromDate, selectedPackagingAccoResult.toDate);
|
|
49
|
+
}, [selectedPackagingAccoResult?.fromDate, selectedPackagingAccoResult?.toDate]);
|
|
50
|
+
|
|
51
|
+
const handleSearchExcursions = (day: Date) => {
|
|
52
|
+
if (!selectedPackagingAccoResult) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const searchParams: ExcursionSearchParams = {
|
|
57
|
+
date: day.toISOString(),
|
|
58
|
+
fromDate: day.toISOString(),
|
|
59
|
+
toDate: day.toISOString(),
|
|
60
|
+
countryId: selectedPackagingAccoResult.countryId,
|
|
61
|
+
regionId: selectedPackagingAccoResult.regionId,
|
|
62
|
+
oordId: selectedPackagingAccoResult.oordId,
|
|
63
|
+
locationId: selectedPackagingAccoResult.locationId,
|
|
64
|
+
locationName: selectedPackagingAccoResult.locationName,
|
|
65
|
+
accommodationCode: selectedPackagingAccoResult.rooms?.[0]?.options?.find((option) => option.isSelected)?.accommodationCode ?? null,
|
|
66
|
+
accommodationName: selectedPackagingAccoResult.rooms?.[0]?.options?.find((option) => option.isSelected)?.accommodationName ?? null,
|
|
67
|
+
hotelCode: selectedPackagingAccoResult.code,
|
|
68
|
+
hotelName: selectedPackagingAccoResult.name,
|
|
69
|
+
rooms: selectedPackagingAccoResult?.rooms ?? []
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
dispatch(setExcursionSearchParams(searchParams));
|
|
73
|
+
dispatch(setFlyInIsOpen(true));
|
|
74
|
+
dispatch(setFlyInType('excursion-results'));
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const getSelectedOptionsSummary = (excursion: PackagingAccommodationResponse) => {
|
|
78
|
+
const options = excursion.rooms.flatMap((room) => room.options ?? []);
|
|
79
|
+
return options.filter((option) => option.isSelected);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
if (!selectedPackagingAccoResult || stayDates.length === 0) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<>
|
|
88
|
+
{stayDates.map((day) => {
|
|
89
|
+
const dayKey = format(day, 'yyyy-MM-dd');
|
|
90
|
+
const formattedDay = format(day, 'd');
|
|
91
|
+
const formattedMonth = format(day, 'MMM');
|
|
92
|
+
const confirmedExcursions = confirmedExcursionsByDay[dayKey] ?? [];
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<React.Fragment key={dayKey}>
|
|
96
|
+
<div className="search__results__label search__results__label--secondary">
|
|
97
|
+
<div className="search__results__label__date">
|
|
98
|
+
<p className="search__results__label__date-date">{formattedDay}</p>
|
|
99
|
+
<p>{formattedMonth}</p>
|
|
100
|
+
</div>
|
|
101
|
+
<div className="search__results__label__text">
|
|
102
|
+
<h3>
|
|
103
|
+
{translations.SRP.SELECT} <strong>{translations.SRP.EXCURSION}</strong>
|
|
104
|
+
</h3>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<div className="search__results__cards__actions">
|
|
109
|
+
<span>Accommodation for this day: {selectedPackagingAccoResult.name}</span>
|
|
110
|
+
|
|
111
|
+
<button type="button" className="cta cta--secondary" onClick={() => handleSearchExcursions(day)}>
|
|
112
|
+
{confirmedExcursions.length > 0 ? 'Add another excursion' : `${translations.SRP.SELECT} ${translations.SRP.EXCURSION}`}
|
|
113
|
+
</button>
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<div className="search__results__cards search__results__cards--compact">
|
|
117
|
+
{confirmedExcursions &&
|
|
118
|
+
confirmedExcursions.length > 0 &&
|
|
119
|
+
confirmedExcursions.map((excursion) => {
|
|
120
|
+
const selectedOptions = getSelectedOptionsSummary(excursion);
|
|
121
|
+
const totalPrice = selectedOptions.reduce((sum: number, option: any) => sum + (option.price || 0), 0);
|
|
122
|
+
const updatedContents = getExcursionContentWithUpdatedPrice(excursion.contents, totalPrice, excursion.currencyCode);
|
|
123
|
+
return (
|
|
124
|
+
<div
|
|
125
|
+
key={excursion.code}
|
|
126
|
+
className="search__result-card__wrapper search__result-card__wrapper--custom"
|
|
127
|
+
onMouseEnter={(e) => (e.currentTarget.style.transform = 'scale(1.02)')}
|
|
128
|
+
onMouseLeave={(e) => (e.currentTarget.style.transform = 'scale(1)')}>
|
|
129
|
+
<div dangerouslySetInnerHTML={{ __html: updatedContents }}></div>
|
|
130
|
+
<div className="search__result-card__content--extra">
|
|
131
|
+
<div className="search__result-card__content__wrapper">
|
|
132
|
+
<div className="search__result-card__options">
|
|
133
|
+
{selectedOptions.length > 0 &&
|
|
134
|
+
selectedOptions.map((option) => (
|
|
135
|
+
<div className="search__result-card__option" key={option.guid}>
|
|
136
|
+
<Icon name="ui-ticket" width={14} height={14} aria-hidden="true" />
|
|
137
|
+
<span>
|
|
138
|
+
{option.accommodationName}
|
|
139
|
+
{/* {option.paxIds?.length > 0 && (
|
|
140
|
+
<>
|
|
141
|
+
{' '}(Traveller{option.paxIds.length > 1 ? 's' : ''}{' '}{option.paxIds.map((id) => id + 1).join(', ')})
|
|
142
|
+
</>
|
|
143
|
+
)} */}
|
|
144
|
+
</span>
|
|
145
|
+
</div>
|
|
146
|
+
))}
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
<div className="search__result-card__footer">
|
|
151
|
+
<button
|
|
152
|
+
type="button"
|
|
153
|
+
className="cta cta--remove"
|
|
154
|
+
onClick={() => dispatch(removeConfirmedExcursionForDay({ dayKey, excursionCode: excursion.code }))}>
|
|
155
|
+
Remove
|
|
156
|
+
</button>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
);
|
|
160
|
+
})}
|
|
161
|
+
</div>
|
|
162
|
+
</React.Fragment>
|
|
163
|
+
);
|
|
164
|
+
})}
|
|
165
|
+
</>
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export default DayByDayExcursions;
|