@qite/tide-booking-component 1.4.33 → 1.4.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/build/build-cjs/index.js +1674 -416
  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 +0 -14
  9. package/build/build-esm/index.js +1674 -416
  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 +0 -14
  17. package/package.json +77 -77
  18. package/src/booking-product/components/product.tsx +26 -22
  19. package/src/booking-wizard/features/booking/booking-self-contained.tsx +303 -304
  20. package/src/booking-wizard/features/travelers-form/controls/gender-control.tsx +5 -5
  21. package/src/booking-wizard/features/travelers-form/travelers-form.tsx +10 -10
  22. package/src/content/components/icon.tsx +1 -1
  23. package/src/content/features/content-page/content-page-self-contained.tsx +0 -1
  24. package/src/qsm/components/QSMContainer/qsm-container.tsx +217 -218
  25. package/src/qsm/components/mobile-filter-modal/index.tsx +12 -10
  26. package/src/qsm/components/travel-class-picker/index.tsx +5 -3
  27. package/src/qsm/components/travel-input/index.tsx +15 -12
  28. package/src/qsm/components/travel-input-group/index.tsx +14 -3
  29. package/src/qsm/components/travel-nationality-picker/index.tsx +5 -3
  30. package/src/qsm/components/travel-type-picker/index.tsx +5 -3
  31. package/src/qsm/qsm-configuration-context.ts +0 -1
  32. package/src/qsm/store/qsm-slice.ts +261 -261
  33. package/src/qsm/types.ts +144 -145
  34. package/src/search-results/components/filters/filters.tsx +15 -16
  35. package/src/search-results/components/flight/flight-results.tsx +168 -1099
  36. package/src/search-results/components/hotel/hotel-accommodation-results.tsx +21 -24
  37. package/src/search-results/components/hotel/hotel-card.tsx +4 -3
  38. package/src/search-results/components/icon.tsx +1 -1
  39. package/src/search-results/components/itinerary/index.tsx +229 -129
  40. package/src/search-results/components/round-trip/round-trip-results.tsx +1 -1
  41. package/src/search-results/components/search-results-container/search-results-container.tsx +353 -337
  42. package/src/search-results/components/spinner/spinner.tsx +3 -1
  43. package/src/search-results/components/tab-views/index.tsx +13 -7
  44. package/src/search-results/features/flights/flight-search-results-self-contained.tsx +1 -14
  45. package/src/search-results/features/hotels/hotel-search-results-self-contained.tsx +1 -14
  46. package/src/search-results/store/search-results-slice.ts +37 -3
  47. package/src/search-results/types.ts +0 -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
@@ -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
 
