@qite/tide-booking-component 1.4.25 → 1.4.26
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 +100 -68
- package/build/build-cjs/qsm/components/search-input/index.d.ts +3 -2
- package/build/build-cjs/qsm/store/qsm-slice.d.ts +5 -9
- package/build/build-cjs/qsm/types.d.ts +3 -0
- package/build/build-esm/index.js +99 -68
- package/build/build-esm/qsm/components/search-input/index.d.ts +3 -2
- package/build/build-esm/qsm/store/qsm-slice.d.ts +5 -9
- package/build/build-esm/qsm/types.d.ts +3 -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
|
@@ -23564,11 +23564,11 @@ var SearchInput = function (_a) {
|
|
|
23564
23564
|
_a.label;
|
|
23565
23565
|
var isSecondInput = _a.isSecondInput,
|
|
23566
23566
|
isDoubleInput = _a.isDoubleInput;
|
|
23567
|
-
var highlightMatch = function (
|
|
23567
|
+
var highlightMatch = function (option, highlight) {
|
|
23568
23568
|
if (!highlight) {
|
|
23569
|
-
return
|
|
23569
|
+
return option.value;
|
|
23570
23570
|
}
|
|
23571
|
-
var parts =
|
|
23571
|
+
var parts = option.value.split(new RegExp('('.concat(highlight, ')'), 'gi'));
|
|
23572
23572
|
return React__default['default'].createElement(
|
|
23573
23573
|
'span',
|
|
23574
23574
|
null,
|
|
@@ -23589,14 +23589,18 @@ var SearchInput = function (_a) {
|
|
|
23589
23589
|
.concat(isSecondInput ? ' qsm__double-input-options--second-input' : '')
|
|
23590
23590
|
.concat(isDoubleInput ? ' qsm__double-input-options--splittable' : '')
|
|
23591
23591
|
},
|
|
23592
|
-
searchResults.map(function (
|
|
23592
|
+
searchResults.map(function (option, index) {
|
|
23593
23593
|
return React__default['default'].createElement(
|
|
23594
23594
|
'div',
|
|
23595
23595
|
{
|
|
23596
23596
|
key: index,
|
|
23597
23597
|
className: 'qsm__double-input-option',
|
|
23598
|
-
|
|
23599
|
-
return
|
|
23598
|
+
onMouseDown: function (e) {
|
|
23599
|
+
return e.preventDefault();
|
|
23600
|
+
},
|
|
23601
|
+
onClick: function (e) {
|
|
23602
|
+
e.stopPropagation();
|
|
23603
|
+
onOptionSelect(option);
|
|
23600
23604
|
},
|
|
23601
23605
|
role: 'option',
|
|
23602
23606
|
'aria-selected': false
|
|
@@ -23604,15 +23608,16 @@ var SearchInput = function (_a) {
|
|
|
23604
23608
|
React__default['default'].createElement(
|
|
23605
23609
|
'div',
|
|
23606
23610
|
{ className: 'qsm__double-input-option-content' },
|
|
23607
|
-
React__default['default'].createElement(Icon$1, { name: 'ui-location', height: 16 }),
|
|
23611
|
+
React__default['default'].createElement(Icon$1, { name: option.type == 'hotel' ? 'ui-hotel' : 'ui-location', height: 16 }),
|
|
23608
23612
|
React__default['default'].createElement(
|
|
23609
23613
|
'div',
|
|
23610
23614
|
{ className: 'qsm__double-input-option-content-text' },
|
|
23611
|
-
highlightMatch(
|
|
23612
|
-
React__default['default'].createElement('span', { className: 'qsm__double-input-option-content-country' },
|
|
23615
|
+
highlightMatch(option, highlightTarget),
|
|
23616
|
+
option.country && React__default['default'].createElement('span', { className: 'qsm__double-input-option-content-country' }, option.country)
|
|
23613
23617
|
)
|
|
23614
23618
|
),
|
|
23615
|
-
|
|
23619
|
+
option.iataCode &&
|
|
23620
|
+
React__default['default'].createElement('span', { className: 'qsm__double-input-option-content-airport-label' }, '[', option.iataCode, ']')
|
|
23616
23621
|
);
|
|
23617
23622
|
})
|
|
23618
23623
|
);
|
|
@@ -24609,26 +24614,41 @@ var MobileFilterModal = function () {
|
|
|
24609
24614
|
hasTypedRef.current = false;
|
|
24610
24615
|
dispatch(closeMobileFilter());
|
|
24611
24616
|
};
|
|
24617
|
+
// const handleLocationChange = (val: string) => {
|
|
24618
|
+
// setInputValue(val);
|
|
24619
|
+
// hasTypedRef.current = true;
|
|
24620
|
+
// if (val.trim() !== '' && activeSearchFieldProps) {
|
|
24621
|
+
// const filtered = activeSearchFieldProps.options.filter((loc) => loc.value.toLowerCase().includes(val.toLowerCase())).map((loc) => loc.value);
|
|
24622
|
+
// setSearchResultsLocal(filtered);
|
|
24623
|
+
// } else {
|
|
24624
|
+
// setSearchResultsLocal([]);
|
|
24625
|
+
// }
|
|
24626
|
+
// };
|
|
24612
24627
|
var handleLocationChange = function (val) {
|
|
24613
24628
|
setInputValue(val);
|
|
24614
24629
|
hasTypedRef.current = true;
|
|
24615
24630
|
if (val.trim() !== '' && activeSearchFieldProps) {
|
|
24616
|
-
var filtered = activeSearchFieldProps.options
|
|
24617
|
-
.
|
|
24618
|
-
|
|
24619
|
-
})
|
|
24620
|
-
.map(function (loc) {
|
|
24621
|
-
return loc.value;
|
|
24622
|
-
});
|
|
24631
|
+
var filtered = activeSearchFieldProps.options.filter(function (option) {
|
|
24632
|
+
return option.value.toLowerCase().includes(val.toLowerCase());
|
|
24633
|
+
});
|
|
24623
24634
|
setSearchResultsLocal(filtered);
|
|
24624
24635
|
} else {
|
|
24625
24636
|
setSearchResultsLocal([]);
|
|
24626
24637
|
}
|
|
24627
24638
|
};
|
|
24628
|
-
|
|
24639
|
+
// const handleLocationSelect = (val: string) => {
|
|
24640
|
+
// if (activeSearchFieldProps) {
|
|
24641
|
+
// const { fieldKey } = activeSearchFieldProps;
|
|
24642
|
+
// dispatch(setFieldValue({ fieldKey, value: val }));
|
|
24643
|
+
// dispatch(setSearchResultsAction([]));
|
|
24644
|
+
// dispatch(setActiveSearchField(null));
|
|
24645
|
+
// }
|
|
24646
|
+
// dispatch(closeMobileFilter());
|
|
24647
|
+
// };
|
|
24648
|
+
var handleLocationSelect = function (option) {
|
|
24629
24649
|
if (activeSearchFieldProps) {
|
|
24630
24650
|
var fieldKey = activeSearchFieldProps.fieldKey;
|
|
24631
|
-
dispatch(setFieldValue({ fieldKey: fieldKey, value:
|
|
24651
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: option.value }));
|
|
24632
24652
|
dispatch(setSearchResults([]));
|
|
24633
24653
|
dispatch(setActiveSearchField(null));
|
|
24634
24654
|
}
|
|
@@ -24818,7 +24838,6 @@ var MobileFilterModal = function () {
|
|
|
24818
24838
|
}
|
|
24819
24839
|
};
|
|
24820
24840
|
|
|
24821
|
-
// SearchInputGroup.tsx
|
|
24822
24841
|
var findConfig = function (all, key) {
|
|
24823
24842
|
for (var _i = 0, all_1 = all; _i < all_1.length; _i++) {
|
|
24824
24843
|
var config = all_1[_i];
|
|
@@ -24859,17 +24878,6 @@ var SearchInputGroup = function (_a) {
|
|
|
24859
24878
|
var label = config.label,
|
|
24860
24879
|
placeholder = config.placeholder,
|
|
24861
24880
|
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
24881
|
var selector = React.useMemo(
|
|
24874
24882
|
function () {
|
|
24875
24883
|
return function (state) {
|
|
@@ -24886,30 +24894,44 @@ var SearchInputGroup = function (_a) {
|
|
|
24886
24894
|
searchResults = _g.searchResults,
|
|
24887
24895
|
activeSearchField = _g.activeSearchField;
|
|
24888
24896
|
var match = React.useCallback(
|
|
24889
|
-
function (
|
|
24890
|
-
if (!
|
|
24897
|
+
function (input) {
|
|
24898
|
+
if (!input) {
|
|
24891
24899
|
return [];
|
|
24892
24900
|
}
|
|
24893
|
-
var lowered =
|
|
24894
|
-
return
|
|
24895
|
-
.
|
|
24896
|
-
|
|
24897
|
-
})
|
|
24898
|
-
.map(function (x) {
|
|
24899
|
-
return x.value;
|
|
24900
|
-
});
|
|
24901
|
+
var lowered = input.toLowerCase();
|
|
24902
|
+
return options.filter(function (option) {
|
|
24903
|
+
return option.value.toLowerCase().includes(lowered);
|
|
24904
|
+
});
|
|
24901
24905
|
},
|
|
24902
|
-
[
|
|
24906
|
+
[options]
|
|
24903
24907
|
);
|
|
24904
|
-
var
|
|
24905
|
-
function (
|
|
24906
|
-
dispatch(setFieldValue({ fieldKey: fieldKey, value:
|
|
24908
|
+
var handleInputChange = React.useCallback(
|
|
24909
|
+
function (input) {
|
|
24910
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: input }));
|
|
24907
24911
|
dispatch(setSearchResults([]));
|
|
24908
|
-
if (
|
|
24909
|
-
|
|
24912
|
+
if (small) return;
|
|
24913
|
+
if (input.length === 3) {
|
|
24914
|
+
var exactIataMatch = findExactIataMatch(options, input);
|
|
24915
|
+
if (exactIataMatch) {
|
|
24916
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: exactIataMatch.value }));
|
|
24917
|
+
dispatch(setSearchResults([]));
|
|
24918
|
+
dispatch(setActiveSearchField(null));
|
|
24919
|
+
return;
|
|
24920
|
+
}
|
|
24910
24921
|
}
|
|
24922
|
+
// Normal typeahead behavior
|
|
24923
|
+
dispatch(setActiveSearchField(fieldKey));
|
|
24924
|
+
dispatch(setSearchResults(match(input)));
|
|
24911
24925
|
},
|
|
24912
|
-
[dispatch, fieldKey, small, match]
|
|
24926
|
+
[dispatch, fieldKey, small, match, options]
|
|
24927
|
+
);
|
|
24928
|
+
var handleOptionSelect = React.useCallback(
|
|
24929
|
+
function (option) {
|
|
24930
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: option.value }));
|
|
24931
|
+
dispatch(setSearchResults([]));
|
|
24932
|
+
dispatch(setActiveSearchField(null));
|
|
24933
|
+
},
|
|
24934
|
+
[dispatch, fieldKey]
|
|
24913
24935
|
);
|
|
24914
24936
|
var click = function () {
|
|
24915
24937
|
dispatch(setActiveSearchField(fieldKey));
|
|
@@ -24929,6 +24951,11 @@ var SearchInputGroup = function (_a) {
|
|
|
24929
24951
|
dispatch(setSearchResults(match(value)));
|
|
24930
24952
|
}
|
|
24931
24953
|
};
|
|
24954
|
+
var findExactIataMatch = function (options, input) {
|
|
24955
|
+
return options.find(function (option) {
|
|
24956
|
+
return option.iataCode && option.iataCode.toLowerCase() === input.toLowerCase();
|
|
24957
|
+
});
|
|
24958
|
+
};
|
|
24932
24959
|
React.useEffect(
|
|
24933
24960
|
function () {
|
|
24934
24961
|
var outside = function (e) {
|
|
@@ -24965,9 +24992,12 @@ var SearchInputGroup = function (_a) {
|
|
|
24965
24992
|
name: fieldKey,
|
|
24966
24993
|
value: value,
|
|
24967
24994
|
readOnly: small,
|
|
24968
|
-
|
|
24995
|
+
onFocus: click,
|
|
24996
|
+
onClick: function (e) {
|
|
24997
|
+
return e.stopPropagation();
|
|
24998
|
+
},
|
|
24969
24999
|
onChange: function (e) {
|
|
24970
|
-
return !small && !readOnlyForced &&
|
|
25000
|
+
return !small && !readOnlyForced && handleInputChange(e.target.value);
|
|
24971
25001
|
},
|
|
24972
25002
|
className: 'qsm__input'.concat(isSecondInput ? ' qsm__input--splittable' : ' u-ps-2'),
|
|
24973
25003
|
placeholder: placeholder
|
|
@@ -24975,12 +25005,9 @@ var SearchInputGroup = function (_a) {
|
|
|
24975
25005
|
!small &&
|
|
24976
25006
|
activeSearchField === fieldKey &&
|
|
24977
25007
|
React__default['default'].createElement(SearchInput, {
|
|
24978
|
-
onChange:
|
|
25008
|
+
onChange: handleInputChange,
|
|
24979
25009
|
searchResults: searchResults,
|
|
24980
|
-
onOptionSelect:
|
|
24981
|
-
change(val);
|
|
24982
|
-
dispatch(setActiveSearchField(null));
|
|
24983
|
-
},
|
|
25010
|
+
onOptionSelect: handleOptionSelect,
|
|
24984
25011
|
highlightTarget: highlightTarget,
|
|
24985
25012
|
label: label,
|
|
24986
25013
|
isSecondInput: isSecondInput,
|
|
@@ -25148,7 +25175,7 @@ var DoubleSearchInputGroup = function (_a) {
|
|
|
25148
25175
|
{ className: 'qsm__reverse-wrapper' },
|
|
25149
25176
|
React__default['default'].createElement(
|
|
25150
25177
|
'button',
|
|
25151
|
-
{ type: 'button', onClick: reverse, className: 'qsm__input-line--reverse-button' },
|
|
25178
|
+
{ type: 'button', onClick: reverse, className: 'qsm__input-line--reverse-button', tabIndex: -1 },
|
|
25152
25179
|
React__default['default'].createElement(
|
|
25153
25180
|
'svg',
|
|
25154
25181
|
{ id: 'qsm-planes-icon', viewBox: '0 0 18 18', width: 18, height: 18 },
|
|
@@ -25394,17 +25421,22 @@ var TravelInputGroup = function () {
|
|
|
25394
25421
|
});
|
|
25395
25422
|
}
|
|
25396
25423
|
};
|
|
25397
|
-
React.useEffect(
|
|
25398
|
-
|
|
25399
|
-
|
|
25400
|
-
|
|
25424
|
+
React.useEffect(
|
|
25425
|
+
function () {
|
|
25426
|
+
var handleClickOutside = function (event) {
|
|
25427
|
+
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
|
|
25428
|
+
setIsOpen(false);
|
|
25429
|
+
}
|
|
25430
|
+
};
|
|
25431
|
+
if (isOpen) {
|
|
25432
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
25401
25433
|
}
|
|
25402
|
-
|
|
25403
|
-
|
|
25404
|
-
|
|
25405
|
-
|
|
25406
|
-
|
|
25407
|
-
|
|
25434
|
+
return function () {
|
|
25435
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
25436
|
+
};
|
|
25437
|
+
},
|
|
25438
|
+
[isOpen]
|
|
25439
|
+
);
|
|
25408
25440
|
React.useEffect(
|
|
25409
25441
|
function () {
|
|
25410
25442
|
if (initDone.current) {
|
|
@@ -25432,8 +25464,8 @@ var TravelInputGroup = function () {
|
|
|
25432
25464
|
[defaultTravelers, maxTravelers]
|
|
25433
25465
|
);
|
|
25434
25466
|
return React__default['default'].createElement(
|
|
25435
|
-
'
|
|
25436
|
-
{ className: 'qsm__single-input-wrapper qsm__single-input-wrapper--travel' },
|
|
25467
|
+
'div',
|
|
25468
|
+
{ ref: wrapperRef, className: 'qsm__single-input-wrapper qsm__single-input-wrapper--travel' },
|
|
25437
25469
|
React__default['default'].createElement(Icon$1, { name: 'ui-user', height: 16 }),
|
|
25438
25470
|
React__default['default'].createElement('span', { className: 'qsm__label' }, 'Met wie ga je?'),
|
|
25439
25471
|
React__default['default'].createElement('input', {
|
|
@@ -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';
|
|
@@ -63,13 +61,11 @@ export declare const setOrigin: import('@reduxjs/toolkit').ActionCreatorWithPayl
|
|
|
63
61
|
label: string;
|
|
64
62
|
placeholder: string;
|
|
65
63
|
value: string;
|
|
66
|
-
options:
|
|
67
|
-
value: string;
|
|
68
|
-
}[];
|
|
64
|
+
options: TypeaheadOption[];
|
|
69
65
|
},
|
|
70
66
|
'qsm/setActiveSearchFieldProps'
|
|
71
67
|
>,
|
|
72
|
-
setSearchResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<
|
|
68
|
+
setSearchResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<TypeaheadOption[], 'qsm/setSearchResults'>,
|
|
73
69
|
setLanguage: import('@reduxjs/toolkit').ActionCreatorWithPayload<'nl' | 'fr' | 'en', 'qsm/setLanguage'>,
|
|
74
70
|
setMobileDatePickerMode: import('@reduxjs/toolkit').ActionCreatorWithPayload<'range' | 'single', 'qsm/setMobileDatePickerMode'>,
|
|
75
71
|
setMinDate: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<string | undefined, 'qsm/setMinDate'>,
|
|
@@ -47,6 +47,8 @@ export interface BaseFieldConfig {
|
|
|
47
47
|
export interface TypeaheadOption {
|
|
48
48
|
key: string;
|
|
49
49
|
value: string;
|
|
50
|
+
iataCode?: string;
|
|
51
|
+
country?: string;
|
|
50
52
|
type: OptionType;
|
|
51
53
|
}
|
|
52
54
|
export type OptionType = 'country' | 'region' | 'oord' | 'location' | 'airport' | 'hotel' | 'other';
|
|
@@ -89,6 +91,7 @@ export interface Room {
|
|
|
89
91
|
babies: number;
|
|
90
92
|
}
|
|
91
93
|
export interface TravelType {
|
|
94
|
+
id: number;
|
|
92
95
|
label: string;
|
|
93
96
|
icon?: ReactNode;
|
|
94
97
|
}
|
package/build/build-esm/index.js
CHANGED
|
@@ -23422,11 +23422,11 @@ var SearchInput = function (_a) {
|
|
|
23422
23422
|
_a.label;
|
|
23423
23423
|
var isSecondInput = _a.isSecondInput,
|
|
23424
23424
|
isDoubleInput = _a.isDoubleInput;
|
|
23425
|
-
var highlightMatch = function (
|
|
23425
|
+
var highlightMatch = function (option, highlight) {
|
|
23426
23426
|
if (!highlight) {
|
|
23427
|
-
return
|
|
23427
|
+
return option.value;
|
|
23428
23428
|
}
|
|
23429
|
-
var parts =
|
|
23429
|
+
var parts = option.value.split(new RegExp('('.concat(highlight, ')'), 'gi'));
|
|
23430
23430
|
return React.createElement(
|
|
23431
23431
|
'span',
|
|
23432
23432
|
null,
|
|
@@ -23447,14 +23447,18 @@ var SearchInput = function (_a) {
|
|
|
23447
23447
|
.concat(isSecondInput ? ' qsm__double-input-options--second-input' : '')
|
|
23448
23448
|
.concat(isDoubleInput ? ' qsm__double-input-options--splittable' : '')
|
|
23449
23449
|
},
|
|
23450
|
-
searchResults.map(function (
|
|
23450
|
+
searchResults.map(function (option, index) {
|
|
23451
23451
|
return React.createElement(
|
|
23452
23452
|
'div',
|
|
23453
23453
|
{
|
|
23454
23454
|
key: index,
|
|
23455
23455
|
className: 'qsm__double-input-option',
|
|
23456
|
-
|
|
23457
|
-
return
|
|
23456
|
+
onMouseDown: function (e) {
|
|
23457
|
+
return e.preventDefault();
|
|
23458
|
+
},
|
|
23459
|
+
onClick: function (e) {
|
|
23460
|
+
e.stopPropagation();
|
|
23461
|
+
onOptionSelect(option);
|
|
23458
23462
|
},
|
|
23459
23463
|
role: 'option',
|
|
23460
23464
|
'aria-selected': false
|
|
@@ -23462,15 +23466,15 @@ var SearchInput = function (_a) {
|
|
|
23462
23466
|
React.createElement(
|
|
23463
23467
|
'div',
|
|
23464
23468
|
{ className: 'qsm__double-input-option-content' },
|
|
23465
|
-
React.createElement(Icon$1, { name: 'ui-location', height: 16 }),
|
|
23469
|
+
React.createElement(Icon$1, { name: option.type == 'hotel' ? 'ui-hotel' : 'ui-location', height: 16 }),
|
|
23466
23470
|
React.createElement(
|
|
23467
23471
|
'div',
|
|
23468
23472
|
{ className: 'qsm__double-input-option-content-text' },
|
|
23469
|
-
highlightMatch(
|
|
23470
|
-
React.createElement('span', { className: 'qsm__double-input-option-content-country' },
|
|
23473
|
+
highlightMatch(option, highlightTarget),
|
|
23474
|
+
option.country && React.createElement('span', { className: 'qsm__double-input-option-content-country' }, option.country)
|
|
23471
23475
|
)
|
|
23472
23476
|
),
|
|
23473
|
-
React.createElement('span', { className: 'qsm__double-input-option-content-airport-label' }, '[
|
|
23477
|
+
option.iataCode && React.createElement('span', { className: 'qsm__double-input-option-content-airport-label' }, '[', option.iataCode, ']')
|
|
23474
23478
|
);
|
|
23475
23479
|
})
|
|
23476
23480
|
);
|
|
@@ -24452,26 +24456,41 @@ var MobileFilterModal = function () {
|
|
|
24452
24456
|
hasTypedRef.current = false;
|
|
24453
24457
|
dispatch(closeMobileFilter());
|
|
24454
24458
|
};
|
|
24459
|
+
// const handleLocationChange = (val: string) => {
|
|
24460
|
+
// setInputValue(val);
|
|
24461
|
+
// hasTypedRef.current = true;
|
|
24462
|
+
// if (val.trim() !== '' && activeSearchFieldProps) {
|
|
24463
|
+
// const filtered = activeSearchFieldProps.options.filter((loc) => loc.value.toLowerCase().includes(val.toLowerCase())).map((loc) => loc.value);
|
|
24464
|
+
// setSearchResultsLocal(filtered);
|
|
24465
|
+
// } else {
|
|
24466
|
+
// setSearchResultsLocal([]);
|
|
24467
|
+
// }
|
|
24468
|
+
// };
|
|
24455
24469
|
var handleLocationChange = function (val) {
|
|
24456
24470
|
setInputValue(val);
|
|
24457
24471
|
hasTypedRef.current = true;
|
|
24458
24472
|
if (val.trim() !== '' && activeSearchFieldProps) {
|
|
24459
|
-
var filtered = activeSearchFieldProps.options
|
|
24460
|
-
.
|
|
24461
|
-
|
|
24462
|
-
})
|
|
24463
|
-
.map(function (loc) {
|
|
24464
|
-
return loc.value;
|
|
24465
|
-
});
|
|
24473
|
+
var filtered = activeSearchFieldProps.options.filter(function (option) {
|
|
24474
|
+
return option.value.toLowerCase().includes(val.toLowerCase());
|
|
24475
|
+
});
|
|
24466
24476
|
setSearchResultsLocal(filtered);
|
|
24467
24477
|
} else {
|
|
24468
24478
|
setSearchResultsLocal([]);
|
|
24469
24479
|
}
|
|
24470
24480
|
};
|
|
24471
|
-
|
|
24481
|
+
// const handleLocationSelect = (val: string) => {
|
|
24482
|
+
// if (activeSearchFieldProps) {
|
|
24483
|
+
// const { fieldKey } = activeSearchFieldProps;
|
|
24484
|
+
// dispatch(setFieldValue({ fieldKey, value: val }));
|
|
24485
|
+
// dispatch(setSearchResultsAction([]));
|
|
24486
|
+
// dispatch(setActiveSearchField(null));
|
|
24487
|
+
// }
|
|
24488
|
+
// dispatch(closeMobileFilter());
|
|
24489
|
+
// };
|
|
24490
|
+
var handleLocationSelect = function (option) {
|
|
24472
24491
|
if (activeSearchFieldProps) {
|
|
24473
24492
|
var fieldKey = activeSearchFieldProps.fieldKey;
|
|
24474
|
-
dispatch(setFieldValue({ fieldKey: fieldKey, value:
|
|
24493
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: option.value }));
|
|
24475
24494
|
dispatch(setSearchResults([]));
|
|
24476
24495
|
dispatch(setActiveSearchField(null));
|
|
24477
24496
|
}
|
|
@@ -24657,7 +24676,6 @@ var MobileFilterModal = function () {
|
|
|
24657
24676
|
}
|
|
24658
24677
|
};
|
|
24659
24678
|
|
|
24660
|
-
// SearchInputGroup.tsx
|
|
24661
24679
|
var findConfig = function (all, key) {
|
|
24662
24680
|
for (var _i = 0, all_1 = all; _i < all_1.length; _i++) {
|
|
24663
24681
|
var config = all_1[_i];
|
|
@@ -24698,17 +24716,6 @@ var SearchInputGroup = function (_a) {
|
|
|
24698
24716
|
var label = config.label,
|
|
24699
24717
|
placeholder = config.placeholder,
|
|
24700
24718
|
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
24719
|
var selector = useMemo(
|
|
24713
24720
|
function () {
|
|
24714
24721
|
return function (state) {
|
|
@@ -24725,30 +24732,44 @@ var SearchInputGroup = function (_a) {
|
|
|
24725
24732
|
searchResults = _g.searchResults,
|
|
24726
24733
|
activeSearchField = _g.activeSearchField;
|
|
24727
24734
|
var match = useCallback(
|
|
24728
|
-
function (
|
|
24729
|
-
if (!
|
|
24735
|
+
function (input) {
|
|
24736
|
+
if (!input) {
|
|
24730
24737
|
return [];
|
|
24731
24738
|
}
|
|
24732
|
-
var lowered =
|
|
24733
|
-
return
|
|
24734
|
-
.
|
|
24735
|
-
|
|
24736
|
-
})
|
|
24737
|
-
.map(function (x) {
|
|
24738
|
-
return x.value;
|
|
24739
|
-
});
|
|
24739
|
+
var lowered = input.toLowerCase();
|
|
24740
|
+
return options.filter(function (option) {
|
|
24741
|
+
return option.value.toLowerCase().includes(lowered);
|
|
24742
|
+
});
|
|
24740
24743
|
},
|
|
24741
|
-
[
|
|
24744
|
+
[options]
|
|
24742
24745
|
);
|
|
24743
|
-
var
|
|
24744
|
-
function (
|
|
24745
|
-
dispatch(setFieldValue({ fieldKey: fieldKey, value:
|
|
24746
|
+
var handleInputChange = useCallback(
|
|
24747
|
+
function (input) {
|
|
24748
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: input }));
|
|
24746
24749
|
dispatch(setSearchResults([]));
|
|
24747
|
-
if (
|
|
24748
|
-
|
|
24750
|
+
if (small) return;
|
|
24751
|
+
if (input.length === 3) {
|
|
24752
|
+
var exactIataMatch = findExactIataMatch(options, input);
|
|
24753
|
+
if (exactIataMatch) {
|
|
24754
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: exactIataMatch.value }));
|
|
24755
|
+
dispatch(setSearchResults([]));
|
|
24756
|
+
dispatch(setActiveSearchField(null));
|
|
24757
|
+
return;
|
|
24758
|
+
}
|
|
24749
24759
|
}
|
|
24760
|
+
// Normal typeahead behavior
|
|
24761
|
+
dispatch(setActiveSearchField(fieldKey));
|
|
24762
|
+
dispatch(setSearchResults(match(input)));
|
|
24750
24763
|
},
|
|
24751
|
-
[dispatch, fieldKey, small, match]
|
|
24764
|
+
[dispatch, fieldKey, small, match, options]
|
|
24765
|
+
);
|
|
24766
|
+
var handleOptionSelect = useCallback(
|
|
24767
|
+
function (option) {
|
|
24768
|
+
dispatch(setFieldValue({ fieldKey: fieldKey, value: option.value }));
|
|
24769
|
+
dispatch(setSearchResults([]));
|
|
24770
|
+
dispatch(setActiveSearchField(null));
|
|
24771
|
+
},
|
|
24772
|
+
[dispatch, fieldKey]
|
|
24752
24773
|
);
|
|
24753
24774
|
var click = function () {
|
|
24754
24775
|
dispatch(setActiveSearchField(fieldKey));
|
|
@@ -24768,6 +24789,11 @@ var SearchInputGroup = function (_a) {
|
|
|
24768
24789
|
dispatch(setSearchResults(match(value)));
|
|
24769
24790
|
}
|
|
24770
24791
|
};
|
|
24792
|
+
var findExactIataMatch = function (options, input) {
|
|
24793
|
+
return options.find(function (option) {
|
|
24794
|
+
return option.iataCode && option.iataCode.toLowerCase() === input.toLowerCase();
|
|
24795
|
+
});
|
|
24796
|
+
};
|
|
24771
24797
|
useEffect(
|
|
24772
24798
|
function () {
|
|
24773
24799
|
var outside = function (e) {
|
|
@@ -24800,9 +24826,12 @@ var SearchInputGroup = function (_a) {
|
|
|
24800
24826
|
name: fieldKey,
|
|
24801
24827
|
value: value,
|
|
24802
24828
|
readOnly: small,
|
|
24803
|
-
|
|
24829
|
+
onFocus: click,
|
|
24830
|
+
onClick: function (e) {
|
|
24831
|
+
return e.stopPropagation();
|
|
24832
|
+
},
|
|
24804
24833
|
onChange: function (e) {
|
|
24805
|
-
return !small && !readOnlyForced &&
|
|
24834
|
+
return !small && !readOnlyForced && handleInputChange(e.target.value);
|
|
24806
24835
|
},
|
|
24807
24836
|
className: 'qsm__input'.concat(isSecondInput ? ' qsm__input--splittable' : ' u-ps-2'),
|
|
24808
24837
|
placeholder: placeholder
|
|
@@ -24810,12 +24839,9 @@ var SearchInputGroup = function (_a) {
|
|
|
24810
24839
|
!small &&
|
|
24811
24840
|
activeSearchField === fieldKey &&
|
|
24812
24841
|
React.createElement(SearchInput, {
|
|
24813
|
-
onChange:
|
|
24842
|
+
onChange: handleInputChange,
|
|
24814
24843
|
searchResults: searchResults,
|
|
24815
|
-
onOptionSelect:
|
|
24816
|
-
change(val);
|
|
24817
|
-
dispatch(setActiveSearchField(null));
|
|
24818
|
-
},
|
|
24844
|
+
onOptionSelect: handleOptionSelect,
|
|
24819
24845
|
highlightTarget: highlightTarget,
|
|
24820
24846
|
label: label,
|
|
24821
24847
|
isSecondInput: isSecondInput,
|
|
@@ -24978,7 +25004,7 @@ var DoubleSearchInputGroup = function (_a) {
|
|
|
24978
25004
|
{ className: 'qsm__reverse-wrapper' },
|
|
24979
25005
|
React.createElement(
|
|
24980
25006
|
'button',
|
|
24981
|
-
{ type: 'button', onClick: reverse, className: 'qsm__input-line--reverse-button' },
|
|
25007
|
+
{ type: 'button', onClick: reverse, className: 'qsm__input-line--reverse-button', tabIndex: -1 },
|
|
24982
25008
|
React.createElement(
|
|
24983
25009
|
'svg',
|
|
24984
25010
|
{ id: 'qsm-planes-icon', viewBox: '0 0 18 18', width: 18, height: 18 },
|
|
@@ -25224,17 +25250,22 @@ var TravelInputGroup = function () {
|
|
|
25224
25250
|
});
|
|
25225
25251
|
}
|
|
25226
25252
|
};
|
|
25227
|
-
useEffect(
|
|
25228
|
-
|
|
25229
|
-
|
|
25230
|
-
|
|
25253
|
+
useEffect(
|
|
25254
|
+
function () {
|
|
25255
|
+
var handleClickOutside = function (event) {
|
|
25256
|
+
if (wrapperRef.current && !wrapperRef.current.contains(event.target)) {
|
|
25257
|
+
setIsOpen(false);
|
|
25258
|
+
}
|
|
25259
|
+
};
|
|
25260
|
+
if (isOpen) {
|
|
25261
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
25231
25262
|
}
|
|
25232
|
-
|
|
25233
|
-
|
|
25234
|
-
|
|
25235
|
-
|
|
25236
|
-
|
|
25237
|
-
|
|
25263
|
+
return function () {
|
|
25264
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
25265
|
+
};
|
|
25266
|
+
},
|
|
25267
|
+
[isOpen]
|
|
25268
|
+
);
|
|
25238
25269
|
useEffect(
|
|
25239
25270
|
function () {
|
|
25240
25271
|
if (initDone.current) {
|
|
@@ -25262,8 +25293,8 @@ var TravelInputGroup = function () {
|
|
|
25262
25293
|
[defaultTravelers, maxTravelers]
|
|
25263
25294
|
);
|
|
25264
25295
|
return React.createElement(
|
|
25265
|
-
'
|
|
25266
|
-
{ className: 'qsm__single-input-wrapper qsm__single-input-wrapper--travel' },
|
|
25296
|
+
'div',
|
|
25297
|
+
{ ref: wrapperRef, className: 'qsm__single-input-wrapper qsm__single-input-wrapper--travel' },
|
|
25267
25298
|
React.createElement(Icon$1, { name: 'ui-user', height: 16 }),
|
|
25268
25299
|
React.createElement('span', { className: 'qsm__label' }, 'Met wie ga je?'),
|
|
25269
25300
|
React.createElement('input', {
|
|
@@ -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';
|
|
@@ -63,13 +61,11 @@ export declare const setOrigin: import('@reduxjs/toolkit').ActionCreatorWithPayl
|
|
|
63
61
|
label: string;
|
|
64
62
|
placeholder: string;
|
|
65
63
|
value: string;
|
|
66
|
-
options:
|
|
67
|
-
value: string;
|
|
68
|
-
}[];
|
|
64
|
+
options: TypeaheadOption[];
|
|
69
65
|
},
|
|
70
66
|
'qsm/setActiveSearchFieldProps'
|
|
71
67
|
>,
|
|
72
|
-
setSearchResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<
|
|
68
|
+
setSearchResults: import('@reduxjs/toolkit').ActionCreatorWithPayload<TypeaheadOption[], 'qsm/setSearchResults'>,
|
|
73
69
|
setLanguage: import('@reduxjs/toolkit').ActionCreatorWithPayload<'nl' | 'fr' | 'en', 'qsm/setLanguage'>,
|
|
74
70
|
setMobileDatePickerMode: import('@reduxjs/toolkit').ActionCreatorWithPayload<'range' | 'single', 'qsm/setMobileDatePickerMode'>,
|
|
75
71
|
setMinDate: import('@reduxjs/toolkit').ActionCreatorWithOptionalPayload<string | undefined, 'qsm/setMinDate'>,
|
|
@@ -47,6 +47,8 @@ export interface BaseFieldConfig {
|
|
|
47
47
|
export interface TypeaheadOption {
|
|
48
48
|
key: string;
|
|
49
49
|
value: string;
|
|
50
|
+
iataCode?: string;
|
|
51
|
+
country?: string;
|
|
50
52
|
type: OptionType;
|
|
51
53
|
}
|
|
52
54
|
export type OptionType = 'country' | 'region' | 'oord' | 'location' | 'airport' | 'hotel' | 'other';
|
|
@@ -89,6 +91,7 @@ export interface Room {
|
|
|
89
91
|
babies: number;
|
|
90
92
|
}
|
|
91
93
|
export interface TravelType {
|
|
94
|
+
id: number;
|
|
92
95
|
label: string;
|
|
93
96
|
icon?: ReactNode;
|
|
94
97
|
}
|
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
|
+
}
|