@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.
Files changed (64) hide show
  1. package/build/build-cjs/index.js +1628 -376
  2. package/build/build-cjs/qsm/types.d.ts +0 -1
  3. package/build/build-cjs/search-results/components/filters/filters.d.ts +2 -2
  4. package/build/build-cjs/search-results/components/flight/flight-results.d.ts +2 -0
  5. package/build/build-cjs/search-results/components/hotel/hotel-card.d.ts +1 -0
  6. package/build/build-cjs/search-results/components/itinerary/index.d.ts +2 -2
  7. package/build/build-cjs/search-results/store/search-results-slice.d.ts +11 -2
  8. package/build/build-cjs/search-results/types.d.ts +4 -14
  9. package/build/build-esm/index.js +1628 -376
  10. package/build/build-esm/qsm/types.d.ts +0 -1
  11. package/build/build-esm/search-results/components/filters/filters.d.ts +2 -2
  12. package/build/build-esm/search-results/components/flight/flight-results.d.ts +2 -0
  13. package/build/build-esm/search-results/components/hotel/hotel-card.d.ts +1 -0
  14. package/build/build-esm/search-results/components/itinerary/index.d.ts +2 -2
  15. package/build/build-esm/search-results/store/search-results-slice.d.ts +11 -2
  16. package/build/build-esm/search-results/types.d.ts +4 -14
  17. package/package.json +2 -2
  18. package/src/booking-wizard/features/booking/booking-self-contained.tsx +0 -1
  19. package/src/booking-wizard/features/travelers-form/controls/gender-control.tsx +5 -5
  20. package/src/booking-wizard/features/travelers-form/travelers-form.tsx +10 -10
  21. package/src/content/components/icon.tsx +1 -1
  22. package/src/content/features/content-page/content-page-self-contained.tsx +0 -1
  23. package/src/qsm/components/QSMContainer/qsm-container.tsx +15 -13
  24. package/src/qsm/components/mobile-filter-modal/index.tsx +12 -10
  25. package/src/qsm/components/travel-class-picker/index.tsx +5 -3
  26. package/src/qsm/components/travel-input/index.tsx +15 -12
  27. package/src/qsm/components/travel-input-group/index.tsx +14 -3
  28. package/src/qsm/components/travel-nationality-picker/index.tsx +5 -3
  29. package/src/qsm/components/travel-type-picker/index.tsx +5 -3
  30. package/src/qsm/qsm-configuration-context.ts +0 -1
  31. package/src/qsm/types.ts +0 -1
  32. package/src/search-results/components/filters/filters.tsx +15 -16
  33. package/src/search-results/components/flight/flight-results.tsx +168 -1099
  34. package/src/search-results/components/hotel/hotel-accommodation-results.tsx +21 -24
  35. package/src/search-results/components/hotel/hotel-card.tsx +4 -3
  36. package/src/search-results/components/icon.tsx +1 -1
  37. package/src/search-results/components/itinerary/index.tsx +233 -131
  38. package/src/search-results/components/round-trip/round-trip-results.tsx +1 -1
  39. package/src/search-results/components/search-results-container/search-results-container.tsx +45 -33
  40. package/src/search-results/components/spinner/spinner.tsx +3 -1
  41. package/src/search-results/components/tab-views/index.tsx +13 -7
  42. package/src/search-results/features/flights/flight-search-results-self-contained.tsx +4 -13
  43. package/src/search-results/features/hotels/hotel-flight-search-results-self-contained.tsx +5 -1
  44. package/src/search-results/features/hotels/hotel-search-results-self-contained.tsx +4 -13
  45. package/src/search-results/features/roundtrips/roundtrip-search-results-self-contained.tsx +5 -1
  46. package/src/search-results/store/search-results-slice.ts +37 -3
  47. package/src/search-results/types.ts +2 -15
  48. package/src/shared/translations/ar-SA.json +70 -0
  49. package/src/shared/translations/da-DK.json +70 -0
  50. package/src/shared/translations/de-DE.json +70 -0
  51. package/src/shared/translations/en-GB.json +71 -1
  52. package/src/shared/translations/es-ES.json +70 -0
  53. package/src/shared/translations/fr-BE.json +71 -1
  54. package/src/shared/translations/fr-FR.json +70 -0
  55. package/src/shared/translations/is-IS.json +72 -2
  56. package/src/shared/translations/it-IT.json +70 -0
  57. package/src/shared/translations/ja-JP.json +72 -2
  58. package/src/shared/translations/nl-BE.json +70 -0
  59. package/src/shared/translations/nl-NL.json +70 -0
  60. package/src/shared/translations/no-NO.json +72 -2
  61. package/src/shared/translations/pl-PL.json +70 -0
  62. package/src/shared/translations/pt-PT.json +70 -0
  63. package/src/shared/translations/sv-SE.json +72 -2
  64. package/styles/components/_search.scss +7 -1
