@qite/tide-booking-component 1.4.25 → 1.4.27
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 +129 -74
- package/build/build-cjs/qsm/components/item-picker/index.d.ts +2 -2
- package/build/build-cjs/qsm/components/search-input/index.d.ts +3 -2
- package/build/build-cjs/qsm/components/travel-nationality-picker/index.d.ts +3 -0
- package/build/build-cjs/qsm/store/qsm-slice.d.ts +7 -9
- package/build/build-cjs/qsm/types.d.ts +9 -0
- package/build/build-esm/index.js +128 -74
- package/build/build-esm/qsm/components/item-picker/index.d.ts +2 -2
- package/build/build-esm/qsm/components/search-input/index.d.ts +3 -2
- package/build/build-esm/qsm/components/travel-nationality-picker/index.d.ts +3 -0
- package/build/build-esm/qsm/store/qsm-slice.d.ts +7 -9
- package/build/build-esm/qsm/types.d.ts +9 -0
- package/package.json +1 -1
- package/src/content/features/content-page/content-page-self-contained.tsx +12 -1
- package/src/qsm/components/QSMContainer/qsm-container.tsx +2 -0
- package/src/qsm/components/item-picker/index.tsx +12 -6
- package/src/qsm/components/travel-nationality-picker/index.tsx +24 -0
- package/src/qsm/qsm-configuration-context.ts +2 -0
- package/src/qsm/store/qsm-slice.ts +6 -0
- package/src/qsm/types.ts +8 -0
package/build/build-cjs/index.js
CHANGED
|
@@ -22872,6 +22872,7 @@ var QSMConfigurationContext = React__default['default'].createContext({
|
|
|
22872
22872
|
travelTypeIcon: '',
|
|
22873
22873
|
travelClasses: [],
|
|
22874
22874
|
travelClassIcon: '',
|
|
22875
|
+
nationalities: [],
|
|
22875
22876
|
showReturnDate: false,
|
|
22876
22877
|
datesIcon: '',
|
|
22877
22878
|
onSubmit: function () {},
|
|
@@ -22929,6 +22930,7 @@ var initialState$1 = {
|
|
|
22929
22930
|
selectedTravelType: undefined,
|
|
22930
22931
|
travelClasses: [],
|
|
22931
22932
|
selectedTravelClass: undefined,
|
|
22933
|
+
selectedNationality: undefined,
|
|
22932
22934
|
defaultTravelers: 2,
|
|
22933
22935
|
maxTravelers: 9,
|
|
22934
22936
|
maxChildAge: 12,
|
|
@@ -23014,6 +23016,9 @@ var qsmSlice = toolkit.createSlice({
|
|
|
23014
23016
|
setSelectedTravelClass: function (state, action) {
|
|
23015
23017
|
state.selectedTravelClass = action.payload;
|
|
23016
23018
|
},
|
|
23019
|
+
setSelectedNationality: function (state, action) {
|
|
23020
|
+
state.selectedNationality = action.payload;
|
|
23021
|
+
},
|
|
23017
23022
|
setDefaultTravelers: function (state, action) {
|
|
23018
23023
|
state.defaultTravelers = action.payload;
|
|
23019
23024
|
},
|
|
@@ -23077,7 +23082,8 @@ var setMobileDatePickerMode = _a$1.setMobileDatePickerMode,
|
|
|
23077
23082
|
_a$1.setTravelTypes;
|
|
23078
23083
|
var setSelectedTravelType = _a$1.setSelectedTravelType;
|
|
23079
23084
|
_a$1.setTravelClasses;
|
|
23080
|
-
var setSelectedTravelClass = _a$1.setSelectedTravelClass
|
|
23085
|
+
var setSelectedTravelClass = _a$1.setSelectedTravelClass,
|
|
23086
|
+
setSelectedNationality = _a$1.setSelectedNationality;
|
|
23081
23087
|
_a$1.setDefaultTravelers;
|
|
23082
23088
|
_a$1.setMaxTravelers;
|
|
23083
23089
|
_a$1.setMaxChildAge;
|
|
@@ -23564,11 +23570,11 @@ var SearchInput = function (_a) {
|
|
|
23564
23570
|
_a.label;
|
|
23565
23571
|
var isSecondInput = _a.isSecondInput,
|
|
23566
23572
|
isDoubleInput = _a.isDoubleInput;
|
|
23567
|
-
var highlightMatch = function (
|
|
23573
|
+
var highlightMatch = function (option, highlight) {
|
|
23568
23574
|
if (!highlight) {
|
|
23569
|
-
return
|
|
23575
|
+
return option.value;
|
|
23570
23576
|
}
|
|
23571
|
-
var parts =
|
|
23577
|
+
var parts = option.value.split(new RegExp('('.concat(highlight, ')'), 'gi'));
|
|
23572
23578
|
return React__default['default'].createElement(
|
|
23573
23579
|
'span',
|
|
23574
23580
|
null,
|
|
@@ -23589,14 +23595,18 @@ var SearchInput = function (_a) {
|
|
|
23589
23595
|
.concat(isSecondInput ? ' qsm__double-input-options--second-input' : '')
|
|
23590
23596
|
.concat(isDoubleInput ? ' qsm__double-input-options--splittable' : '')
|
|
23591
23597
|
},
|
|
23592
|
-
searchResults.map(function (
|
|
23598
|
+
searchResults.map(function (option, index) {
|
|
23593
23599
|
return React__default['default'].createElement(
|
|
23594
23600
|
'div',
|
|
23595
23601
|
{
|
|
23596
23602
|
key: index,
|
|
23597
23603
|
className: 'qsm__double-input-option',
|
|
23598
|
-
|
|
23599
|
-
return
|
|
23604
|
+
onMouseDown: function (e) {
|
|
23605
|
+
return e.preventDefault();
|
|
23606
|
+
},
|
|
23607
|
+
onClick: function (e) {
|
|
23608
|
+
e.stopPropagation();
|
|
23609
|
+
onOptionSelect(option);
|
|
23600
23610
|
},
|
|
23601
23611
|
role: 'option',
|
|
23602
23612
|
'aria-selected': false
|
|
@@ -23604,15 +23614,16 @@ var SearchInput = function (_a) {
|
|
|
23604
23614
|
React__default['default'].createElement(
|
|
23605
23615
|
'div',
|
|
23606
23616
|
{ className: 'qsm__double-input-option-content' },
|
|
23607
|
-
React__default['default'].createElement(Icon$1, { name: 'ui-location', height: 16 }),
|
|
23617
|
+
React__default['default'].createElement(Icon$1, { name: option.type == 'hotel' ? 'ui-hotel' : 'ui-location', height: 16 }),
|
|
23608
23618
|
React__default['default'].createElement(
|
|
23609
23619
|
'div',
|
|
23610
23620
|
{ className: 'qsm__double-input-option-content-text' },
|
|
23611
|
-
highlightMatch(
|
|
23612
|
-
React__default['default'].createElement('span', { className: 'qsm__double-input-option-content-country' },
|
|
23621
|
+
highlightMatch(option, highlightTarget),
|
|
23622
|
+
option.country && React__default['default'].createElement('span', { className: 'qsm__double-input-option-content-country' }, option.country)
|
|
23613
23623
|
)
|
|
23614
23624
|
),
|
|
23615
|
-
|
|
23625
|
+
option.iataCode &&
|
|
23626
|
+
React__default['default'].createElement('span', { className: 'qsm__double-input-option-content-airport-label' }, '[', option.iataCode, ']')
|
|
23616
23627
|
);
|
|
23617
23628
|
})
|
|
23618
23629
|
);
|
|
@@ -24609,26 +24620,41 @@ var MobileFilterModal = function () {
|
|
|
24609
24620
|
hasTypedRef.current = false;
|
|
24610
24621
|
dispatch(closeMobileFilter());
|
|
24611
24622
|
};
|
|
24623
|
+
// const handleLocationChange = (val: string) => {
|
|
24624
|
+
// setInputValue(val);
|
|
24625
|
+
// hasTypedRef.current = true;
|
|
24626
|
+
// if (val.trim() !== '' && activeSearchFieldProps) {
|
|
24627
|
+
// const filtered = activeSearchFieldProps.options.filter((loc) => loc.value.toLowerCase().includes(val.toLowerCase())).map((loc) => loc.value);
|
|
24628
|
+
// setSearchResultsLocal(filtered);
|
|
24629
|
+
// } else {
|
|
24630
|
+
// setSearchResultsLocal([]);
|
|
24631
|
+
// }
|
|
24632
|
+
// };
|
|
24612
24633
|
var handleLocationChange = function (val) {
|
|
24613
24634
|
setInputValue(val);
|
|
24614
24635
|
hasTypedRef.current = true;
|
|
24615
24636
|
if (val.trim() !== '' && activeSearchFieldProps) {
|
|
24616
|
-
var filtered = activeSearchFieldProps.options
|
|
24617
|
-
.
|
|
24618
|
-
|
|
24619
|
-
})
|
|
24620
|
-
.map(function (loc) {
|
|
24621
|
-
return loc.value;
|
|
24622
|
-
});
|
|
24637
|
+
var filtered = activeSearchFieldProps.options.filter(function (option) {
|
|
24638
|
+
return option.value.toLowerCase().includes(val.toLowerCase());
|
|
24639
|
+
});
|
|
24623
24640
|
setSearchResultsLocal(filtered);
|
|
24624
24641
|
} else {
|
|
24625
24642
|
setSearchResultsLocal([]);
|
|
24626
24643
|
}
|
|
24627
24644
|
};
|
|
24628
|
-
|
|
24645
|
+
// const handleLocationSelect = (val: string) => {
|
|
24646
|
+
// if (activeSearchFieldProps) {
|
|
24647
|
+
// const { fieldKey } = activeSearchFieldProps;
|
|
24648
|
+
// dispatch(setFieldValue({ fieldKey, value: val }));
|
|
24649
|
+
// dispatch(setSearchResultsAction([]));
|
|
24650
|
+
// dispatch(setActiveSearchField(null));
|
|
24651
|
+
// }
|
|
24652
|
+
// dispatch(closeMobileFilter());
|
|
24653
|
+
// };
|
|
24654
|
+
var handleLocationSelect = function (option) {
|
|
24629
24655
|
if (activeSearchFieldProps) {
|
|
24630
24656
|
var fieldKey = activeSearchFieldProps.fieldKey;
|
|
24631
|
-
dispatch(setFieldValue({ fieldKey: fieldKey, value:
|
|
24657
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: option.value }));
|
|
24632
24658
|
dispatch(setSearchResults([]));
|
|
24633
24659
|
dispatch(setActiveSearchField(null));
|
|
24634
24660
|
}
|
|
@@ -24818,7 +24844,6 @@ var MobileFilterModal = function () {
|
|
|
24818
24844
|
}
|
|
24819
24845
|
};
|
|
24820
24846
|
|
|
24821
|
-
// SearchInputGroup.tsx
|
|
24822
24847
|
var findConfig = function (all, key) {
|
|
24823
24848
|
for (var _i = 0, all_1 = all; _i < all_1.length; _i++) {
|
|
24824
24849
|
var config = all_1[_i];
|
|
@@ -24859,17 +24884,6 @@ var SearchInputGroup = function (_a) {
|
|
|
24859
24884
|
var label = config.label,
|
|
24860
24885
|
placeholder = config.placeholder,
|
|
24861
24886
|
options = config.options;
|
|
24862
|
-
var lowerOptions = React.useMemo(
|
|
24863
|
-
function () {
|
|
24864
|
-
return options.map(function (x) {
|
|
24865
|
-
return {
|
|
24866
|
-
value: x.value,
|
|
24867
|
-
lower: x.value.toLowerCase()
|
|
24868
|
-
};
|
|
24869
|
-
});
|
|
24870
|
-
},
|
|
24871
|
-
[options]
|
|
24872
|
-
);
|
|
24873
24887
|
var selector = React.useMemo(
|
|
24874
24888
|
function () {
|
|
24875
24889
|
return function (state) {
|
|
@@ -24886,30 +24900,44 @@ var SearchInputGroup = function (_a) {
|
|
|
24886
24900
|
searchResults = _g.searchResults,
|
|
24887
24901
|
activeSearchField = _g.activeSearchField;
|
|
24888
24902
|
var match = React.useCallback(
|
|
24889
|
-
function (
|
|
24890
|
-
if (!
|
|
24903
|
+
function (input) {
|
|
24904
|
+
if (!input) {
|
|
24891
24905
|
return [];
|
|
24892
24906
|
}
|
|
24893
|
-
var lowered =
|
|
24894
|
-
return
|
|
24895
|
-
.
|
|
24896
|
-
|
|
24897
|
-
})
|
|
24898
|
-
.map(function (x) {
|
|
24899
|
-
return x.value;
|
|
24900
|
-
});
|
|
24907
|
+
var lowered = input.toLowerCase();
|
|
24908
|
+
return options.filter(function (option) {
|
|
24909
|
+
return option.value.toLowerCase().includes(lowered);
|
|
24910
|
+
});
|
|
24901
24911
|
},
|
|
24902
|
-
[
|
|
24912
|
+
[options]
|
|
24903
24913
|
);
|
|
24904
|
-
var
|
|
24905
|
-
function (
|
|
24906
|
-
dispatch(setFieldValue({ fieldKey: fieldKey, value:
|
|
24914
|
+
var handleInputChange = React.useCallback(
|
|
24915
|
+
function (input) {
|
|
24916
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: input }));
|
|
24907
24917
|
dispatch(setSearchResults([]));
|
|
24908
|
-
if (
|
|
24909
|
-
|
|
24918
|
+
if (small) return;
|
|
24919
|
+
if (input.length === 3) {
|
|
24920
|
+
var exactIataMatch = findExactIataMatch(options, input);
|
|
24921
|
+
if (exactIataMatch) {
|
|
24922
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: exactIataMatch.value }));
|
|
24923
|
+
dispatch(setSearchResults([]));
|
|
24924
|
+
dispatch(setActiveSearchField(null));
|
|
24925
|
+
return;
|
|
24926
|
+
}
|
|
24910
24927
|
}
|
|
24928
|
+
// Normal typeahead behavior
|
|
24929
|
+
dispatch(setActiveSearchField(fieldKey));
|
|
24930
|
+
dispatch(setSearchResults(match(input)));
|
|
24931
|
+
},
|
|
24932
|
+
[dispatch, fieldKey, small, match, options]
|
|
24933
|
+
);
|
|
24934
|
+
var handleOptionSelect = React.useCallback(
|
|
24935
|
+
function (option) {
|
|
24936
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: option.value }));
|
|
24937
|
+
dispatch(setSearchResults([]));
|
|
24938
|
+
dispatch(setActiveSearchField(null));
|
|
24911
24939
|
},
|
|
24912
|
-
[dispatch, fieldKey
|
|
24940
|
+
[dispatch, fieldKey]
|
|
24913
24941
|
);
|
|
24914
24942
|
var click = function () {
|
|
24915
24943
|
dispatch(setActiveSearchField(fieldKey));
|
|
@@ -24929,6 +24957,11 @@ var SearchInputGroup = function (_a) {
|
|
|
24929
24957
|
dispatch(setSearchResults(match(value)));
|
|
24930
24958
|
}
|
|
24931
24959
|
};
|
|
24960
|
+
var findExactIataMatch = function (options, input) {
|
|
24961
|
+
return options.find(function (option) {
|
|
24962
|
+
return option.iataCode && option.iataCode.toLowerCase() === input.toLowerCase();
|
|
24963
|
+
});
|
|
24964
|
+
};
|
|
24932
24965
|
React.useEffect(
|
|
24933
24966
|
function () {
|
|
24934
24967
|
var outside = function (e) {
|
|
@@ -24965,9 +24998,12 @@ var SearchInputGroup = function (_a) {
|
|
|
24965
24998
|
name: fieldKey,
|
|
24966
24999
|
value: value,
|
|
24967
25000
|
readOnly: small,
|
|
24968
|
-
|
|
25001
|
+
onFocus: click,
|
|
25002
|
+
onClick: function (e) {
|
|
25003
|
+
return e.stopPropagation();
|
|
25004
|
+
},
|
|
24969
25005
|
onChange: function (e) {
|
|
24970
|
-
return !small && !readOnlyForced &&
|
|
25006
|
+
return !small && !readOnlyForced && handleInputChange(e.target.value);
|
|
24971
25007
|
},
|
|
24972
25008
|
className: 'qsm__input'.concat(isSecondInput ? ' qsm__input--splittable' : ' u-ps-2'),
|
|
24973
25009
|
placeholder: placeholder
|
|
@@ -24975,12 +25011,9 @@ var SearchInputGroup = function (_a) {
|
|
|
24975
25011
|
!small &&
|
|
24976
25012
|
activeSearchField === fieldKey &&
|
|
24977
25013
|
React__default['default'].createElement(SearchInput, {
|
|
24978
|
-
onChange:
|
|
25014
|
+
onChange: handleInputChange,
|
|
24979
25015
|
searchResults: searchResults,
|
|
24980
|
-
onOptionSelect:
|
|
24981
|
-
change(val);
|
|
24982
|
-
dispatch(setActiveSearchField(null));
|
|
24983
|
-
},
|
|
25016
|
+
onOptionSelect: handleOptionSelect,
|
|
24984
25017
|
highlightTarget: highlightTarget,
|
|
24985
25018
|
label: label,
|
|
24986
25019
|
isSecondInput: isSecondInput,
|
|
@@ -25148,7 +25181,7 @@ var DoubleSearchInputGroup = function (_a) {
|
|
|
25148
25181
|
{ className: 'qsm__reverse-wrapper' },
|
|
25149
25182
|
React__default['default'].createElement(
|
|
25150
25183
|
'button',
|
|
25151
|
-
{ type: 'button', onClick: reverse, className: 'qsm__input-line--reverse-button' },
|
|
25184
|
+
{ type: 'button', onClick: reverse, className: 'qsm__input-line--reverse-button', tabIndex: -1 },
|
|
25152
25185
|
React__default['default'].createElement(
|
|
25153
25186
|
'svg',
|
|
25154
25187
|
{ id: 'qsm-planes-icon', viewBox: '0 0 18 18', width: 18, height: 18 },
|
|
@@ -25394,17 +25427,22 @@ var TravelInputGroup = function () {
|
|
|
25394
25427
|
});
|
|
25395
25428
|
}
|
|
25396
25429
|
};
|
|
25397
|
-
React.useEffect(
|
|
25398
|
-
|
|
25399
|
-
|
|
25400
|
-
|
|
25430
|
+
React.useEffect(
|
|
25431
|
+
function () {
|
|
25432
|
+
var handleClickOutside = function (event) {
|
|
25433
|
+
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
|
|
25434
|
+
setIsOpen(false);
|
|
25435
|
+
}
|
|
25436
|
+
};
|
|
25437
|
+
if (isOpen) {
|
|
25438
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
25401
25439
|
}
|
|
25402
|
-
|
|
25403
|
-
|
|
25404
|
-
|
|
25405
|
-
|
|
25406
|
-
|
|
25407
|
-
|
|
25440
|
+
return function () {
|
|
25441
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
25442
|
+
};
|
|
25443
|
+
},
|
|
25444
|
+
[isOpen]
|
|
25445
|
+
);
|
|
25408
25446
|
React.useEffect(
|
|
25409
25447
|
function () {
|
|
25410
25448
|
if (initDone.current) {
|
|
@@ -25432,8 +25470,8 @@ var TravelInputGroup = function () {
|
|
|
25432
25470
|
[defaultTravelers, maxTravelers]
|
|
25433
25471
|
);
|
|
25434
25472
|
return React__default['default'].createElement(
|
|
25435
|
-
'
|
|
25436
|
-
{ className: 'qsm__single-input-wrapper qsm__single-input-wrapper--travel' },
|
|
25473
|
+
'div',
|
|
25474
|
+
{ ref: wrapperRef, className: 'qsm__single-input-wrapper qsm__single-input-wrapper--travel' },
|
|
25437
25475
|
React__default['default'].createElement(Icon$1, { name: 'ui-user', height: 16 }),
|
|
25438
25476
|
React__default['default'].createElement('span', { className: 'qsm__label' }, 'Met wie ga je?'),
|
|
25439
25477
|
React__default['default'].createElement('input', {
|
|
@@ -25467,8 +25505,8 @@ var ItemPicker$1 = function (_a) {
|
|
|
25467
25505
|
var dropdownMenuRef = React.useRef(null);
|
|
25468
25506
|
var toggleButtonRef = React.useRef(null);
|
|
25469
25507
|
var handlePick = function (picked) {
|
|
25470
|
-
dispatch(onPick(picked));
|
|
25471
25508
|
setIsDropdownOpen(false);
|
|
25509
|
+
dispatch(onPick(picked));
|
|
25472
25510
|
};
|
|
25473
25511
|
React.useEffect(function () {
|
|
25474
25512
|
var handleClickOutside = function (event) {
|
|
@@ -25495,7 +25533,7 @@ var ItemPicker$1 = function (_a) {
|
|
|
25495
25533
|
[isDropdownOpen]
|
|
25496
25534
|
);
|
|
25497
25535
|
return React__default['default'].createElement(
|
|
25498
|
-
'
|
|
25536
|
+
'div',
|
|
25499
25537
|
{ className: 'dropdown__input ' + classModifier },
|
|
25500
25538
|
React__default['default'].createElement('span', { className: 'dropdown__label' }, label),
|
|
25501
25539
|
React__default['default'].createElement(
|
|
@@ -25526,8 +25564,9 @@ var ItemPicker$1 = function (_a) {
|
|
|
25526
25564
|
'li',
|
|
25527
25565
|
{
|
|
25528
25566
|
key: label,
|
|
25529
|
-
onClick: function () {
|
|
25530
|
-
|
|
25567
|
+
onClick: function (e) {
|
|
25568
|
+
handlePick(label);
|
|
25569
|
+
e.stopPropagation();
|
|
25531
25570
|
},
|
|
25532
25571
|
className: 'dropdown-menu__item'.concat(selection === label ? ' dropdown-menu__item--selected' : '')
|
|
25533
25572
|
},
|
|
@@ -25570,6 +25609,21 @@ var TravelTypePicker = function () {
|
|
|
25570
25609
|
});
|
|
25571
25610
|
};
|
|
25572
25611
|
|
|
25612
|
+
var TravelNationalityPicker = function () {
|
|
25613
|
+
var nationalities = React.useContext(QSMConfigurationContext).nationalities;
|
|
25614
|
+
var selectedNationality = reactRedux.useSelector(function (state) {
|
|
25615
|
+
return state.qsm;
|
|
25616
|
+
}).selectedNationality;
|
|
25617
|
+
return React__default['default'].createElement(ItemPicker$1, {
|
|
25618
|
+
items: nationalities,
|
|
25619
|
+
selection: selectedNationality,
|
|
25620
|
+
label: 'Nationaliteit',
|
|
25621
|
+
placeholder: 'Selecteer nationaliteit',
|
|
25622
|
+
classModifier: 'travel-class-picker__items',
|
|
25623
|
+
onPick: setSelectedNationality
|
|
25624
|
+
});
|
|
25625
|
+
};
|
|
25626
|
+
|
|
25573
25627
|
var QSMContainer = function () {
|
|
25574
25628
|
var isMobile = useMediaQuery('(max-width: 768px)');
|
|
25575
25629
|
var mobileFilterType = reactRedux.useSelector(function (state) {
|
|
@@ -25731,7 +25785,8 @@ var QSMContainer = function () {
|
|
|
25731
25785
|
'div',
|
|
25732
25786
|
{ className: 'qsm__filter__classgroup' },
|
|
25733
25787
|
React__default['default'].createElement(TravelClassPicker, null),
|
|
25734
|
-
React__default['default'].createElement(TravelTypePicker, null)
|
|
25788
|
+
React__default['default'].createElement(TravelTypePicker, null),
|
|
25789
|
+
React__default['default'].createElement(TravelNationalityPicker, null)
|
|
25735
25790
|
)
|
|
25736
25791
|
),
|
|
25737
25792
|
React__default['default'].createElement(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { TravelClass, TravelType } from '../../types';
|
|
2
|
+
import { Nationality, TravelClass, TravelType } from '../../types';
|
|
3
3
|
interface ItemPickerProps {
|
|
4
|
-
items: TravelType[] | TravelClass[];
|
|
4
|
+
items: TravelType[] | TravelClass[] | Nationality[];
|
|
5
5
|
selection: string | undefined;
|
|
6
6
|
label: string;
|
|
7
7
|
placeholder: string;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { TypeaheadOption } from '../../types';
|
|
2
3
|
interface SearchInputProps {
|
|
3
4
|
onChange: (input: string) => void;
|
|
4
|
-
searchResults:
|
|
5
|
-
onOptionSelect: (val:
|
|
5
|
+
searchResults: TypeaheadOption[];
|
|
6
|
+
onOptionSelect: (val: TypeaheadOption) => void;
|
|
6
7
|
highlightTarget: string;
|
|
7
8
|
label: string;
|
|
8
9
|
isSecondInput?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MobileFilterType, Room, TravelerType, TravelType, TravelClass } from '../types';
|
|
1
|
+
import { MobileFilterType, Room, TravelerType, TravelType, TravelClass, TypeaheadOption } from '../types';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
export interface QSMState {
|
|
4
4
|
selectedOrigin?: string;
|
|
@@ -9,16 +9,14 @@ export interface QSMState {
|
|
|
9
9
|
travelers: any[];
|
|
10
10
|
travelClass?: string;
|
|
11
11
|
mobileFilterType: MobileFilterType;
|
|
12
|
-
searchResults:
|
|
12
|
+
searchResults: TypeaheadOption[];
|
|
13
13
|
activeSearchField: string | null;
|
|
14
14
|
activeSearchFieldProps: {
|
|
15
15
|
fieldKey: string;
|
|
16
16
|
label: string;
|
|
17
17
|
placeholder: string;
|
|
18
18
|
value: string;
|
|
19
|
-
options:
|
|
20
|
-
value: string;
|
|
21
|
-
}[];
|
|
19
|
+
options: TypeaheadOption[];
|
|
22
20
|
} | null;
|
|
23
21
|
language: 'nl' | 'fr' | 'en';
|
|
24
22
|
mobileDatePickerMode: 'range' | 'single';
|
|
@@ -38,6 +36,7 @@ export interface QSMState {
|
|
|
38
36
|
selectedTravelType?: string;
|
|
39
37
|
travelClasses: TravelClass[];
|
|
40
38
|
selectedTravelClass?: string;
|
|
39
|
+
selectedNationality?: string;
|
|
41
40
|
defaultTravelers: number;
|
|
42
41
|
maxTravelers: number;
|
|
43
42
|
maxChildAge: number;
|
|
@@ -63,13 +62,11 @@ export declare const setOrigin: import('@reduxjs/toolkit').ActionCreatorWithPayl
|
|
|
63
62
|
label: string;
|
|
64
63
|
placeholder: string;
|
|
65
64
|
value: string;
|
|
66
|
-
options:
|
|
67
|
-
value: string;
|
|
68
|
-
}[];
|
|
65
|
+
options: TypeaheadOption[];
|
|
69
66
|
},
|
|
70
67
|
'qsm/setActiveSearchFieldProps'
|
|
71
68
|
>,
|
|
72
|
-
setSearchResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<
|
|
69
|
+
setSearchResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<TypeaheadOption[], 'qsm/setSearchResults'>,
|
|
73
70
|
setLanguage: import('@reduxjs/toolkit').ActionCreatorWithPayload<'nl' | 'fr' | 'en', 'qsm/setLanguage'>,
|
|
74
71
|
setMobileDatePickerMode: import('@reduxjs/toolkit').ActionCreatorWithPayload<'range' | 'single', 'qsm/setMobileDatePickerMode'>,
|
|
75
72
|
setMinDate: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<string | undefined, 'qsm/setMinDate'>,
|
|
@@ -95,6 +92,7 @@ export declare const setOrigin: import('@reduxjs/toolkit').ActionCreatorWithPayl
|
|
|
95
92
|
setSelectedTravelType: import('@reduxjs/toolkit').ActionCreatorWithPayload<any, 'qsm/setSelectedTravelType'>,
|
|
96
93
|
setTravelClasses: import('@reduxjs/toolkit').ActionCreatorWithPayload<TravelType[], 'qsm/setTravelClasses'>,
|
|
97
94
|
setSelectedTravelClass: import('@reduxjs/toolkit').ActionCreatorWithPayload<any, 'qsm/setSelectedTravelClass'>,
|
|
95
|
+
setSelectedNationality: import('@reduxjs/toolkit').ActionCreatorWithPayload<any, 'qsm/setSelectedNationality'>,
|
|
98
96
|
setDefaultTravelers: import('@reduxjs/toolkit').ActionCreatorWithPayload<number, 'qsm/setDefaultTravelers'>,
|
|
99
97
|
setMaxTravelers: import('@reduxjs/toolkit').ActionCreatorWithPayload<number, 'qsm/setMaxTravelers'>,
|
|
100
98
|
setMaxChildAge: import('@reduxjs/toolkit').ActionCreatorWithPayload<number, 'qsm/setMaxChildAge'>,
|
|
@@ -37,6 +37,7 @@ export interface QSMConfiguration {
|
|
|
37
37
|
onSubmit: (data: any) => void;
|
|
38
38
|
submitLabel: string;
|
|
39
39
|
submitIcon: ReactNode;
|
|
40
|
+
nationalities: Nationality[];
|
|
40
41
|
}
|
|
41
42
|
export interface BaseFieldConfig {
|
|
42
43
|
fieldKey: string;
|
|
@@ -47,6 +48,8 @@ export interface BaseFieldConfig {
|
|
|
47
48
|
export interface TypeaheadOption {
|
|
48
49
|
key: string;
|
|
49
50
|
value: string;
|
|
51
|
+
iataCode?: string;
|
|
52
|
+
country?: string;
|
|
50
53
|
type: OptionType;
|
|
51
54
|
}
|
|
52
55
|
export type OptionType = 'country' | 'region' | 'oord' | 'location' | 'airport' | 'hotel' | 'other';
|
|
@@ -89,6 +92,7 @@ export interface Room {
|
|
|
89
92
|
babies: number;
|
|
90
93
|
}
|
|
91
94
|
export interface TravelType {
|
|
95
|
+
id: number;
|
|
92
96
|
label: string;
|
|
93
97
|
icon?: ReactNode;
|
|
94
98
|
}
|
|
@@ -96,3 +100,8 @@ export interface TravelClass {
|
|
|
96
100
|
label: string;
|
|
97
101
|
icon?: ReactNode;
|
|
98
102
|
}
|
|
103
|
+
export interface Nationality {
|
|
104
|
+
id: number;
|
|
105
|
+
label: string;
|
|
106
|
+
icon?: ReactNode;
|
|
107
|
+
}
|
package/build/build-esm/index.js
CHANGED
|
@@ -22732,6 +22732,7 @@ var QSMConfigurationContext = React.createContext({
|
|
|
22732
22732
|
travelTypeIcon: '',
|
|
22733
22733
|
travelClasses: [],
|
|
22734
22734
|
travelClassIcon: '',
|
|
22735
|
+
nationalities: [],
|
|
22735
22736
|
showReturnDate: false,
|
|
22736
22737
|
datesIcon: '',
|
|
22737
22738
|
onSubmit: function () {},
|
|
@@ -22789,6 +22790,7 @@ var initialState$1 = {
|
|
|
22789
22790
|
selectedTravelType: undefined,
|
|
22790
22791
|
travelClasses: [],
|
|
22791
22792
|
selectedTravelClass: undefined,
|
|
22793
|
+
selectedNationality: undefined,
|
|
22792
22794
|
defaultTravelers: 2,
|
|
22793
22795
|
maxTravelers: 9,
|
|
22794
22796
|
maxChildAge: 12,
|
|
@@ -22874,6 +22876,9 @@ var qsmSlice = createSlice({
|
|
|
22874
22876
|
setSelectedTravelClass: function (state, action) {
|
|
22875
22877
|
state.selectedTravelClass = action.payload;
|
|
22876
22878
|
},
|
|
22879
|
+
setSelectedNationality: function (state, action) {
|
|
22880
|
+
state.selectedNationality = action.payload;
|
|
22881
|
+
},
|
|
22877
22882
|
setDefaultTravelers: function (state, action) {
|
|
22878
22883
|
state.defaultTravelers = action.payload;
|
|
22879
22884
|
},
|
|
@@ -22937,7 +22942,8 @@ var setMobileDatePickerMode = _a$1.setMobileDatePickerMode,
|
|
|
22937
22942
|
_a$1.setTravelTypes;
|
|
22938
22943
|
var setSelectedTravelType = _a$1.setSelectedTravelType;
|
|
22939
22944
|
_a$1.setTravelClasses;
|
|
22940
|
-
var setSelectedTravelClass = _a$1.setSelectedTravelClass
|
|
22945
|
+
var setSelectedTravelClass = _a$1.setSelectedTravelClass,
|
|
22946
|
+
setSelectedNationality = _a$1.setSelectedNationality;
|
|
22941
22947
|
_a$1.setDefaultTravelers;
|
|
22942
22948
|
_a$1.setMaxTravelers;
|
|
22943
22949
|
_a$1.setMaxChildAge;
|
|
@@ -23422,11 +23428,11 @@ var SearchInput = function (_a) {
|
|
|
23422
23428
|
_a.label;
|
|
23423
23429
|
var isSecondInput = _a.isSecondInput,
|
|
23424
23430
|
isDoubleInput = _a.isDoubleInput;
|
|
23425
|
-
var highlightMatch = function (
|
|
23431
|
+
var highlightMatch = function (option, highlight) {
|
|
23426
23432
|
if (!highlight) {
|
|
23427
|
-
return
|
|
23433
|
+
return option.value;
|
|
23428
23434
|
}
|
|
23429
|
-
var parts =
|
|
23435
|
+
var parts = option.value.split(new RegExp('('.concat(highlight, ')'), 'gi'));
|
|
23430
23436
|
return React.createElement(
|
|
23431
23437
|
'span',
|
|
23432
23438
|
null,
|
|
@@ -23447,14 +23453,18 @@ var SearchInput = function (_a) {
|
|
|
23447
23453
|
.concat(isSecondInput ? ' qsm__double-input-options--second-input' : '')
|
|
23448
23454
|
.concat(isDoubleInput ? ' qsm__double-input-options--splittable' : '')
|
|
23449
23455
|
},
|
|
23450
|
-
searchResults.map(function (
|
|
23456
|
+
searchResults.map(function (option, index) {
|
|
23451
23457
|
return React.createElement(
|
|
23452
23458
|
'div',
|
|
23453
23459
|
{
|
|
23454
23460
|
key: index,
|
|
23455
23461
|
className: 'qsm__double-input-option',
|
|
23456
|
-
|
|
23457
|
-
return
|
|
23462
|
+
onMouseDown: function (e) {
|
|
23463
|
+
return e.preventDefault();
|
|
23464
|
+
},
|
|
23465
|
+
onClick: function (e) {
|
|
23466
|
+
e.stopPropagation();
|
|
23467
|
+
onOptionSelect(option);
|
|
23458
23468
|
},
|
|
23459
23469
|
role: 'option',
|
|
23460
23470
|
'aria-selected': false
|
|
@@ -23462,15 +23472,15 @@ var SearchInput = function (_a) {
|
|
|
23462
23472
|
React.createElement(
|
|
23463
23473
|
'div',
|
|
23464
23474
|
{ className: 'qsm__double-input-option-content' },
|
|
23465
|
-
React.createElement(Icon$1, { name: 'ui-location', height: 16 }),
|
|
23475
|
+
React.createElement(Icon$1, { name: option.type == 'hotel' ? 'ui-hotel' : 'ui-location', height: 16 }),
|
|
23466
23476
|
React.createElement(
|
|
23467
23477
|
'div',
|
|
23468
23478
|
{ className: 'qsm__double-input-option-content-text' },
|
|
23469
|
-
highlightMatch(
|
|
23470
|
-
React.createElement('span', { className: 'qsm__double-input-option-content-country' },
|
|
23479
|
+
highlightMatch(option, highlightTarget),
|
|
23480
|
+
option.country && React.createElement('span', { className: 'qsm__double-input-option-content-country' }, option.country)
|
|
23471
23481
|
)
|
|
23472
23482
|
),
|
|
23473
|
-
React.createElement('span', { className: 'qsm__double-input-option-content-airport-label' }, '[
|
|
23483
|
+
option.iataCode && React.createElement('span', { className: 'qsm__double-input-option-content-airport-label' }, '[', option.iataCode, ']')
|
|
23474
23484
|
);
|
|
23475
23485
|
})
|
|
23476
23486
|
);
|
|
@@ -24452,26 +24462,41 @@ var MobileFilterModal = function () {
|
|
|
24452
24462
|
hasTypedRef.current = false;
|
|
24453
24463
|
dispatch(closeMobileFilter());
|
|
24454
24464
|
};
|
|
24465
|
+
// const handleLocationChange = (val: string) => {
|
|
24466
|
+
// setInputValue(val);
|
|
24467
|
+
// hasTypedRef.current = true;
|
|
24468
|
+
// if (val.trim() !== '' && activeSearchFieldProps) {
|
|
24469
|
+
// const filtered = activeSearchFieldProps.options.filter((loc) => loc.value.toLowerCase().includes(val.toLowerCase())).map((loc) => loc.value);
|
|
24470
|
+
// setSearchResultsLocal(filtered);
|
|
24471
|
+
// } else {
|
|
24472
|
+
// setSearchResultsLocal([]);
|
|
24473
|
+
// }
|
|
24474
|
+
// };
|
|
24455
24475
|
var handleLocationChange = function (val) {
|
|
24456
24476
|
setInputValue(val);
|
|
24457
24477
|
hasTypedRef.current = true;
|
|
24458
24478
|
if (val.trim() !== '' && activeSearchFieldProps) {
|
|
24459
|
-
var filtered = activeSearchFieldProps.options
|
|
24460
|
-
.
|
|
24461
|
-
|
|
24462
|
-
})
|
|
24463
|
-
.map(function (loc) {
|
|
24464
|
-
return loc.value;
|
|
24465
|
-
});
|
|
24479
|
+
var filtered = activeSearchFieldProps.options.filter(function (option) {
|
|
24480
|
+
return option.value.toLowerCase().includes(val.toLowerCase());
|
|
24481
|
+
});
|
|
24466
24482
|
setSearchResultsLocal(filtered);
|
|
24467
24483
|
} else {
|
|
24468
24484
|
setSearchResultsLocal([]);
|
|
24469
24485
|
}
|
|
24470
24486
|
};
|
|
24471
|
-
|
|
24487
|
+
// const handleLocationSelect = (val: string) => {
|
|
24488
|
+
// if (activeSearchFieldProps) {
|
|
24489
|
+
// const { fieldKey } = activeSearchFieldProps;
|
|
24490
|
+
// dispatch(setFieldValue({ fieldKey, value: val }));
|
|
24491
|
+
// dispatch(setSearchResultsAction([]));
|
|
24492
|
+
// dispatch(setActiveSearchField(null));
|
|
24493
|
+
// }
|
|
24494
|
+
// dispatch(closeMobileFilter());
|
|
24495
|
+
// };
|
|
24496
|
+
var handleLocationSelect = function (option) {
|
|
24472
24497
|
if (activeSearchFieldProps) {
|
|
24473
24498
|
var fieldKey = activeSearchFieldProps.fieldKey;
|
|
24474
|
-
dispatch(setFieldValue({ fieldKey: fieldKey, value:
|
|
24499
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: option.value }));
|
|
24475
24500
|
dispatch(setSearchResults([]));
|
|
24476
24501
|
dispatch(setActiveSearchField(null));
|
|
24477
24502
|
}
|
|
@@ -24657,7 +24682,6 @@ var MobileFilterModal = function () {
|
|
|
24657
24682
|
}
|
|
24658
24683
|
};
|
|
24659
24684
|
|
|
24660
|
-
// SearchInputGroup.tsx
|
|
24661
24685
|
var findConfig = function (all, key) {
|
|
24662
24686
|
for (var _i = 0, all_1 = all; _i < all_1.length; _i++) {
|
|
24663
24687
|
var config = all_1[_i];
|
|
@@ -24698,17 +24722,6 @@ var SearchInputGroup = function (_a) {
|
|
|
24698
24722
|
var label = config.label,
|
|
24699
24723
|
placeholder = config.placeholder,
|
|
24700
24724
|
options = config.options;
|
|
24701
|
-
var lowerOptions = useMemo(
|
|
24702
|
-
function () {
|
|
24703
|
-
return options.map(function (x) {
|
|
24704
|
-
return {
|
|
24705
|
-
value: x.value,
|
|
24706
|
-
lower: x.value.toLowerCase()
|
|
24707
|
-
};
|
|
24708
|
-
});
|
|
24709
|
-
},
|
|
24710
|
-
[options]
|
|
24711
|
-
);
|
|
24712
24725
|
var selector = useMemo(
|
|
24713
24726
|
function () {
|
|
24714
24727
|
return function (state) {
|
|
@@ -24725,30 +24738,44 @@ var SearchInputGroup = function (_a) {
|
|
|
24725
24738
|
searchResults = _g.searchResults,
|
|
24726
24739
|
activeSearchField = _g.activeSearchField;
|
|
24727
24740
|
var match = useCallback(
|
|
24728
|
-
function (
|
|
24729
|
-
if (!
|
|
24741
|
+
function (input) {
|
|
24742
|
+
if (!input) {
|
|
24730
24743
|
return [];
|
|
24731
24744
|
}
|
|
24732
|
-
var lowered =
|
|
24733
|
-
return
|
|
24734
|
-
.
|
|
24735
|
-
|
|
24736
|
-
})
|
|
24737
|
-
.map(function (x) {
|
|
24738
|
-
return x.value;
|
|
24739
|
-
});
|
|
24745
|
+
var lowered = input.toLowerCase();
|
|
24746
|
+
return options.filter(function (option) {
|
|
24747
|
+
return option.value.toLowerCase().includes(lowered);
|
|
24748
|
+
});
|
|
24740
24749
|
},
|
|
24741
|
-
[
|
|
24750
|
+
[options]
|
|
24742
24751
|
);
|
|
24743
|
-
var
|
|
24744
|
-
function (
|
|
24745
|
-
dispatch(setFieldValue({ fieldKey: fieldKey, value:
|
|
24752
|
+
var handleInputChange = useCallback(
|
|
24753
|
+
function (input) {
|
|
24754
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: input }));
|
|
24746
24755
|
dispatch(setSearchResults([]));
|
|
24747
|
-
if (
|
|
24748
|
-
|
|
24756
|
+
if (small) return;
|
|
24757
|
+
if (input.length === 3) {
|
|
24758
|
+
var exactIataMatch = findExactIataMatch(options, input);
|
|
24759
|
+
if (exactIataMatch) {
|
|
24760
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: exactIataMatch.value }));
|
|
24761
|
+
dispatch(setSearchResults([]));
|
|
24762
|
+
dispatch(setActiveSearchField(null));
|
|
24763
|
+
return;
|
|
24764
|
+
}
|
|
24749
24765
|
}
|
|
24766
|
+
// Normal typeahead behavior
|
|
24767
|
+
dispatch(setActiveSearchField(fieldKey));
|
|
24768
|
+
dispatch(setSearchResults(match(input)));
|
|
24769
|
+
},
|
|
24770
|
+
[dispatch, fieldKey, small, match, options]
|
|
24771
|
+
);
|
|
24772
|
+
var handleOptionSelect = useCallback(
|
|
24773
|
+
function (option) {
|
|
24774
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: option.value }));
|
|
24775
|
+
dispatch(setSearchResults([]));
|
|
24776
|
+
dispatch(setActiveSearchField(null));
|
|
24750
24777
|
},
|
|
24751
|
-
[dispatch, fieldKey
|
|
24778
|
+
[dispatch, fieldKey]
|
|
24752
24779
|
);
|
|
24753
24780
|
var click = function () {
|
|
24754
24781
|
dispatch(setActiveSearchField(fieldKey));
|
|
@@ -24768,6 +24795,11 @@ var SearchInputGroup = function (_a) {
|
|
|
24768
24795
|
dispatch(setSearchResults(match(value)));
|
|
24769
24796
|
}
|
|
24770
24797
|
};
|
|
24798
|
+
var findExactIataMatch = function (options, input) {
|
|
24799
|
+
return options.find(function (option) {
|
|
24800
|
+
return option.iataCode && option.iataCode.toLowerCase() === input.toLowerCase();
|
|
24801
|
+
});
|
|
24802
|
+
};
|
|
24771
24803
|
useEffect(
|
|
24772
24804
|
function () {
|
|
24773
24805
|
var outside = function (e) {
|
|
@@ -24800,9 +24832,12 @@ var SearchInputGroup = function (_a) {
|
|
|
24800
24832
|
name: fieldKey,
|
|
24801
24833
|
value: value,
|
|
24802
24834
|
readOnly: small,
|
|
24803
|
-
|
|
24835
|
+
onFocus: click,
|
|
24836
|
+
onClick: function (e) {
|
|
24837
|
+
return e.stopPropagation();
|
|
24838
|
+
},
|
|
24804
24839
|
onChange: function (e) {
|
|
24805
|
-
return !small && !readOnlyForced &&
|
|
24840
|
+
return !small && !readOnlyForced && handleInputChange(e.target.value);
|
|
24806
24841
|
},
|
|
24807
24842
|
className: 'qsm__input'.concat(isSecondInput ? ' qsm__input--splittable' : ' u-ps-2'),
|
|
24808
24843
|
placeholder: placeholder
|
|
@@ -24810,12 +24845,9 @@ var SearchInputGroup = function (_a) {
|
|
|
24810
24845
|
!small &&
|
|
24811
24846
|
activeSearchField === fieldKey &&
|
|
24812
24847
|
React.createElement(SearchInput, {
|
|
24813
|
-
onChange:
|
|
24848
|
+
onChange: handleInputChange,
|
|
24814
24849
|
searchResults: searchResults,
|
|
24815
|
-
onOptionSelect:
|
|
24816
|
-
change(val);
|
|
24817
|
-
dispatch(setActiveSearchField(null));
|
|
24818
|
-
},
|
|
24850
|
+
onOptionSelect: handleOptionSelect,
|
|
24819
24851
|
highlightTarget: highlightTarget,
|
|
24820
24852
|
label: label,
|
|
24821
24853
|
isSecondInput: isSecondInput,
|
|
@@ -24978,7 +25010,7 @@ var DoubleSearchInputGroup = function (_a) {
|
|
|
24978
25010
|
{ className: 'qsm__reverse-wrapper' },
|
|
24979
25011
|
React.createElement(
|
|
24980
25012
|
'button',
|
|
24981
|
-
{ type: 'button', onClick: reverse, className: 'qsm__input-line--reverse-button' },
|
|
25013
|
+
{ type: 'button', onClick: reverse, className: 'qsm__input-line--reverse-button', tabIndex: -1 },
|
|
24982
25014
|
React.createElement(
|
|
24983
25015
|
'svg',
|
|
24984
25016
|
{ id: 'qsm-planes-icon', viewBox: '0 0 18 18', width: 18, height: 18 },
|
|
@@ -25224,17 +25256,22 @@ var TravelInputGroup = function () {
|
|
|
25224
25256
|
});
|
|
25225
25257
|
}
|
|
25226
25258
|
};
|
|
25227
|
-
useEffect(
|
|
25228
|
-
|
|
25229
|
-
|
|
25230
|
-
|
|
25259
|
+
useEffect(
|
|
25260
|
+
function () {
|
|
25261
|
+
var handleClickOutside = function (event) {
|
|
25262
|
+
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
|
|
25263
|
+
setIsOpen(false);
|
|
25264
|
+
}
|
|
25265
|
+
};
|
|
25266
|
+
if (isOpen) {
|
|
25267
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
25231
25268
|
}
|
|
25232
|
-
|
|
25233
|
-
|
|
25234
|
-
|
|
25235
|
-
|
|
25236
|
-
|
|
25237
|
-
|
|
25269
|
+
return function () {
|
|
25270
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
25271
|
+
};
|
|
25272
|
+
},
|
|
25273
|
+
[isOpen]
|
|
25274
|
+
);
|
|
25238
25275
|
useEffect(
|
|
25239
25276
|
function () {
|
|
25240
25277
|
if (initDone.current) {
|
|
@@ -25262,8 +25299,8 @@ var TravelInputGroup = function () {
|
|
|
25262
25299
|
[defaultTravelers, maxTravelers]
|
|
25263
25300
|
);
|
|
25264
25301
|
return React.createElement(
|
|
25265
|
-
'
|
|
25266
|
-
{ className: 'qsm__single-input-wrapper qsm__single-input-wrapper--travel' },
|
|
25302
|
+
'div',
|
|
25303
|
+
{ ref: wrapperRef, className: 'qsm__single-input-wrapper qsm__single-input-wrapper--travel' },
|
|
25267
25304
|
React.createElement(Icon$1, { name: 'ui-user', height: 16 }),
|
|
25268
25305
|
React.createElement('span', { className: 'qsm__label' }, 'Met wie ga je?'),
|
|
25269
25306
|
React.createElement('input', {
|
|
@@ -25297,8 +25334,8 @@ var ItemPicker$1 = function (_a) {
|
|
|
25297
25334
|
var dropdownMenuRef = useRef(null);
|
|
25298
25335
|
var toggleButtonRef = useRef(null);
|
|
25299
25336
|
var handlePick = function (picked) {
|
|
25300
|
-
dispatch(onPick(picked));
|
|
25301
25337
|
setIsDropdownOpen(false);
|
|
25338
|
+
dispatch(onPick(picked));
|
|
25302
25339
|
};
|
|
25303
25340
|
useEffect(function () {
|
|
25304
25341
|
var handleClickOutside = function (event) {
|
|
@@ -25325,7 +25362,7 @@ var ItemPicker$1 = function (_a) {
|
|
|
25325
25362
|
[isDropdownOpen]
|
|
25326
25363
|
);
|
|
25327
25364
|
return React.createElement(
|
|
25328
|
-
'
|
|
25365
|
+
'div',
|
|
25329
25366
|
{ className: 'dropdown__input ' + classModifier },
|
|
25330
25367
|
React.createElement('span', { className: 'dropdown__label' }, label),
|
|
25331
25368
|
React.createElement(
|
|
@@ -25356,8 +25393,9 @@ var ItemPicker$1 = function (_a) {
|
|
|
25356
25393
|
'li',
|
|
25357
25394
|
{
|
|
25358
25395
|
key: label,
|
|
25359
|
-
onClick: function () {
|
|
25360
|
-
|
|
25396
|
+
onClick: function (e) {
|
|
25397
|
+
handlePick(label);
|
|
25398
|
+
e.stopPropagation();
|
|
25361
25399
|
},
|
|
25362
25400
|
className: 'dropdown-menu__item'.concat(selection === label ? ' dropdown-menu__item--selected' : '')
|
|
25363
25401
|
},
|
|
@@ -25400,6 +25438,21 @@ var TravelTypePicker = function () {
|
|
|
25400
25438
|
});
|
|
25401
25439
|
};
|
|
25402
25440
|
|
|
25441
|
+
var TravelNationalityPicker = function () {
|
|
25442
|
+
var nationalities = useContext(QSMConfigurationContext).nationalities;
|
|
25443
|
+
var selectedNationality = useSelector(function (state) {
|
|
25444
|
+
return state.qsm;
|
|
25445
|
+
}).selectedNationality;
|
|
25446
|
+
return React.createElement(ItemPicker$1, {
|
|
25447
|
+
items: nationalities,
|
|
25448
|
+
selection: selectedNationality,
|
|
25449
|
+
label: 'Nationaliteit',
|
|
25450
|
+
placeholder: 'Selecteer nationaliteit',
|
|
25451
|
+
classModifier: 'travel-class-picker__items',
|
|
25452
|
+
onPick: setSelectedNationality
|
|
25453
|
+
});
|
|
25454
|
+
};
|
|
25455
|
+
|
|
25403
25456
|
var QSMContainer = function () {
|
|
25404
25457
|
var isMobile = useMediaQuery('(max-width: 768px)');
|
|
25405
25458
|
var mobileFilterType = useSelector(function (state) {
|
|
@@ -25529,7 +25582,8 @@ var QSMContainer = function () {
|
|
|
25529
25582
|
'div',
|
|
25530
25583
|
{ className: 'qsm__filter__classgroup' },
|
|
25531
25584
|
React.createElement(TravelClassPicker, null),
|
|
25532
|
-
React.createElement(TravelTypePicker, null)
|
|
25585
|
+
React.createElement(TravelTypePicker, null),
|
|
25586
|
+
React.createElement(TravelNationalityPicker, null)
|
|
25533
25587
|
)
|
|
25534
25588
|
),
|
|
25535
25589
|
React.createElement(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { TravelClass, TravelType } from '../../types';
|
|
2
|
+
import { Nationality, TravelClass, TravelType } from '../../types';
|
|
3
3
|
interface ItemPickerProps {
|
|
4
|
-
items: TravelType[] | TravelClass[];
|
|
4
|
+
items: TravelType[] | TravelClass[] | Nationality[];
|
|
5
5
|
selection: string | undefined;
|
|
6
6
|
label: string;
|
|
7
7
|
placeholder: string;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { TypeaheadOption } from '../../types';
|
|
2
3
|
interface SearchInputProps {
|
|
3
4
|
onChange: (input: string) => void;
|
|
4
|
-
searchResults:
|
|
5
|
-
onOptionSelect: (val:
|
|
5
|
+
searchResults: TypeaheadOption[];
|
|
6
|
+
onOptionSelect: (val: TypeaheadOption) => void;
|
|
6
7
|
highlightTarget: string;
|
|
7
8
|
label: string;
|
|
8
9
|
isSecondInput?: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MobileFilterType, Room, TravelerType, TravelType, TravelClass } from '../types';
|
|
1
|
+
import { MobileFilterType, Room, TravelerType, TravelType, TravelClass, TypeaheadOption } from '../types';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
export interface QSMState {
|
|
4
4
|
selectedOrigin?: string;
|
|
@@ -9,16 +9,14 @@ export interface QSMState {
|
|
|
9
9
|
travelers: any[];
|
|
10
10
|
travelClass?: string;
|
|
11
11
|
mobileFilterType: MobileFilterType;
|
|
12
|
-
searchResults:
|
|
12
|
+
searchResults: TypeaheadOption[];
|
|
13
13
|
activeSearchField: string | null;
|
|
14
14
|
activeSearchFieldProps: {
|
|
15
15
|
fieldKey: string;
|
|
16
16
|
label: string;
|
|
17
17
|
placeholder: string;
|
|
18
18
|
value: string;
|
|
19
|
-
options:
|
|
20
|
-
value: string;
|
|
21
|
-
}[];
|
|
19
|
+
options: TypeaheadOption[];
|
|
22
20
|
} | null;
|
|
23
21
|
language: 'nl' | 'fr' | 'en';
|
|
24
22
|
mobileDatePickerMode: 'range' | 'single';
|
|
@@ -38,6 +36,7 @@ export interface QSMState {
|
|
|
38
36
|
selectedTravelType?: string;
|
|
39
37
|
travelClasses: TravelClass[];
|
|
40
38
|
selectedTravelClass?: string;
|
|
39
|
+
selectedNationality?: string;
|
|
41
40
|
defaultTravelers: number;
|
|
42
41
|
maxTravelers: number;
|
|
43
42
|
maxChildAge: number;
|
|
@@ -63,13 +62,11 @@ export declare const setOrigin: import('@reduxjs/toolkit').ActionCreatorWithPayl
|
|
|
63
62
|
label: string;
|
|
64
63
|
placeholder: string;
|
|
65
64
|
value: string;
|
|
66
|
-
options:
|
|
67
|
-
value: string;
|
|
68
|
-
}[];
|
|
65
|
+
options: TypeaheadOption[];
|
|
69
66
|
},
|
|
70
67
|
'qsm/setActiveSearchFieldProps'
|
|
71
68
|
>,
|
|
72
|
-
setSearchResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<
|
|
69
|
+
setSearchResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<TypeaheadOption[], 'qsm/setSearchResults'>,
|
|
73
70
|
setLanguage: import('@reduxjs/toolkit').ActionCreatorWithPayload<'nl' | 'fr' | 'en', 'qsm/setLanguage'>,
|
|
74
71
|
setMobileDatePickerMode: import('@reduxjs/toolkit').ActionCreatorWithPayload<'range' | 'single', 'qsm/setMobileDatePickerMode'>,
|
|
75
72
|
setMinDate: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<string | undefined, 'qsm/setMinDate'>,
|
|
@@ -95,6 +92,7 @@ export declare const setOrigin: import('@reduxjs/toolkit').ActionCreatorWithPayl
|
|
|
95
92
|
setSelectedTravelType: import('@reduxjs/toolkit').ActionCreatorWithPayload<any, 'qsm/setSelectedTravelType'>,
|
|
96
93
|
setTravelClasses: import('@reduxjs/toolkit').ActionCreatorWithPayload<TravelType[], 'qsm/setTravelClasses'>,
|
|
97
94
|
setSelectedTravelClass: import('@reduxjs/toolkit').ActionCreatorWithPayload<any, 'qsm/setSelectedTravelClass'>,
|
|
95
|
+
setSelectedNationality: import('@reduxjs/toolkit').ActionCreatorWithPayload<any, 'qsm/setSelectedNationality'>,
|
|
98
96
|
setDefaultTravelers: import('@reduxjs/toolkit').ActionCreatorWithPayload<number, 'qsm/setDefaultTravelers'>,
|
|
99
97
|
setMaxTravelers: import('@reduxjs/toolkit').ActionCreatorWithPayload<number, 'qsm/setMaxTravelers'>,
|
|
100
98
|
setMaxChildAge: import('@reduxjs/toolkit').ActionCreatorWithPayload<number, 'qsm/setMaxChildAge'>,
|
|
@@ -37,6 +37,7 @@ export interface QSMConfiguration {
|
|
|
37
37
|
onSubmit: (data: any) => void;
|
|
38
38
|
submitLabel: string;
|
|
39
39
|
submitIcon: ReactNode;
|
|
40
|
+
nationalities: Nationality[];
|
|
40
41
|
}
|
|
41
42
|
export interface BaseFieldConfig {
|
|
42
43
|
fieldKey: string;
|
|
@@ -47,6 +48,8 @@ export interface BaseFieldConfig {
|
|
|
47
48
|
export interface TypeaheadOption {
|
|
48
49
|
key: string;
|
|
49
50
|
value: string;
|
|
51
|
+
iataCode?: string;
|
|
52
|
+
country?: string;
|
|
50
53
|
type: OptionType;
|
|
51
54
|
}
|
|
52
55
|
export type OptionType = 'country' | 'region' | 'oord' | 'location' | 'airport' | 'hotel' | 'other';
|
|
@@ -89,6 +92,7 @@ export interface Room {
|
|
|
89
92
|
babies: number;
|
|
90
93
|
}
|
|
91
94
|
export interface TravelType {
|
|
95
|
+
id: number;
|
|
92
96
|
label: string;
|
|
93
97
|
icon?: ReactNode;
|
|
94
98
|
}
|
|
@@ -96,3 +100,8 @@ export interface TravelClass {
|
|
|
96
100
|
label: string;
|
|
97
101
|
icon?: ReactNode;
|
|
98
102
|
}
|
|
103
|
+
export interface Nationality {
|
|
104
|
+
id: number;
|
|
105
|
+
label: string;
|
|
106
|
+
icon?: ReactNode;
|
|
107
|
+
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@ import { TideLogo, language, languages, topLinks, navItems } from '../../../../s
|
|
|
4
4
|
import Icon from '../../components/icon';
|
|
5
5
|
import ContactForm from '../../components/contact';
|
|
6
6
|
import Slider from '../../components/slider';
|
|
7
|
-
import { QSMConfiguration, TypeaheadOption } from '../../../qsm/types';
|
|
7
|
+
import { Nationality, QSMConfiguration, TypeaheadOption } from '../../../qsm/types';
|
|
8
8
|
import QSM from '../../../qsm';
|
|
9
9
|
|
|
10
10
|
interface ContentPageSelfContainedProps {
|
|
@@ -38,6 +38,15 @@ const destinations: TypeaheadOption[] = [
|
|
|
38
38
|
{ key: 'SIN', value: 'Singapore Changi', type: 'location' }
|
|
39
39
|
];
|
|
40
40
|
|
|
41
|
+
const nationalities: Nationality[] = [
|
|
42
|
+
{ id: 1, label: 'Nederland' },
|
|
43
|
+
{ id: 2, label: 'België' },
|
|
44
|
+
{ id: 3, label: 'Duitsland' },
|
|
45
|
+
{ id: 4, label: 'Frankrijk' },
|
|
46
|
+
{ id: 5, label: 'Verenigd Koninkrijk' },
|
|
47
|
+
{ id: 6, label: 'Spanje' }
|
|
48
|
+
];
|
|
49
|
+
|
|
41
50
|
const configuration: QSMConfiguration = {
|
|
42
51
|
type: 'hotel',
|
|
43
52
|
askTravelers: true,
|
|
@@ -135,6 +144,8 @@ const configuration: QSMConfiguration = {
|
|
|
135
144
|
travelClasses: [],
|
|
136
145
|
travelClassIcon: '',
|
|
137
146
|
|
|
147
|
+
nationalities: nationalities,
|
|
148
|
+
|
|
138
149
|
dateFlexibility: [
|
|
139
150
|
{
|
|
140
151
|
name: '1 dag voor en na',
|
|
@@ -11,6 +11,7 @@ import TravelInputGroup from '../travel-input-group';
|
|
|
11
11
|
import TravelClassPicker from '../travel-class-picker';
|
|
12
12
|
import TravelTypePicker from '../travel-type-picker';
|
|
13
13
|
import Icon from '../icon';
|
|
14
|
+
import TravelNationalityPicker from '../travel-nationality-picker';
|
|
14
15
|
|
|
15
16
|
const QSMContainer: React.FC = () => {
|
|
16
17
|
const isMobile = useMediaQuery('(max-width: 768px)');
|
|
@@ -120,6 +121,7 @@ const QSMContainer: React.FC = () => {
|
|
|
120
121
|
<div className="qsm__filter__classgroup">
|
|
121
122
|
<TravelClassPicker />
|
|
122
123
|
<TravelTypePicker />
|
|
124
|
+
<TravelNationalityPicker />
|
|
123
125
|
</div>
|
|
124
126
|
</div>
|
|
125
127
|
<div className="qsm__input-group">
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import { useDispatch } from 'react-redux';
|
|
3
|
-
import { TravelClass, TravelType } from '../../types';
|
|
3
|
+
import { Nationality, TravelClass, TravelType } from '../../types';
|
|
4
4
|
|
|
5
5
|
interface ItemPickerProps {
|
|
6
|
-
items: TravelType[] | TravelClass[];
|
|
6
|
+
items: TravelType[] | TravelClass[] | Nationality[];
|
|
7
7
|
selection: string | undefined;
|
|
8
8
|
label: string;
|
|
9
9
|
placeholder: string;
|
|
@@ -21,8 +21,8 @@ const ItemPicker: React.FC<ItemPickerProps> = ({ items, selection, label, placeh
|
|
|
21
21
|
const toggleButtonRef = useRef<HTMLButtonElement | null>(null);
|
|
22
22
|
|
|
23
23
|
const handlePick = (picked: string) => {
|
|
24
|
-
dispatch(onPick(picked));
|
|
25
24
|
setIsDropdownOpen(false);
|
|
25
|
+
dispatch(onPick(picked));
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
useEffect(() => {
|
|
@@ -49,7 +49,7 @@ const ItemPicker: React.FC<ItemPickerProps> = ({ items, selection, label, placeh
|
|
|
49
49
|
}, [isDropdownOpen]);
|
|
50
50
|
|
|
51
51
|
return (
|
|
52
|
-
<
|
|
52
|
+
<div className={'dropdown__input ' + classModifier}>
|
|
53
53
|
<span className="dropdown__label">{label}</span>
|
|
54
54
|
<div className="dropdown">
|
|
55
55
|
<button
|
|
@@ -62,7 +62,13 @@ const ItemPicker: React.FC<ItemPickerProps> = ({ items, selection, label, placeh
|
|
|
62
62
|
{isDropdownOpen && (
|
|
63
63
|
<ul className={`dropdown-menu dropdown-menu--${openDirection}`} ref={dropdownMenuRef}>
|
|
64
64
|
{items.map(({ label, icon }) => (
|
|
65
|
-
<li
|
|
65
|
+
<li
|
|
66
|
+
key={label}
|
|
67
|
+
onClick={(e) => {
|
|
68
|
+
handlePick(label);
|
|
69
|
+
e.stopPropagation();
|
|
70
|
+
}}
|
|
71
|
+
className={`dropdown-menu__item${selection === label ? ' dropdown-menu__item--selected' : ''}`}>
|
|
66
72
|
{icon && <span className="travel-class-icon">{icon}</span>}
|
|
67
73
|
{label}
|
|
68
74
|
</li>
|
|
@@ -70,7 +76,7 @@ const ItemPicker: React.FC<ItemPickerProps> = ({ items, selection, label, placeh
|
|
|
70
76
|
</ul>
|
|
71
77
|
)}
|
|
72
78
|
</div>
|
|
73
|
-
</
|
|
79
|
+
</div>
|
|
74
80
|
);
|
|
75
81
|
};
|
|
76
82
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
import { useSelector } from 'react-redux';
|
|
3
|
+
import { QSMRootState } from '../../store/qsm-store';
|
|
4
|
+
import { setSelectedNationality } from '../../store/qsm-slice';
|
|
5
|
+
import QSMConfigurationContext from '../../qsm-configuration-context';
|
|
6
|
+
import ItemPicker from '../item-picker';
|
|
7
|
+
|
|
8
|
+
const TravelNationalityPicker: React.FC = () => {
|
|
9
|
+
const { nationalities } = useContext(QSMConfigurationContext);
|
|
10
|
+
const { selectedNationality } = useSelector((state: QSMRootState) => state.qsm);
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<ItemPicker
|
|
14
|
+
items={nationalities}
|
|
15
|
+
selection={selectedNationality}
|
|
16
|
+
label="Nationaliteit"
|
|
17
|
+
placeholder="Selecteer nationaliteit"
|
|
18
|
+
classModifier="travel-class-picker__items"
|
|
19
|
+
onPick={setSelectedNationality}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default TravelNationalityPicker;
|
|
@@ -36,6 +36,7 @@ export interface QSMState {
|
|
|
36
36
|
selectedTravelType?: string;
|
|
37
37
|
travelClasses: TravelClass[];
|
|
38
38
|
selectedTravelClass?: string;
|
|
39
|
+
selectedNationality?: string;
|
|
39
40
|
defaultTravelers: number;
|
|
40
41
|
maxTravelers: number;
|
|
41
42
|
maxChildAge: number;
|
|
@@ -75,6 +76,7 @@ const initialState: QSMState = {
|
|
|
75
76
|
selectedTravelType: undefined,
|
|
76
77
|
travelClasses: [],
|
|
77
78
|
selectedTravelClass: undefined,
|
|
79
|
+
selectedNationality: undefined,
|
|
78
80
|
defaultTravelers: 2,
|
|
79
81
|
maxTravelers: 9,
|
|
80
82
|
maxChildAge: 12,
|
|
@@ -174,6 +176,9 @@ const qsmSlice = createSlice({
|
|
|
174
176
|
setSelectedTravelClass: (state, action) => {
|
|
175
177
|
state.selectedTravelClass = action.payload;
|
|
176
178
|
},
|
|
179
|
+
setSelectedNationality: (state, action) => {
|
|
180
|
+
state.selectedNationality = action.payload;
|
|
181
|
+
},
|
|
177
182
|
setDefaultTravelers: (state, action: PayloadAction<number>) => {
|
|
178
183
|
state.defaultTravelers = action.payload;
|
|
179
184
|
},
|
|
@@ -245,6 +250,7 @@ export const {
|
|
|
245
250
|
setSelectedTravelType,
|
|
246
251
|
setTravelClasses,
|
|
247
252
|
setSelectedTravelClass,
|
|
253
|
+
setSelectedNationality,
|
|
248
254
|
setDefaultTravelers,
|
|
249
255
|
setMaxTravelers,
|
|
250
256
|
setMaxChildAge,
|
package/src/qsm/types.ts
CHANGED
|
@@ -54,6 +54,8 @@ export interface QSMConfiguration {
|
|
|
54
54
|
onSubmit: (data: any) => void;
|
|
55
55
|
submitLabel: string;
|
|
56
56
|
submitIcon: ReactNode;
|
|
57
|
+
|
|
58
|
+
nationalities: Nationality[];
|
|
57
59
|
}
|
|
58
60
|
|
|
59
61
|
export interface BaseFieldConfig {
|
|
@@ -132,3 +134,9 @@ export interface TravelClass {
|
|
|
132
134
|
label: string;
|
|
133
135
|
icon?: ReactNode;
|
|
134
136
|
}
|
|
137
|
+
|
|
138
|
+
export interface Nationality {
|
|
139
|
+
id: number;
|
|
140
|
+
label: string;
|
|
141
|
+
icon?: ReactNode;
|
|
142
|
+
}
|