@qite/tide-booking-component 1.4.113 → 1.4.114
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 +212 -126
- package/build/build-cjs/src/search-results/components/book-packaging-entry/index.d.ts +1 -0
- package/build/build-cjs/src/search-results/components/book-packaging-entry/wl-sidebar.d.ts +2 -0
- package/build/build-cjs/src/shared/utils/booking-summary.d.ts +1 -0
- package/build/build-esm/index.js +212 -126
- package/build/build-esm/src/search-results/components/book-packaging-entry/index.d.ts +1 -0
- package/build/build-esm/src/search-results/components/book-packaging-entry/wl-sidebar.d.ts +2 -0
- package/build/build-esm/src/shared/utils/booking-summary.d.ts +1 -0
- package/package.json +1 -1
- package/src/search-results/components/book-packaging-entry/index.tsx +27 -7
- package/src/search-results/components/book-packaging-entry/wl-sidebar.tsx +27 -16
- package/src/search-results/components/flight/flight-selection/independent-flight-selection.tsx +5 -2
- package/src/search-results/components/hotel/hotel-accommodation-results.tsx +11 -2
- package/src/search-results/components/search-results-container/search-results-container.tsx +5 -1
- package/src/shared/booking/summary.tsx +0 -1
- package/src/shared/components/flyin/flyin.tsx +10 -1
- package/src/shared/utils/booking-summary.tsx +11 -0
- package/styles/components/_select-wrapper.scss +5 -0
|
@@ -10,12 +10,14 @@ import { SearchSeed } from '../../types';
|
|
|
10
10
|
import { getTravelersText } from '../../../booking-wizard/features/sidebar/sidebar-util';
|
|
11
11
|
import { RoomTraveler } from '../../../booking-wizard/types';
|
|
12
12
|
|
|
13
|
-
import { BookingPackageFlightMetaData, BookingPriceDetail, PackagingEntryLine } from '@qite/tide-client';
|
|
13
|
+
import { BookingPackageFlightMetaData, BookingPriceDetail, PackagingAccommodationResponse, PackagingEntryLine, PortalQsmType } from '@qite/tide-client';
|
|
14
14
|
import Spinner from '../spinner/spinner';
|
|
15
15
|
import SharedSidebar from '../../../shared/booking/shared-sidebar';
|
|
16
|
+
import { getImageSrcFromHtml } from '../../../shared/utils/booking-summary';
|
|
16
17
|
|
|
17
18
|
interface WLSidebarProps {
|
|
18
19
|
activeSearchSeed: SearchSeed | null;
|
|
20
|
+
packagingAccoResult: PackagingAccommodationResponse | null;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
const mapToSidebarFlightMetaData = (entryLine: PackagingEntryLine) => {
|
|
@@ -66,18 +68,12 @@ const selectSeparatePackagePriceDetails = (priceDetails: BookingPriceDetail[]) =
|
|
|
66
68
|
return result;
|
|
67
69
|
};
|
|
68
70
|
|
|
69
|
-
const WLSidebar: React.FC<WLSidebarProps> = ({ activeSearchSeed }) => {
|
|
71
|
+
const WLSidebar: React.FC<WLSidebarProps> = ({ activeSearchSeed, packagingAccoResult }) => {
|
|
70
72
|
const context = useContext(SearchResultsConfigurationContext);
|
|
71
|
-
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
const translations = getTranslations(context.languageCode ?? 'en-GB');
|
|
73
|
+
|
|
75
74
|
const { editablePackagingEntry, priceDetails } = useSelector((state: SearchResultsRootState) => state.searchResults);
|
|
76
75
|
|
|
77
|
-
|
|
78
|
-
if (!editablePackagingEntry) {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
76
|
+
const translations = getTranslations(context?.languageCode ?? 'en-GB');
|
|
81
77
|
|
|
82
78
|
const sortedLines = useMemo(() => {
|
|
83
79
|
return [...(editablePackagingEntry?.lines ?? [])].sort((a, b) => {
|
|
@@ -92,16 +88,31 @@ const WLSidebar: React.FC<WLSidebarProps> = ({ activeSearchSeed }) => {
|
|
|
92
88
|
});
|
|
93
89
|
}, [editablePackagingEntry]);
|
|
94
90
|
|
|
91
|
+
const accoImage = useMemo(() => {
|
|
92
|
+
return getImageSrcFromHtml(packagingAccoResult?.contents);
|
|
93
|
+
}, [packagingAccoResult?.contents]);
|
|
94
|
+
|
|
95
|
+
if (!context || !editablePackagingEntry) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
95
99
|
const firstEntryLine = first(sortedLines);
|
|
96
100
|
const accommodationLines = editablePackagingEntry.lines.filter((line) => line.serviceType === ACCOMMODATION_SERVICE_TYPE);
|
|
97
101
|
const accommodationLine = first(accommodationLines) ?? firstEntryLine;
|
|
98
102
|
|
|
99
103
|
const location =
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
context.searchConfiguration.qsmType === PortalQsmType.Accommodation
|
|
105
|
+
? packagingAccoResult?.name ??
|
|
106
|
+
accommodationLine?.location?.name ??
|
|
107
|
+
accommodationLine?.oord?.name ??
|
|
108
|
+
accommodationLine?.region?.name ??
|
|
109
|
+
accommodationLine?.country?.name ??
|
|
110
|
+
firstEntryLine?.location?.name
|
|
111
|
+
: accommodationLine?.location?.name ??
|
|
112
|
+
accommodationLine?.oord?.name ??
|
|
113
|
+
accommodationLine?.region?.name ??
|
|
114
|
+
accommodationLine?.country?.name ??
|
|
115
|
+
firstEntryLine?.location?.name;
|
|
105
116
|
|
|
106
117
|
const rooms =
|
|
107
118
|
activeSearchSeed?.rooms.map((room) => {
|
|
@@ -136,7 +147,7 @@ const WLSidebar: React.FC<WLSidebarProps> = ({ activeSearchSeed }) => {
|
|
|
136
147
|
return (
|
|
137
148
|
<SharedSidebar
|
|
138
149
|
productName={location ?? ''}
|
|
139
|
-
thumbnailUrl={context.destinationImage?.url}
|
|
150
|
+
thumbnailUrl={accoImage ?? context.destinationImage?.url}
|
|
140
151
|
translations={translations}
|
|
141
152
|
travelerRooms={travelerRooms}
|
|
142
153
|
startDateText={first(sortedLines)?.from && formatDate(new Date(first(sortedLines)!.from))}
|
package/src/search-results/components/flight/flight-selection/independent-flight-selection.tsx
CHANGED
|
@@ -94,9 +94,12 @@ const IndependentFlightSelection: React.FC<IndependentFlightSelectionProps> = ({
|
|
|
94
94
|
}, [searchResults, selectedReturnKey]);
|
|
95
95
|
|
|
96
96
|
const firstResultDate = uniqueOutwardFlights.length > 0 ? uniqueOutwardFlights[0].outward.segments[0].departureDateTime : null;
|
|
97
|
+
const firstResultReturnDate = uniqueReturnFlights.length > 0 ? uniqueReturnFlights[0].return.segments[0].departureDateTime : null;
|
|
97
98
|
|
|
98
99
|
const firstResultDay = firstResultDate ? format(firstResultDate, 'd') : null;
|
|
99
100
|
const firstResultMonth = firstResultDate ? format(firstResultDate, 'MMM') : null;
|
|
101
|
+
const firstResultReturnDay = firstResultReturnDate ? format(firstResultReturnDate, 'd') : null;
|
|
102
|
+
const firstResultReturnMonth = firstResultReturnDate ? format(firstResultReturnDate, 'MMM') : null;
|
|
100
103
|
|
|
101
104
|
return (
|
|
102
105
|
<>
|
|
@@ -138,8 +141,8 @@ const IndependentFlightSelection: React.FC<IndependentFlightSelectionProps> = ({
|
|
|
138
141
|
|
|
139
142
|
<div className="search__results__label search__results__label--secondary">
|
|
140
143
|
<div className="search__results__label__date">
|
|
141
|
-
|
|
142
|
-
<p>{
|
|
144
|
+
<p className="search__results__label__date-date">{firstResultReturnDay}</p>
|
|
145
|
+
<p>{firstResultReturnMonth}</p>
|
|
143
146
|
</div>
|
|
144
147
|
<div className="search__results__label__text">
|
|
145
148
|
<Icon name="ui-flight" height={16} fill="white" />
|
|
@@ -175,12 +175,21 @@ const HotelAccommodationResults: React.FC<HotelAccommodationResultsProps> = ({ i
|
|
|
175
175
|
const visibleResults = React.useMemo(() => {
|
|
176
176
|
const shouldShowAll = context?.searchConfiguration.qsmType !== PortalQsmType.AccommodationAndFlight || isFlyIn;
|
|
177
177
|
|
|
178
|
+
let filteredMapperResults = mappedResults;
|
|
179
|
+
|
|
180
|
+
if (selectedPackagingAccoResult) {
|
|
181
|
+
filteredMapperResults = mappedResults.filter((result) => result.code !== selectedPackagingAccoResult.code);
|
|
182
|
+
}
|
|
183
|
+
|
|
178
184
|
if (shouldShowAll) {
|
|
179
|
-
|
|
185
|
+
if (isFlyIn) {
|
|
186
|
+
return mappedResults;
|
|
187
|
+
}
|
|
188
|
+
return filteredMapperResults;
|
|
180
189
|
}
|
|
181
190
|
|
|
182
191
|
if (selectedPackagingAccoResult) {
|
|
183
|
-
return
|
|
192
|
+
return filteredMapperResults.filter((result) => result.code !== selectedPackagingAccoResult.code).slice(0, 2);
|
|
184
193
|
}
|
|
185
194
|
|
|
186
195
|
return mappedResults.slice(0, 3);
|
|
@@ -1489,7 +1489,11 @@ const SearchResultsContainer: React.FC<SearchResultsContainerProps> = ({ onBooki
|
|
|
1489
1489
|
{context && (
|
|
1490
1490
|
<div className="search">
|
|
1491
1491
|
{bookPackagingEntry ? (
|
|
1492
|
-
<BookPackagingEntry
|
|
1492
|
+
<BookPackagingEntry
|
|
1493
|
+
activeSearchSeed={activeSearchSeed}
|
|
1494
|
+
isLoading={itineraryIsLoading || pricesAreLoading}
|
|
1495
|
+
isConfirmationPage={isBookingConfirmation}
|
|
1496
|
+
/>
|
|
1493
1497
|
) : (
|
|
1494
1498
|
<div className="search__container">
|
|
1495
1499
|
{context.searchConfiguration.qsmType === PortalQsmType.Flight && (
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { compact, findIndex, isEmpty, isNil, uniqBy } from 'lodash';
|
|
2
2
|
import React, { ReactNode, useEffect, useState } from 'react';
|
|
3
3
|
import { SummaryCheckbox, TravelersFormValues } from '../../booking-wizard/types';
|
|
4
|
-
import Loader from '../components/loader';
|
|
5
4
|
import { buildClassName } from '../utils/class-util';
|
|
6
5
|
import Icon from '../components/icon';
|
|
7
6
|
import Spinner from '../../search-results/components/spinner/spinner';
|
|
@@ -4,6 +4,7 @@ import { useFlightSearch } from '../../../search-results/components/flight/fligh
|
|
|
4
4
|
import { useDispatch, useSelector } from 'react-redux';
|
|
5
5
|
import {
|
|
6
6
|
resetFilters,
|
|
7
|
+
setBookPackagingEntry,
|
|
7
8
|
setFilters,
|
|
8
9
|
setFlyInType,
|
|
9
10
|
setSelectedFlight,
|
|
@@ -125,6 +126,14 @@ const FlyIn: React.FC<FlyInProps> = ({
|
|
|
125
126
|
}
|
|
126
127
|
};
|
|
127
128
|
|
|
129
|
+
const onHandleConfirm = () => {
|
|
130
|
+
if (context?.packagingEntry) {
|
|
131
|
+
handleConfirm?.();
|
|
132
|
+
} else {
|
|
133
|
+
dispatch(setBookPackagingEntry(true));
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
128
137
|
return (
|
|
129
138
|
<div
|
|
130
139
|
className={`flyin ${isOpen ? 'flyin--active' : ''} ${className} ${isPackageEditFlow || flyInType === 'acco-results' ? 'flyin--large' : ''} ${
|
|
@@ -211,7 +220,7 @@ const FlyIn: React.FC<FlyInProps> = ({
|
|
|
211
220
|
)}
|
|
212
221
|
|
|
213
222
|
{(srpType === PortalQsmType.Accommodation || srpType === PortalQsmType.AccommodationAndFlight) && flyInType === 'acco-details' && (
|
|
214
|
-
<AccommodationFlyIn isLoading={detailsLoading} handleConfirm={
|
|
223
|
+
<AccommodationFlyIn isLoading={detailsLoading} handleConfirm={onHandleConfirm} />
|
|
215
224
|
)}
|
|
216
225
|
|
|
217
226
|
{srpType === PortalQsmType.AccommodationAndFlight && (flyInType === 'flight-outward-results' || flyInType === 'flight-return-results') && (
|
|
@@ -44,3 +44,14 @@ export const renderEditablePackagingEntrySummaryOptions = (editablePackagingEntr
|
|
|
44
44
|
);
|
|
45
45
|
});
|
|
46
46
|
};
|
|
47
|
+
|
|
48
|
+
export const getImageSrcFromHtml = (html?: string | null): string | undefined => {
|
|
49
|
+
if (!html || typeof window === 'undefined') {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const doc = new DOMParser().parseFromString(html, 'text/html');
|
|
54
|
+
const img = doc.querySelector('img');
|
|
55
|
+
|
|
56
|
+
return img?.getAttribute('src') ?? undefined;
|
|
57
|
+
};
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
border-left: 2px solid var(--tide-booking-room-options-dropdown-select-icon-color);
|
|
14
14
|
border-bottom: 2px solid var(--tide-booking-room-options-dropdown-select-icon-color);
|
|
15
15
|
transform: rotate(-45deg);
|
|
16
|
+
pointer-events: none;
|
|
16
17
|
}
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -30,6 +31,10 @@
|
|
|
30
31
|
border: --tide-booking-room-options-dropdown-select-border-focus;
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
&:hover {
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
}
|
|
37
|
+
|
|
33
38
|
option {
|
|
34
39
|
appearance: none;
|
|
35
40
|
display: flex;
|