@@ -35,7 +35,6 @@ export interface QSMConfiguration {
35
35
  maxChildAge?: number;
36
36
  maxInfantAge?: number;
37
37
  onSubmit: (data: any) => void;
38
- submitLabel: string;
39
38
  submitIcon: ReactNode;
40
39
  nationalities: Nationality[];
41
40
  languageCode?: string;
@@ -2,8 +2,8 @@ import React from 'react';
2
2
  import { Filter } from '../../types';
3
3
  interface FiltersProps {
4
4
  filters: Filter[];
5
- isMobileFiltersOpen: boolean;
6
- handleSetIsMobileFiltersOpen: () => void;
5
+ isOpen: boolean;
6
+ handleSetIsOpen: () => void;
7
7
  handleApplyFilters: () => void;
8
8
  isLoading?: boolean;
9
9
  }
@@ -1,5 +1,7 @@
1
1
  import React from 'react';
2
+ import { BookingPackageFlight } from '@qite/tide-client';
2
3
  interface FlightResultsProps {
4
+ flights: BookingPackageFlight[];
3
5
  isDeparture?: boolean;
4
6
  }
5
7
  declare const FlightResults: React.FC<FlightResultsProps>;
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { HotelResult } from '../../types';
3
3
  interface HotelCardProps {
4
4
  result: HotelResult;
5
+ translations?: any;
5
6
  }
6
7
  declare const HotelCard: React.FC<HotelCardProps>;
7
8
  export default HotelCard;
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  interface ItineraryProps {
3
- isMobileFiltersOpen: boolean;
4
- handleSetIsMobileFiltersOpen: () => void;
3
+ isOpen: boolean;
4
+ handleSetIsOpen: () => void;
5
5
  isLoading?: boolean;
6
6
  }
7
7
  declare const Itinerary: React.FC<ItineraryProps>;
@@ -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">, 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">;
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.34",
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.123",
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.GENDER} *</label>
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.MALE}
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.FEMALE}
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.GENDER} *</label>
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.MALE}
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.FEMALE}
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.GENDER} *</label>
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.MALE}
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.FEMALE}
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-comparator':
533
+ case 'ui-list':
534
534
  return (
535
535
  <svg
536
536
  className={['icon', `icon--${name}`, className].filter((className) => !isEmpty(className)).join(' ')}
@@ -169,7 +169,6 @@ const configuration: QSMConfiguration = {
169
169
  maxInfantAge: 2,
170
170
 
171
171
  onSubmit: () => {},
172
- submitLabel: 'Zoeken',
173
172
  submitIcon: ''
174
173
  };
175
174
 
@@ -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, submitLabel, onSubmit, travelTypes } = useContext(QSMConfigurationContext);
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
- Multidestination
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
- Packages
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
- Transport + hotel
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
- Accommodation
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
- Transports
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
- Ticket Only
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
- Rent a car
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
- Transfers
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
- Cruises
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>One accommodation</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>Multiple accommodations</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>{submitLabel}</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">Kies data</span>
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">Vertrek</span>
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="Datum"
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">Retour</span>
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="Datum"
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
- Bevestigen
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
- Bevestigen
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">Reizigers</span>
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
- Bevestigen
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="Reisklasse"
17
- placeholder="Selecteer reisklasse"
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 } = useContext(QSMConfigurationContext);
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}+ jaar` : '12+ jaar',
71
- kids: maxChildAge && maxInfantAge ? `${maxInfantAge + 1}-${maxChildAge} jaar` : '2-11 jaar',
72
- babies: maxInfantAge !== undefined ? `0-${maxInfantAge} jaar` : '0-1 jaar'
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
- Kamers: <span className="passenger-picker__rooms-header-count">{rooms.length}</span>
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
- Kamer toevoegen
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
- Verwijder kamer
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">Je zit aan het maximale aantal personen</span>
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>Volwassenen</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>Kinderen</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>Baby&squot;s</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">Je zit aan het maximale aantal personen</span>
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">Met wie ga je?</span>
90
- <input type="text" id="traveler" className="qsm__input u-ps-2" placeholder="Met wie ga je?" readOnly onClick={handleClick} value={travelerSummary} />
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>