@qite/tide-booking-component 1.4.34 → 1.4.36
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 +1628 -376
- 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 +4 -14
- package/build/build-esm/index.js +1628 -376
- 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 +4 -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 +233 -131
- 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 +4 -13
- package/src/search-results/features/hotels/hotel-flight-search-results-self-contained.tsx +5 -1
- package/src/search-results/features/hotels/hotel-search-results-self-contained.tsx +4 -13
- package/src/search-results/features/roundtrips/roundtrip-search-results-self-contained.tsx +5 -1
- package/src/search-results/store/search-results-slice.ts +37 -3
- package/src/search-results/types.ts +2 -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
|
@@ -2,8 +2,8 @@ import React from 'react';
|
|
|
2
2
|
import { Filter } from '../../types';
|
|
3
3
|
interface FiltersProps {
|
|
4
4
|
filters: Filter[];
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
isOpen: boolean;
|
|
6
|
+
handleSetIsOpen: () => void;
|
|
7
7
|
handleApplyFilters: () => void;
|
|
8
8
|
isLoading?: boolean;
|
|
9
9
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Filter } from '../types';
|
|
2
|
-
import { BookingPackageItem } from '@qite/tide-client/build/types';
|
|
2
|
+
import { BookingPackage, BookingPackageItem, EntryLight } from '@qite/tide-client/build/types';
|
|
3
3
|
export interface SearchResultsState {
|
|
4
4
|
results: BookingPackageItem[];
|
|
5
5
|
selectedHotelId: number | null;
|
|
6
|
+
bookingPackageDetails: BookingPackage | null;
|
|
7
|
+
entry: EntryLight | null;
|
|
6
8
|
isLoading: boolean;
|
|
7
9
|
filters: Filter[];
|
|
8
10
|
sortKey: string | null;
|
|
@@ -11,6 +13,13 @@ export interface SearchResultsState {
|
|
|
11
13
|
}
|
|
12
14
|
export declare const setResults: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
13
15
|
results: BookingPackageItem[];
|
|
14
|
-
}, "searchResults/setResults">, setSelectedHotel: import("@reduxjs/toolkit").ActionCreatorWithPayload<number | null, "searchResults/setSelectedHotel">,
|
|
16
|
+
}, "searchResults/setResults">, setSelectedHotel: import("@reduxjs/toolkit").ActionCreatorWithPayload<number | null, "searchResults/setSelectedHotel">, setBookingPackageDetails: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
17
|
+
details: BookingPackage;
|
|
18
|
+
}, "searchResults/setBookingPackageDetails">, setEntry: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
19
|
+
entry: EntryLight;
|
|
20
|
+
}, "searchResults/setEntry">, selectFlight: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
21
|
+
flightOptionId: string;
|
|
22
|
+
isDeparture: boolean;
|
|
23
|
+
}, "searchResults/selectFlight">, setIsLoading: import("@reduxjs/toolkit").ActionCreatorWithPayload<boolean, "searchResults/setIsLoading">, setFilters: import("@reduxjs/toolkit").ActionCreatorWithPayload<Filter[], "searchResults/setFilters">, resetFilters: import("@reduxjs/toolkit").ActionCreatorWithPayload<Filter[], "searchResults/resetFilters">, setSortKey: import("@reduxjs/toolkit").ActionCreatorWithPayload<string | null, "searchResults/setSortKey">, setActiveTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<string | null, "searchResults/setActiveTab">, setCurrentPage: import("@reduxjs/toolkit").ActionCreatorWithPayload<number, "searchResults/setCurrentPage">, resetSearchState: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"searchResults/resetSearchState">;
|
|
15
24
|
declare const _default: import("redux").Reducer<SearchResultsState, import("redux").AnyAction>;
|
|
16
25
|
export default _default;
|
|
@@ -19,24 +19,14 @@ export interface SearchResultsConfiguration {
|
|
|
19
19
|
showCustomCards?: boolean;
|
|
20
20
|
customCardRenderer?: (result: SearchResult) => ReactNode;
|
|
21
21
|
showMapView?: boolean;
|
|
22
|
-
noResultsLabel?: string;
|
|
23
22
|
isLoading?: boolean;
|
|
24
23
|
customSpinner?: ReactNode;
|
|
25
|
-
translations?: {
|
|
26
|
-
filters?: string;
|
|
27
|
-
filterTitle?: string;
|
|
28
|
-
resetButton?: string;
|
|
29
|
-
sortBy?: string;
|
|
30
|
-
noResults?: string;
|
|
31
|
-
totalResultsLabel?: string;
|
|
32
|
-
luggageIncluded?: string;
|
|
33
|
-
cancel?: string;
|
|
34
|
-
apply?: string;
|
|
35
|
-
loading?: string;
|
|
36
|
-
searchResultCTA?: string;
|
|
37
|
-
};
|
|
38
24
|
cmsHotelData?: any[];
|
|
39
25
|
languageCode?: string;
|
|
26
|
+
destinationImage?: {
|
|
27
|
+
url: string;
|
|
28
|
+
alt: string;
|
|
29
|
+
};
|
|
40
30
|
}
|
|
41
31
|
export type FilterType = 'checkbox' | 'toggle' | 'slider' | 'star-rating';
|
|
42
32
|
export type FilterProperty = 'regime' | 'max-duration' | 'price' | 'rating' | 'theme';
|
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.36",
|
|
4
4
|
"description": "React Booking wizard & Booking product component for Tide",
|
|
5
5
|
"main": "build/build-cjs/index.js",
|
|
6
6
|
"module": "build/build-esm/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@jsonurl/jsonurl": "^1.1.4",
|
|
29
29
|
"@popperjs/core": "^2.10.2",
|
|
30
|
-
"@qite/tide-client": "^1.1.
|
|
30
|
+
"@qite/tide-client": "^1.1.126",
|
|
31
31
|
"@reach/router": "^1.3.4",
|
|
32
32
|
"@reduxjs/toolkit": "^1.6.0",
|
|
33
33
|
"@rollup/plugin-commonjs": "^19.0.1",
|
|
@@ -286,7 +286,6 @@ const BookingSelfContained: React.FC<BookingProps> = ({ productCode, productName
|
|
|
286
286
|
<p className="booking__loader-text">
|
|
287
287
|
{allowOption ? translations.MAIN.PREPARING_DOSSIER : isOffer ? translations.MAIN.PREPARING_OFFER : translations.MAIN.PREPARING_BOOKING}
|
|
288
288
|
</p>
|
|
289
|
-
<p className="booking__loader-text">{isOffer ? translations.MAIN.PREPARING_OFFER : translations.MAIN.PREPARING_BOOKING}</p>
|
|
290
289
|
</div>
|
|
291
290
|
</div>
|
|
292
291
|
)}
|
|
@@ -6,7 +6,7 @@ import { ControlProps, hasVisibleError } from '../travelers-form-util';
|
|
|
6
6
|
const GenderControl: React.FC<ControlProps<Traveler>> = ({ translations, value, formik, name }) => {
|
|
7
7
|
return (
|
|
8
8
|
<div className={buildClassName(['form__group', hasVisibleError(formik, name) && 'form__group--error'])}>
|
|
9
|
-
<label className="form__label">{translations.TRAVELERS_FORM.
|
|
9
|
+
<label className="form__label">{translations.TRAVELERS_FORM.GENDER_ID} *</label>
|
|
10
10
|
<div className="radiobutton-group">
|
|
11
11
|
<div className="radiobutton">
|
|
12
12
|
<label className="radiobutton__label">
|
|
@@ -19,7 +19,7 @@ const GenderControl: React.FC<ControlProps<Traveler>> = ({ translations, value,
|
|
|
19
19
|
value="m"
|
|
20
20
|
checked={value.gender === 'm'}
|
|
21
21
|
/>
|
|
22
|
-
{translations.TRAVELERS_FORM.
|
|
22
|
+
{translations.TRAVELERS_FORM.MALE_GENDER}
|
|
23
23
|
</label>
|
|
24
24
|
</div>
|
|
25
25
|
|
|
@@ -34,11 +34,11 @@ const GenderControl: React.FC<ControlProps<Traveler>> = ({ translations, value,
|
|
|
34
34
|
value="f"
|
|
35
35
|
checked={value.gender === 'f'}
|
|
36
36
|
/>
|
|
37
|
-
{translations.TRAVELERS_FORM.
|
|
37
|
+
{translations.TRAVELERS_FORM.FEMALE_GENDER}
|
|
38
38
|
</label>
|
|
39
39
|
</div>
|
|
40
40
|
|
|
41
|
-
<div className="radiobutton">
|
|
41
|
+
{/* <div className="radiobutton">
|
|
42
42
|
<label className="radiobutton__label">
|
|
43
43
|
<input
|
|
44
44
|
type="radio"
|
|
@@ -51,7 +51,7 @@ const GenderControl: React.FC<ControlProps<Traveler>> = ({ translations, value,
|
|
|
51
51
|
/>
|
|
52
52
|
{translations.TRAVELERS_FORM.OTHER}
|
|
53
53
|
</label>
|
|
54
|
-
</div>
|
|
54
|
+
</div> */}
|
|
55
55
|
</div>
|
|
56
56
|
</div>
|
|
57
57
|
);
|
|
@@ -615,7 +615,7 @@ const TravelersForm: React.FC<TravelersFormProps> = () => {
|
|
|
615
615
|
<>
|
|
616
616
|
<div className="form__row">
|
|
617
617
|
<div className={buildClassName(['form__group', hasVisibleError(`rooms[${rIndex}].adults[${index}].gender`) && 'form__group--error'])}>
|
|
618
|
-
<label className="form__label">{translations.TRAVELERS_FORM.
|
|
618
|
+
<label className="form__label">{translations.TRAVELERS_FORM.GENDER_ID} *</label>
|
|
619
619
|
<div className="radiobutton-group">
|
|
620
620
|
<div className="radiobutton">
|
|
621
621
|
<label className="radiobutton__label">
|
|
@@ -628,7 +628,7 @@ const TravelersForm: React.FC<TravelersFormProps> = () => {
|
|
|
628
628
|
value="m"
|
|
629
629
|
checked={travelerValues.gender === 'm'}
|
|
630
630
|
/>
|
|
631
|
-
{translations.TRAVELERS_FORM.
|
|
631
|
+
{translations.TRAVELERS_FORM.MALE_GENDER}
|
|
632
632
|
</label>
|
|
633
633
|
</div>
|
|
634
634
|
|
|
@@ -643,11 +643,11 @@ const TravelersForm: React.FC<TravelersFormProps> = () => {
|
|
|
643
643
|
value="f"
|
|
644
644
|
checked={travelerValues.gender === 'f'}
|
|
645
645
|
/>
|
|
646
|
-
{translations.TRAVELERS_FORM.
|
|
646
|
+
{translations.TRAVELERS_FORM.FEMALE_GENDER}
|
|
647
647
|
</label>
|
|
648
648
|
</div>
|
|
649
649
|
|
|
650
|
-
<div className="radiobutton">
|
|
650
|
+
{/* <div className="radiobutton">
|
|
651
651
|
<label className="radiobutton__label">
|
|
652
652
|
<input
|
|
653
653
|
type="radio"
|
|
@@ -660,7 +660,7 @@ const TravelersForm: React.FC<TravelersFormProps> = () => {
|
|
|
660
660
|
/>
|
|
661
661
|
{translations.TRAVELERS_FORM.OTHER}
|
|
662
662
|
</label>
|
|
663
|
-
</div>
|
|
663
|
+
</div> */}
|
|
664
664
|
</div>
|
|
665
665
|
</div>
|
|
666
666
|
</div>
|
|
@@ -729,7 +729,7 @@ const TravelersForm: React.FC<TravelersFormProps> = () => {
|
|
|
729
729
|
<div className="form__row">
|
|
730
730
|
<div
|
|
731
731
|
className={buildClassName(['form__group', hasVisibleError(`rooms[${rIndex}].children[${index}].gender`) && 'form__group--error'])}>
|
|
732
|
-
<label className="form__label">{translations.TRAVELERS_FORM.
|
|
732
|
+
<label className="form__label">{translations.TRAVELERS_FORM.GENDER_ID} *</label>
|
|
733
733
|
<div className="radiobutton-group">
|
|
734
734
|
<div className="radiobutton">
|
|
735
735
|
<label className="radiobutton__label">
|
|
@@ -742,7 +742,7 @@ const TravelersForm: React.FC<TravelersFormProps> = () => {
|
|
|
742
742
|
value="m"
|
|
743
743
|
checked={travelerValues.gender === 'm'}
|
|
744
744
|
/>
|
|
745
|
-
{translations.TRAVELERS_FORM.
|
|
745
|
+
{translations.TRAVELERS_FORM.MALE_GENDER}
|
|
746
746
|
</label>
|
|
747
747
|
</div>
|
|
748
748
|
|
|
@@ -757,11 +757,11 @@ const TravelersForm: React.FC<TravelersFormProps> = () => {
|
|
|
757
757
|
value="f"
|
|
758
758
|
checked={travelerValues.gender === 'f'}
|
|
759
759
|
/>
|
|
760
|
-
{translations.TRAVELERS_FORM.
|
|
760
|
+
{translations.TRAVELERS_FORM.FEMALE_GENDER}
|
|
761
761
|
</label>
|
|
762
762
|
</div>
|
|
763
763
|
|
|
764
|
-
<div className="radiobutton">
|
|
764
|
+
{/* <div className="radiobutton">
|
|
765
765
|
<label className="radiobutton__label">
|
|
766
766
|
<input
|
|
767
767
|
type="radio"
|
|
@@ -774,7 +774,7 @@ const TravelersForm: React.FC<TravelersFormProps> = () => {
|
|
|
774
774
|
/>
|
|
775
775
|
{translations.TRAVELERS_FORM.OTHER}
|
|
776
776
|
</label>
|
|
777
|
-
</div>
|
|
777
|
+
</div> */}
|
|
778
778
|
</div>
|
|
779
779
|
</div>
|
|
780
780
|
</div>
|
|
@@ -530,7 +530,7 @@ const Icon: React.FC<IconProps> = ({ name, className, title, width, height }) =>
|
|
|
530
530
|
</svg>
|
|
531
531
|
);
|
|
532
532
|
|
|
533
|
-
case 'ui-
|
|
533
|
+
case 'ui-list':
|
|
534
534
|
return (
|
|
535
535
|
<svg
|
|
536
536
|
className={['icon', `icon--${name}`, className].filter((className) => !isEmpty(className)).join(' ')}
|
|
@@ -16,13 +16,15 @@ import { addDays, addMonths } from 'date-fns';
|
|
|
16
16
|
import { DateRange } from '../../../booking-product/types';
|
|
17
17
|
import { QSMState, setFromDate, setToDate } from '../../store/qsm-slice';
|
|
18
18
|
import { FieldConfig } from '../../types';
|
|
19
|
+
import { getTranslations } from '../../../shared/utils/localization-util';
|
|
19
20
|
|
|
20
21
|
const QSMContainer: React.FC = () => {
|
|
21
22
|
const dispatch = useDispatch();
|
|
22
23
|
const isMobile = useMediaQuery('(max-width: 768px)');
|
|
23
24
|
const qsmState = useSelector((state: QSMRootState) => state.qsm);
|
|
24
25
|
const { mobileFilterType, fromDate, toDate } = qsmState;
|
|
25
|
-
const { searchFields, askTravelers, submitIcon,
|
|
26
|
+
const { searchFields, askTravelers, submitIcon, onSubmit, travelTypes, languageCode } = useContext(QSMConfigurationContext);
|
|
27
|
+
const translations = getTranslations(languageCode ?? 'en-GB');
|
|
26
28
|
|
|
27
29
|
useEffect(() => {
|
|
28
30
|
if (fromDate || toDate) return;
|
|
@@ -96,13 +98,13 @@ const QSMContainer: React.FC = () => {
|
|
|
96
98
|
<span className="qsm__tab__icons">
|
|
97
99
|
<Icon name="ui-location" height={16} />
|
|
98
100
|
</span>
|
|
99
|
-
|
|
101
|
+
{translations.QSM.MULTIDESTINATION}
|
|
100
102
|
</button>
|
|
101
103
|
<button type="button" className="qsm__tab">
|
|
102
104
|
<span className="qsm__tab__icons">
|
|
103
105
|
<Icon name="ui-suitcase" height={16} />
|
|
104
106
|
</span>
|
|
105
|
-
|
|
107
|
+
{translations.QSM.PACKAGES}
|
|
106
108
|
</button>
|
|
107
109
|
<button type="button" className="qsm__tab qsm__tab--active">
|
|
108
110
|
<span className="qsm__tab__icons">
|
|
@@ -110,43 +112,43 @@ const QSMContainer: React.FC = () => {
|
|
|
110
112
|
+
|
|
111
113
|
<Icon name="ui-bed" height={14} />
|
|
112
114
|
</span>
|
|
113
|
-
|
|
115
|
+
{translations.QSM.TRANSPORT_HOTEL}
|
|
114
116
|
</button>
|
|
115
117
|
<button type="button" className="qsm__tab">
|
|
116
118
|
<span className="qsm__tab__icons">
|
|
117
119
|
<Icon name="ui-bed" height={16} />
|
|
118
120
|
</span>
|
|
119
|
-
|
|
121
|
+
{translations.QSM.ACCOMMODATION}
|
|
120
122
|
</button>
|
|
121
123
|
<button type="button" className="qsm__tab">
|
|
122
124
|
<span className="qsm__tab__icons">
|
|
123
125
|
<Icon name="ui-flight" height={16} />
|
|
124
126
|
</span>
|
|
125
|
-
|
|
127
|
+
{translations.QSM.TRANSPORTS}
|
|
126
128
|
</button>
|
|
127
129
|
<button type="button" className="qsm__tab">
|
|
128
130
|
<span className="qsm__tab__icons">
|
|
129
131
|
<Icon name="ui-ticket" height={16} />
|
|
130
132
|
</span>
|
|
131
|
-
|
|
133
|
+
{translations.QSM.TICKET_ONLY}
|
|
132
134
|
</button>
|
|
133
135
|
<button type="button" className="qsm__tab">
|
|
134
136
|
<span className="qsm__tab__icons">
|
|
135
137
|
<Icon name="ui-car" height={16} />
|
|
136
138
|
</span>
|
|
137
|
-
|
|
139
|
+
{translations.QSM.RENT_A_CAR}
|
|
138
140
|
</button>
|
|
139
141
|
<button type="button" className="qsm__tab">
|
|
140
142
|
<span className="qsm__tab__icons">
|
|
141
143
|
<Icon name="ui-backforward" height={16} />
|
|
142
144
|
</span>
|
|
143
|
-
|
|
145
|
+
{translations.QSM.TRANSFERS}
|
|
144
146
|
</button>
|
|
145
147
|
<button type="button" className="qsm__tab">
|
|
146
148
|
<span className="qsm__tab__icons">
|
|
147
149
|
<Icon name="ui-ship" height={16} />
|
|
148
150
|
</span>
|
|
149
|
-
|
|
151
|
+
{translations.QSM.CRUISES}
|
|
150
152
|
</button>
|
|
151
153
|
</div>
|
|
152
154
|
<div className="qsm__filter">
|
|
@@ -164,7 +166,7 @@ const QSMContainer: React.FC = () => {
|
|
|
164
166
|
readOnly
|
|
165
167
|
className="radiobutton__input"
|
|
166
168
|
/>
|
|
167
|
-
<span>
|
|
169
|
+
<span>{translations.QSM.ONE_ACCOMMODATION}</span>
|
|
168
170
|
</label>
|
|
169
171
|
</div>
|
|
170
172
|
<div className="radiobutton">
|
|
@@ -179,7 +181,7 @@ const QSMContainer: React.FC = () => {
|
|
|
179
181
|
className="radiobutton__input"
|
|
180
182
|
disabled={true}
|
|
181
183
|
/>
|
|
182
|
-
<span>
|
|
184
|
+
<span>{translations.QSM.MULTIPLE_ACCOMMODATIONS}</span>
|
|
183
185
|
</label>
|
|
184
186
|
</div>
|
|
185
187
|
</div>
|
|
@@ -203,7 +205,7 @@ const QSMContainer: React.FC = () => {
|
|
|
203
205
|
|
|
204
206
|
<button type="button" className="cta" onClick={handleSubmit}>
|
|
205
207
|
{submitIcon && submitIcon.toString().length > 0 && <span>{submitIcon}</span>}
|
|
206
|
-
<span>{
|
|
208
|
+
<span>{translations.QSM.CONFIRM}</span>
|
|
207
209
|
</button>
|
|
208
210
|
</div>
|
|
209
211
|
</div>
|
|
@@ -15,9 +15,11 @@ import TravelInput from '../travel-input';
|
|
|
15
15
|
import { format } from 'date-fns';
|
|
16
16
|
import QSMConfigurationContext from '../../qsm-configuration-context';
|
|
17
17
|
import { TypeaheadOption } from '../../types';
|
|
18
|
+
import { getTranslations } from '../../../shared/utils/localization-util';
|
|
18
19
|
|
|
19
20
|
const MobileFilterModal: React.FC = () => {
|
|
20
|
-
const { datesIcon } = useContext(QSMConfigurationContext);
|
|
21
|
+
const { datesIcon, languageCode } = useContext(QSMConfigurationContext);
|
|
22
|
+
const translations = getTranslations(languageCode ?? 'en-GB');
|
|
21
23
|
const dispatch = useDispatch();
|
|
22
24
|
const { mobileFilterType, mobileDatePickerMode, activeSearchFieldProps, fromDate, toDate } = useSelector((state: QSMRootState) => state.qsm);
|
|
23
25
|
|
|
@@ -103,7 +105,7 @@ const MobileFilterModal: React.FC = () => {
|
|
|
103
105
|
{/* header */}
|
|
104
106
|
<div className="mobile-qsm-filter__modal-header">
|
|
105
107
|
<div className="mobile-qsm-filter__modal-header-row">
|
|
106
|
-
<span className="mobile-qsm-filter__modal-header-title">
|
|
108
|
+
<span className="mobile-qsm-filter__modal-header-title">{translations.QSM.CHOOSE_DATES}</span>
|
|
107
109
|
<span className="mobile-qsm-filter__modal-header-close" onClick={closeModal}></span>
|
|
108
110
|
</div>
|
|
109
111
|
</div>
|
|
@@ -114,12 +116,12 @@ const MobileFilterModal: React.FC = () => {
|
|
|
114
116
|
<div className="qsm__double-input__wrapper">
|
|
115
117
|
<label className="qsm__input-wrapper">
|
|
116
118
|
{datesIcon && <span className="qsm__input-icon">{datesIcon}</span>}
|
|
117
|
-
<span className="qsm__label">
|
|
119
|
+
<span className="qsm__label">{translations.QSM.DEPARTURE_DATE}</span>
|
|
118
120
|
<input
|
|
119
121
|
type="text"
|
|
120
122
|
id="vertrek"
|
|
121
123
|
className="qsm__input u-ps-2"
|
|
122
|
-
placeholder=
|
|
124
|
+
placeholder={translations.QSM.DEPARTURE_DATE}
|
|
123
125
|
readOnly
|
|
124
126
|
value={fromDate ? format(new Date(fromDate), 'dd/MM/yyyy') : ''}
|
|
125
127
|
/>
|
|
@@ -130,12 +132,12 @@ const MobileFilterModal: React.FC = () => {
|
|
|
130
132
|
{mobileDatePickerMode === 'range' && (
|
|
131
133
|
<label className="qsm__input-wrapper">
|
|
132
134
|
{datesIcon && <span className="qsm__input-icon">{datesIcon}</span>}
|
|
133
|
-
<span className="qsm__label qsm__label--second-input-label">
|
|
135
|
+
<span className="qsm__label qsm__label--second-input-label">{translations.QSM.RETURN_DATE}</span>
|
|
134
136
|
<input
|
|
135
137
|
type="text"
|
|
136
138
|
id="retour"
|
|
137
139
|
className="qsm__input"
|
|
138
|
-
placeholder=
|
|
140
|
+
placeholder={translations.QSM.RETURN_DATE}
|
|
139
141
|
readOnly
|
|
140
142
|
value={toDate ? format(new Date(toDate), 'dd/MM/yyyy') : ''}
|
|
141
143
|
/>
|
|
@@ -171,7 +173,7 @@ const MobileFilterModal: React.FC = () => {
|
|
|
171
173
|
closeModal();
|
|
172
174
|
}
|
|
173
175
|
}}>
|
|
174
|
-
|
|
176
|
+
{translations.QSM.CONFIRM}
|
|
175
177
|
</button>
|
|
176
178
|
</div>
|
|
177
179
|
</div>
|
|
@@ -215,7 +217,7 @@ const MobileFilterModal: React.FC = () => {
|
|
|
215
217
|
</div>
|
|
216
218
|
<div className="mobile-qsm-filter__modal-footer">
|
|
217
219
|
<button className="cta" onClick={closeModal}>
|
|
218
|
-
|
|
220
|
+
{translations.QSM.CONFIRM}
|
|
219
221
|
</button>
|
|
220
222
|
</div>
|
|
221
223
|
{/* </div> */}
|
|
@@ -236,7 +238,7 @@ const MobileFilterModal: React.FC = () => {
|
|
|
236
238
|
{/* header */}
|
|
237
239
|
<div className="mobile-qsm-filter__modal-header">
|
|
238
240
|
<div className="mobile-qsm-filter__modal-header-row">
|
|
239
|
-
<span className="mobile-qsm-filter__modal-header-title">
|
|
241
|
+
<span className="mobile-qsm-filter__modal-header-title">{translations.QSM.TRAVELERS}</span>
|
|
240
242
|
<span className="mobile-qsm-filter__modal-header-close" onClick={closeModal}></span>
|
|
241
243
|
</div>
|
|
242
244
|
</div>
|
|
@@ -249,7 +251,7 @@ const MobileFilterModal: React.FC = () => {
|
|
|
249
251
|
|
|
250
252
|
<div className="mobile-qsm-filter__modal-footer">
|
|
251
253
|
<button className="cta" onClick={closeModal}>
|
|
252
|
-
|
|
254
|
+
{translations.QSM.CONFIRM}
|
|
253
255
|
</button>
|
|
254
256
|
</div>
|
|
255
257
|
</div>
|
|
@@ -4,17 +4,19 @@ import { QSMRootState } from '../../store/qsm-store';
|
|
|
4
4
|
import { setSelectedTravelClass } from '../../store/qsm-slice';
|
|
5
5
|
import QSMConfigurationContext from '../../qsm-configuration-context';
|
|
6
6
|
import ItemPicker from '../item-picker';
|
|
7
|
+
import { getTranslations } from '../../../shared/utils/localization-util';
|
|
7
8
|
|
|
8
9
|
const TravelClassPicker: React.FC = () => {
|
|
9
|
-
const { travelClasses } = useContext(QSMConfigurationContext);
|
|
10
|
+
const { travelClasses, languageCode } = useContext(QSMConfigurationContext);
|
|
11
|
+
const translations = getTranslations(languageCode ?? 'en-GB');
|
|
10
12
|
const { selectedTravelClass } = useSelector((state: QSMRootState) => state.qsm);
|
|
11
13
|
|
|
12
14
|
return (
|
|
13
15
|
<ItemPicker
|
|
14
16
|
items={travelClasses}
|
|
15
17
|
selection={selectedTravelClass}
|
|
16
|
-
label=
|
|
17
|
-
placeholder=
|
|
18
|
+
label={translations.QSM.TRAVEL_CLASS_LABEL}
|
|
19
|
+
placeholder={translations.QSM.TRAVEL_CLASS_PLACEHOLDER}
|
|
18
20
|
classModifier="travel-class-picker__items"
|
|
19
21
|
onPick={setSelectedTravelClass}
|
|
20
22
|
/>
|
|
@@ -3,16 +3,19 @@ import { useDispatch, useSelector } from 'react-redux';
|
|
|
3
3
|
import { QSMRootState } from '../../store/qsm-store';
|
|
4
4
|
import { setAdults, setKids, setBabies, setRooms, addRoom, removeRoom, updateRoomTraveler } from '../../store/qsm-slice';
|
|
5
5
|
import QSMConfigurationContext from '../../qsm-configuration-context';
|
|
6
|
+
import { getTranslations } from '../../../shared/utils/localization-util';
|
|
6
7
|
import TravelClassPicker from '../travel-class-picker';
|
|
7
8
|
import TravelTypePicker from '../travel-type-picker';
|
|
8
9
|
import Icon from '../icon';
|
|
9
10
|
|
|
10
11
|
const TravelInput: React.FC = () => {
|
|
11
|
-
const { type, askRooms, maxTravelers, defaultTravelers, maxChildAge, maxInfantAge, askTravelType, askTravelClass } =
|
|
12
|
+
const { type, askRooms, maxTravelers, defaultTravelers, maxChildAge, maxInfantAge, askTravelType, askTravelClass, languageCode } =
|
|
13
|
+
useContext(QSMConfigurationContext);
|
|
12
14
|
const areTravelersInRooms = type !== 'flight' && askRooms;
|
|
13
15
|
|
|
14
16
|
const dispatch = useDispatch();
|
|
15
17
|
const { adults, kids, babies, rooms } = useSelector((state: QSMRootState) => state.qsm);
|
|
18
|
+
const translations = getTranslations(languageCode ?? 'en-GB');
|
|
16
19
|
|
|
17
20
|
const getTravelerButtonClass = (disabled: boolean) => `button button--increment ${disabled ? 'button--disabled' : ''}`;
|
|
18
21
|
|
|
@@ -67,9 +70,9 @@ const TravelInput: React.FC = () => {
|
|
|
67
70
|
|
|
68
71
|
// Compute age labels dynamically
|
|
69
72
|
const ageLabels = {
|
|
70
|
-
adults: maxChildAge ? `${maxChildAge + 1}+
|
|
71
|
-
kids: maxChildAge && maxInfantAge ? `${maxInfantAge + 1}-${maxChildAge}
|
|
72
|
-
babies: maxInfantAge !== undefined ? `0-${maxInfantAge}
|
|
73
|
+
adults: maxChildAge ? `${maxChildAge + 1}+ ${translations.PRODUCT.YEAR}` : `12+ ${translations.PRODUCT.YEAR}`,
|
|
74
|
+
kids: maxChildAge && maxInfantAge ? `${maxInfantAge + 1}-${maxChildAge} ${translations.PRODUCT.YEAR}` : `2-11 ${translations.PRODUCT.YEAR}`,
|
|
75
|
+
babies: maxInfantAge !== undefined ? `0-${maxInfantAge} ${translations.PRODUCT.YEAR}` : `0-1 ${translations.PRODUCT.YEAR}`
|
|
73
76
|
};
|
|
74
77
|
|
|
75
78
|
return (
|
|
@@ -78,7 +81,7 @@ const TravelInput: React.FC = () => {
|
|
|
78
81
|
<div>
|
|
79
82
|
<div className="passenger-picker__rooms-header">
|
|
80
83
|
<h4 className="passenger-picker__rooms-header-title">
|
|
81
|
-
|
|
84
|
+
{translations.SHARED.ROOMS}: <span className="passenger-picker__rooms-header-count">{rooms.length}</span>
|
|
82
85
|
</h4>
|
|
83
86
|
{rooms.length < 4 && (
|
|
84
87
|
<div
|
|
@@ -88,7 +91,7 @@ const TravelInput: React.FC = () => {
|
|
|
88
91
|
handleAddRoom();
|
|
89
92
|
}
|
|
90
93
|
}}>
|
|
91
|
-
|
|
94
|
+
{translations.QSM.ADD_ROOM}
|
|
92
95
|
</div>
|
|
93
96
|
)}
|
|
94
97
|
</div>
|
|
@@ -129,7 +132,7 @@ const TravelInput: React.FC = () => {
|
|
|
129
132
|
{rooms.length > 1 && (
|
|
130
133
|
<div className="passenger-picker__remove-room">
|
|
131
134
|
<button type="button" className="cta--remove" onClick={() => handleRemoveRoom(idx)}>
|
|
132
|
-
|
|
135
|
+
{translations.QSM.REMOVE_ROOM}
|
|
133
136
|
</button>
|
|
134
137
|
</div>
|
|
135
138
|
)}
|
|
@@ -143,7 +146,7 @@ const TravelInput: React.FC = () => {
|
|
|
143
146
|
transform="translate(-96 864)"
|
|
144
147
|
/>
|
|
145
148
|
</svg>
|
|
146
|
-
<span className="passenger-picker__info-message-explanation">
|
|
149
|
+
<span className="passenger-picker__info-message-explanation">{translations.QSM.MAX_TRAVELERS_REACHED}</span>
|
|
147
150
|
</div>
|
|
148
151
|
)}
|
|
149
152
|
|
|
@@ -158,7 +161,7 @@ const TravelInput: React.FC = () => {
|
|
|
158
161
|
{/* Adults */}
|
|
159
162
|
<div className="passenger-picker__item">
|
|
160
163
|
<div className="passenger-picker__item-text">
|
|
161
|
-
<span>
|
|
164
|
+
<span>{translations.QSM.ADULTS}</span>
|
|
162
165
|
<span className="passenger-picker__item-text-age">{ageLabels.adults}</span>
|
|
163
166
|
</div>
|
|
164
167
|
<div className="decrement-increment__ui">
|
|
@@ -177,7 +180,7 @@ const TravelInput: React.FC = () => {
|
|
|
177
180
|
{/* Children */}
|
|
178
181
|
<div className="passenger-picker__item">
|
|
179
182
|
<div className="passenger-picker__item-text">
|
|
180
|
-
<span>
|
|
183
|
+
<span>{translations.QSM.CHILDREN}</span>
|
|
181
184
|
<span className="passenger-picker__item-text-age">{ageLabels.kids}</span>
|
|
182
185
|
</div>
|
|
183
186
|
<div className="decrement-increment__ui">
|
|
@@ -194,7 +197,7 @@ const TravelInput: React.FC = () => {
|
|
|
194
197
|
{/* Babies */}
|
|
195
198
|
<div className="passenger-picker__item">
|
|
196
199
|
<div className="passenger-picker__item-text">
|
|
197
|
-
<span>
|
|
200
|
+
<span>{translations.QSM.BABIES}</span>
|
|
198
201
|
<span className="passenger-picker__item-text-age">{ageLabels.babies}</span>
|
|
199
202
|
</div>
|
|
200
203
|
<div className="decrement-increment__ui">
|
|
@@ -220,7 +223,7 @@ const TravelInput: React.FC = () => {
|
|
|
220
223
|
transform="translate(-96 864)"
|
|
221
224
|
/>
|
|
222
225
|
</svg>
|
|
223
|
-
<span className="passenger-picker__info-message-explanation">
|
|
226
|
+
<span className="passenger-picker__info-message-explanation">{translations.QSM.MAX_TRAVELERS_REACHED}</span>
|
|
224
227
|
</div>
|
|
225
228
|
)}
|
|
226
229
|
|
|
@@ -6,6 +6,7 @@ import useMediaQuery from '../../../shared/utils/use-media-query-util';
|
|
|
6
6
|
import { QSMRootState } from '../../store/qsm-store';
|
|
7
7
|
import QSMConfigurationContext from '../../qsm-configuration-context';
|
|
8
8
|
import Icon from '../icon';
|
|
9
|
+
import { getTranslations } from '../../../shared/utils/localization-util';
|
|
9
10
|
|
|
10
11
|
const selectTravelerSummary = (state: QSMRootState, areTravelersInRooms: boolean | undefined) => {
|
|
11
12
|
const { adults, kids, babies, rooms, selectedTravelType } = state.qsm;
|
|
@@ -29,7 +30,9 @@ const TravelInputGroup: React.FC = () => {
|
|
|
29
30
|
const isSmallScreen = useMediaQuery('(max-width: 768px)');
|
|
30
31
|
const [isOpen, setIsOpen] = useState(false);
|
|
31
32
|
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
32
|
-
const { type, askRooms, defaultTravelers, maxTravelers } = useContext(QSMConfigurationContext);
|
|
33
|
+
const { type, askRooms, defaultTravelers, maxTravelers, languageCode } = useContext(QSMConfigurationContext);
|
|
34
|
+
const translations = getTranslations(languageCode ?? 'en-GB');
|
|
35
|
+
|
|
33
36
|
const areTravelersInRooms = type !== 'flight' && askRooms;
|
|
34
37
|
|
|
35
38
|
const { adults, rooms } = useSelector((s: QSMRootState) => s.qsm);
|
|
@@ -86,8 +89,16 @@ const TravelInputGroup: React.FC = () => {
|
|
|
86
89
|
<div ref={wrapperRef} className="qsm__single-input-wrapper qsm__single-input-wrapper--travel">
|
|
87
90
|
<Icon name="ui-user" height={16} />
|
|
88
91
|
|
|
89
|
-
<span className="qsm__label">
|
|
90
|
-
<input
|
|
92
|
+
<span className="qsm__label">{translations.QSM.TRAVELERS_LABEL}</span>
|
|
93
|
+
<input
|
|
94
|
+
type="text"
|
|
95
|
+
id="traveler"
|
|
96
|
+
className="qsm__input u-ps-2"
|
|
97
|
+
placeholder={translations.QSM.TRAVELERS_LABEL}
|
|
98
|
+
readOnly
|
|
99
|
+
onClick={handleClick}
|
|
100
|
+
value={travelerSummary}
|
|
101
|
+
/>
|
|
91
102
|
|
|
92
103
|
{!isSmallScreen && isOpen && (
|
|
93
104
|
<div>
|