@@ -1,218 +1,217 @@
1
- import React, { useContext, useEffect, useMemo } from 'react';
2
- import { useDispatch, useSelector } from 'react-redux';
3
- import { QSMRootState } from '../../store/qsm-store';
4
- import QSMConfigurationContext from '../../qsm-configuration-context';
5
- import useMediaQuery from '../../../shared/utils/use-media-query-util';
6
- import MobileFilterModal from '../mobile-filter-modal';
7
- import SearchInputGroup from '../search-input-group';
8
- import DoubleSearchInputGroup from '../double-search-input-group';
9
- import Dates from '../../../booking-product/components/dates';
10
- import TravelInputGroup from '../travel-input-group';
11
- import TravelClassPicker from '../travel-class-picker';
12
- import TravelTypePicker from '../travel-type-picker';
13
- import Icon from '../icon';
14
- import TravelNationalityPicker from '../travel-nationality-picker';
15
- import { addDays, addMonths } from 'date-fns';
16
- import { DateRange } from '../../../booking-product/types';
17
- import { QSMState, setFromDate, setToDate } from '../../store/qsm-slice';
18
- import { FieldConfig } from '../../types';
19
-
20
- const QSMContainer: React.FC = () => {
21
- const dispatch = useDispatch();
22
- const isMobile = useMediaQuery('(max-width: 768px)');
23
- const qsmState = useSelector((state: QSMRootState) => state.qsm);
24
- const { mobileFilterType, fromDate, toDate } = qsmState;
25
- const { searchFields, askTravelers, submitIcon, submitLabel, onSubmit } = useContext(QSMConfigurationContext);
26
-
27
- useEffect(() => {
28
- if (fromDate || toDate) return;
29
-
30
- const startDate = addMonths(new Date(), 1);
31
- const endDate = addDays(startDate, 7);
32
-
33
- dispatch(setFromDate(startDate.toISOString()));
34
- dispatch(setToDate(endDate.toISOString()));
35
- }, [fromDate, toDate, dispatch]);
36
-
37
- const dateRange = useMemo<DateRange | undefined>(() => {
38
- if (!fromDate || !toDate) return undefined;
39
-
40
- return {
41
- fromDate: new Date(fromDate),
42
- toDate: new Date(toDate)
43
- };
44
- }, [fromDate, toDate]);
45
-
46
- const handleDateChange = (value: DateRange) => {
47
- dispatch(setFromDate(value.fromDate?.toISOString()));
48
- dispatch(setToDate(value.toDate?.toISOString()));
49
- };
50
-
51
- const handleSubmit = () => {
52
- if (!onSubmit) return;
53
-
54
- const { fromDate, toDate, travelers, selectedTravelClass, selectedTravelType, selectedNationality, adults, kids, babies, rooms, selectedFlexRange } =
55
- qsmState;
56
-
57
- const payload = {
58
- fromDate,
59
- toDate,
60
- travelers,
61
- travelClass: selectedTravelClass,
62
- travelType: selectedTravelType,
63
- nationality: selectedNationality,
64
- adults,
65
- kids,
66
- babies,
67
- rooms,
68
- dateFlexibility: selectedFlexRange
69
- };
70
-
71
- addSearchFieldsToPayload(payload, searchFields, qsmState);
72
- onSubmit(payload);
73
- };
74
-
75
- const addSearchFieldsToPayload = (payload: any, fields: FieldConfig[], state: QSMState) => {
76
- fields.forEach((field) => {
77
- if (field.type === 'single') {
78
- const key = field.fieldKey;
79
- const option = field.options.find((opt) => opt.value === state[key]);
80
- payload[key] = option ?? state[key];
81
- }
82
-
83
- if (field.type === 'double' && field.fields) {
84
- // recursively add each nested field
85
- field.fields.forEach((nestedField) => {
86
- const key = nestedField.fieldKey;
87
- const option = nestedField.options.find((opt) => opt.value === state[key]);
88
- payload[key] = option ?? state[key];
89
- });
90
- }
91
- });
92
- };
93
-
94
- return (
95
- <div className="qsm">
96
- <div className="qsm__content">
97
- <div className="qsm__tabs">
98
- <button type="button" className="qsm__tab">
99
- <span className="qsm__tab__icons">
100
- <Icon name="ui-location" height={16} />
101
- </span>
102
- Multidestination
103
- </button>
104
- <button type="button" className="qsm__tab">
105
- <span className="qsm__tab__icons">
106
- <Icon name="ui-suitcase" height={16} />
107
- </span>
108
- Packages
109
- </button>
110
- <button type="button" className="qsm__tab qsm__tab--active">
111
- <span className="qsm__tab__icons">
112
- <Icon name="ui-backforward" height={14} />
113
- +
114
- <Icon name="ui-bed" height={14} />
115
- </span>
116
- Transport + hotel
117
- </button>
118
- <button type="button" className="qsm__tab">
119
- <span className="qsm__tab__icons">
120
- <Icon name="ui-bed" height={16} />
121
- </span>
122
- Accommodation
123
- </button>
124
- <button type="button" className="qsm__tab">
125
- <span className="qsm__tab__icons">
126
- <Icon name="ui-flight" height={16} />
127
- </span>
128
- Transports
129
- </button>
130
- <button type="button" className="qsm__tab">
131
- <span className="qsm__tab__icons">
132
- <Icon name="ui-ticket" height={16} />
133
- </span>
134
- Ticket Only
135
- </button>
136
- <button type="button" className="qsm__tab">
137
- <span className="qsm__tab__icons">
138
- <Icon name="ui-car" height={16} />
139
- </span>
140
- Rent a car
141
- </button>
142
- <button type="button" className="qsm__tab">
143
- <span className="qsm__tab__icons">
144
- <Icon name="ui-backforward" height={16} />
145
- </span>
146
- Transfers
147
- </button>
148
- <button type="button" className="qsm__tab">
149
- <span className="qsm__tab__icons">
150
- <Icon name="ui-ship" height={16} />
151
- </span>
152
- Cruises
153
- </button>
154
- </div>
155
- <div className="qsm__filter">
156
- <div className="radiobutton-group qsm__filter__inputgroup">
157
- <div className="radiobutton">
158
- <label className="radiobutton__label">
159
- <input
160
- type="radio"
161
- name="mainBookerId"
162
- // onChange={handleMainBookerChange}
163
- // onBlur={formik.handleBlur}
164
- value=""
165
- // checked={formik.values.mainBookerId === travelerValues.id}
166
- checked={true}
167
- readOnly
168
- className="radiobutton__input"
169
- />
170
- <span>One accommodation</span>
171
- </label>
172
- </div>
173
- <div className="radiobutton">
174
- <label className="radiobutton__label">
175
- <input
176
- type="radio"
177
- name="mainBookerId"
178
- // onChange={handleMainBookerChange}
179
- // onBlur={formik.handleBlur}
180
- value=""
181
- // checked={formik.values.mainBookerId === travelerValues.id}
182
- className="radiobutton__input"
183
- disabled={true}
184
- />
185
- <span>Multiple accommodations</span>
186
- </label>
187
- </div>
188
- </div>
189
- <div className="qsm__filter__classgroup">
190
- <TravelClassPicker />
191
- <TravelTypePicker />
192
- <TravelNationalityPicker />
193
- </div>
194
- </div>
195
- <div className="qsm__input-group">
196
- {searchFields.map((field, idx) => {
197
- if (field.type === 'double') {
198
- return <DoubleSearchInputGroup key={idx} fieldKey={field.fieldKey} showReverse={field.showReverse} />;
199
- }
200
- return <SearchInputGroup key={idx} fieldKey={field.fieldKey} />;
201
- })}
202
-
203
- <Dates value={dateRange} onChange={handleDateChange} />
204
-
205
- {askTravelers && <TravelInputGroup />}
206
-
207
- <button type="button" className="cta" onClick={handleSubmit}>
208
- {submitIcon && submitIcon.toString().length > 0 && <span>{submitIcon}</span>}
209
- <span>{submitLabel}</span>
210
- </button>
211
- </div>
212
- </div>
213
- {isMobile && mobileFilterType && <MobileFilterModal />}
214
- </div>
215
- );
216
- };
217
-
218
- export default QSMContainer;
1
+ import React, { useContext, useEffect, useMemo } from 'react';
2
+ import { useDispatch, useSelector } from 'react-redux';
3
+ import { QSMRootState } from '../../store/qsm-store';
4
+ import QSMConfigurationContext from '../../qsm-configuration-context';
5
+ import useMediaQuery from '../../../shared/utils/use-media-query-util';
6
+ import MobileFilterModal from '../mobile-filter-modal';
7
+ import SearchInputGroup from '../search-input-group';
8
+ import DoubleSearchInputGroup from '../double-search-input-group';
9
+ import Dates from '../../../booking-product/components/dates';
10
+ import TravelInputGroup from '../travel-input-group';
11
+ import TravelClassPicker from '../travel-class-picker';
12
+ import TravelTypePicker from '../travel-type-picker';
13
+ import Icon from '../icon';
14
+ import TravelNationalityPicker from '../travel-nationality-picker';
15
+ import { addDays, addMonths } from 'date-fns';
16
+ import { DateRange } from '../../../booking-product/types';
17
+ import { QSMState, setFromDate, setToDate } from '../../store/qsm-slice';
18
+ import { FieldConfig } from '../../types';
19
+ import { getTranslations } from '../../../shared/utils/localization-util';
20
+
21
+ const QSMContainer: React.FC = () => {
22
+ const dispatch = useDispatch();
23
+ const isMobile = useMediaQuery('(max-width: 768px)');
24
+ const qsmState = useSelector((state: QSMRootState) => state.qsm);
25
+ const { mobileFilterType, fromDate, toDate } = qsmState;
26
+ const { searchFields, askTravelers, submitIcon, onSubmit, travelTypes, languageCode } = useContext(QSMConfigurationContext);
27
+ const translations = getTranslations(languageCode ?? 'en-GB');
28
+
29
+ useEffect(() => {
30
+ if (fromDate || toDate) return;
31
+
32
+ const startDate = addMonths(new Date(), 1);
33
+ const endDate = addDays(startDate, 7);
34
+
35
+ dispatch(setFromDate(startDate.toISOString()));
36
+ dispatch(setToDate(endDate.toISOString()));
37
+ }, [fromDate, toDate, dispatch]);
38
+
39
+ const dateRange = useMemo<DateRange | undefined>(() => {
40
+ if (!fromDate || !toDate) return undefined;
41
+
42
+ return {
43
+ fromDate: new Date(fromDate),
44
+ toDate: new Date(toDate)
45
+ };
46
+ }, [fromDate, toDate]);
47
+
48
+ const handleDateChange = (value: DateRange) => {
49
+ dispatch(setFromDate(value.fromDate?.toISOString()));
50
+ dispatch(setToDate(value.toDate?.toISOString()));
51
+ };
52
+
53
+ const handleSubmit = () => {
54
+ if (!onSubmit) return;
55
+
56
+ const { fromDate, toDate, travelers, selectedTravelClass, selectedTravelType, selectedNationality, adults, kids, babies, rooms, selectedFlexRange } =
57
+ qsmState;
58
+
59
+ const selectedTravelTypeValue = travelTypes.find((t) => t.label === selectedTravelType);
60
+
61
+ const payload = {
62
+ fromDate,
63
+ toDate,
64
+ travelClass: selectedTravelClass,
65
+ travelType: selectedTravelTypeValue,
66
+ nationality: selectedNationality,
67
+ rooms
68
+ };
69
+
70
+ addSearchFieldsToPayload(payload, searchFields, qsmState);
71
+ onSubmit(payload);
72
+ };
73
+
74
+ const addSearchFieldsToPayload = (payload: any, fields: FieldConfig[], state: QSMState) => {
75
+ fields.forEach((field) => {
76
+ if (field.type === 'single') {
77
+ const key = field.fieldKey;
78
+ const option = field.options.find((opt) => opt.value === state[key]);
79
+ payload[key] = option ?? state[key];
80
+ }
81
+
82
+ if (field.type === 'double' && field.fields) {
83
+ // recursively add each nested field
84
+ field.fields.forEach((nestedField) => {
85
+ const key = nestedField.fieldKey;
86
+ const option = nestedField.options.find((opt) => opt.value === state[key]);
87
+ payload[key] = option ?? state[key];
88
+ });
89
+ }
90
+ });
91
+ };
92
+
93
+ return (
94
+ <div className="qsm">
95
+ <div className="qsm__content">
96
+ <div className="qsm__tabs">
97
+ <button type="button" className="qsm__tab">
98
+ <span className="qsm__tab__icons">
99
+ <Icon name="ui-location" height={16} />
100
+ </span>
101
+ {translations.QSM.MULTIDESTINATION}
102
+ </button>
103
+ <button type="button" className="qsm__tab">
104
+ <span className="qsm__tab__icons">
105
+ <Icon name="ui-suitcase" height={16} />
106
+ </span>
107
+ {translations.QSM.PACKAGES}
108
+ </button>
109
+ <button type="button" className="qsm__tab qsm__tab--active">
110
+ <span className="qsm__tab__icons">
111
+ <Icon name="ui-backforward" height={14} />
112
+ +
113
+ <Icon name="ui-bed" height={14} />
114
+ </span>
115
+ {translations.QSM.TRANSPORT_HOTEL}
116
+ </button>
117
+ <button type="button" className="qsm__tab">
118
+ <span className="qsm__tab__icons">
119
+ <Icon name="ui-bed" height={16} />
120
+ </span>
121
+ {translations.QSM.ACCOMMODATION}
122
+ </button>
123
+ <button type="button" className="qsm__tab">
124
+ <span className="qsm__tab__icons">
125
+ <Icon name="ui-flight" height={16} />
126
+ </span>
127
+ {translations.QSM.TRANSPORTS}
128
+ </button>
129
+ <button type="button" className="qsm__tab">
130
+ <span className="qsm__tab__icons">
131
+ <Icon name="ui-ticket" height={16} />
132
+ </span>
133
+ {translations.QSM.TICKET_ONLY}
134
+ </button>
135
+ <button type="button" className="qsm__tab">
136
+ <span className="qsm__tab__icons">
137
+ <Icon name="ui-car" height={16} />
138
+ </span>
139
+ {translations.QSM.RENT_A_CAR}
140
+ </button>
141
+ <button type="button" className="qsm__tab">
142
+ <span className="qsm__tab__icons">
143
+ <Icon name="ui-backforward" height={16} />
144
+ </span>
145
+ {translations.QSM.TRANSFERS}
146
+ </button>
147
+ <button type="button" className="qsm__tab">
148
+ <span className="qsm__tab__icons">
149
+ <Icon name="ui-ship" height={16} />
150
+ </span>
151
+ {translations.QSM.CRUISES}
152
+ </button>
153
+ </div>
154
+ <div className="qsm__filter">
155
+ <div className="radiobutton-group qsm__filter__inputgroup">
156
+ <div className="radiobutton">
157
+ <label className="radiobutton__label">
158
+ <input
159
+ type="radio"
160
+ name="mainBookerId"
161
+ // onChange={handleMainBookerChange}
162
+ // onBlur={formik.handleBlur}
163
+ value=""
164
+ // checked={formik.values.mainBookerId === travelerValues.id}
165
+ checked={true}
166
+ readOnly
167
+ className="radiobutton__input"
168
+ />
169
+ <span>{translations.QSM.ONE_ACCOMMODATION}</span>
170
+ </label>
171
+ </div>
172
+ <div className="radiobutton">
173
+ <label className="radiobutton__label">
174
+ <input
175
+ type="radio"
176
+ name="mainBookerId"
177
+ // onChange={handleMainBookerChange}
178
+ // onBlur={formik.handleBlur}
179
+ value=""
180
+ // checked={formik.values.mainBookerId === travelerValues.id}
181
+ className="radiobutton__input"
182
+ disabled={true}
183
+ />
184
+ <span>{translations.QSM.MULTIPLE_ACCOMMODATIONS}</span>
185
+ </label>
186
+ </div>
187
+ </div>
188
+ <div className="qsm__filter__classgroup">
189
+ <TravelClassPicker />
190
+ <TravelTypePicker />
191
+ <TravelNationalityPicker />
192
+ </div>
193
+ </div>
194
+ <div className="qsm__input-group">
195
+ {searchFields.map((field, idx) => {
196
+ if (field.type === 'double') {
197
+ return <DoubleSearchInputGroup key={idx} fieldKey={field.fieldKey} showReverse={field.showReverse} />;
198
+ }
199
+ return <SearchInputGroup key={idx} fieldKey={field.fieldKey} />;
200
+ })}
201
+
202
+ <Dates value={dateRange} onChange={handleDateChange} />
203
+
204
+ {askTravelers && <TravelInputGroup />}
205
+
206
+ <button type="button" className="cta" onClick={handleSubmit}>
207
+ {submitIcon && submitIcon.toString().length > 0 && <span>{submitIcon}</span>}
208
+ <span>{translations.QSM.CONFIRM}</span>
209
+ </button>
210
+ </div>
211
+ </div>
212
+ {isMobile && mobileFilterType && <MobileFilterModal />}
213
+ </div>
214
+ );
215
+ };
216
+
217
+ export default QSMContainer;
@@ -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>