@qite/tide-booking-component 1.4.27 → 1.4.29
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 +98 -205
- package/build/build-cjs/qsm/store/qsm-slice.d.ts +0 -1
- package/build/build-cjs/qsm/types.d.ts +2 -0
- package/build/build-esm/index.js +98 -205
- package/build/build-esm/qsm/store/qsm-slice.d.ts +0 -1
- package/build/build-esm/qsm/types.d.ts +2 -0
- package/package.json +1 -1
- package/src/qsm/components/QSMContainer/qsm-container.tsx +98 -37
- package/src/qsm/components/item-picker/index.tsx +1 -13
- package/src/qsm/components/search-input-group/index.tsx +2 -2
- package/src/qsm/store/qsm-slice.ts +0 -1
- package/src/qsm/types.ts +2 -0
package/build/build-cjs/index.js
CHANGED
|
@@ -23074,11 +23074,11 @@ var setMobileFilterType = _a$1.setMobileFilterType,
|
|
|
23074
23074
|
setActiveSearchFieldProps = _a$1.setActiveSearchFieldProps,
|
|
23075
23075
|
setSearchResults = _a$1.setSearchResults;
|
|
23076
23076
|
_a$1.setLanguage;
|
|
23077
|
-
|
|
23078
|
-
|
|
23079
|
-
|
|
23080
|
-
|
|
23081
|
-
|
|
23077
|
+
_a$1.setMobileDatePickerMode;
|
|
23078
|
+
_a$1.setMinDate;
|
|
23079
|
+
_a$1.setMaxDate;
|
|
23080
|
+
_a$1.setDateFlexibility;
|
|
23081
|
+
var setSelectedFlexRange = _a$1.setSelectedFlexRange;
|
|
23082
23082
|
_a$1.setTravelTypes;
|
|
23083
23083
|
var setSelectedTravelType = _a$1.setSelectedTravelType;
|
|
23084
23084
|
_a$1.setTravelClasses;
|
|
@@ -24883,7 +24883,8 @@ var SearchInputGroup = function (_a) {
|
|
|
24883
24883
|
}
|
|
24884
24884
|
var label = config.label,
|
|
24885
24885
|
placeholder = config.placeholder,
|
|
24886
|
-
options = config.options
|
|
24886
|
+
options = config.options,
|
|
24887
|
+
autoComplete = config.autoComplete;
|
|
24887
24888
|
var selector = React.useMemo(
|
|
24888
24889
|
function () {
|
|
24889
24890
|
return function (state) {
|
|
@@ -24916,7 +24917,7 @@ var SearchInputGroup = function (_a) {
|
|
|
24916
24917
|
dispatch(setFieldValue({ fieldKey: fieldKey, value: input }));
|
|
24917
24918
|
dispatch(setSearchResults([]));
|
|
24918
24919
|
if (small) return;
|
|
24919
|
-
if (input.length === 3) {
|
|
24920
|
+
if (input.length === 3 && autoComplete) {
|
|
24920
24921
|
var exactIataMatch = findExactIataMatch(options, input);
|
|
24921
24922
|
if (exactIataMatch) {
|
|
24922
24923
|
dispatch(setFieldValue({ fieldKey: fieldKey, value: exactIataMatch.value }));
|
|
@@ -25201,180 +25202,6 @@ var DoubleSearchInputGroup = function (_a) {
|
|
|
25201
25202
|
);
|
|
25202
25203
|
};
|
|
25203
25204
|
|
|
25204
|
-
var DatePicker = function () {
|
|
25205
|
-
var dispatch = reactRedux.useDispatch();
|
|
25206
|
-
var isSmallScreen = useMediaQuery('(max-width: 768px)');
|
|
25207
|
-
/* 🔑 STATE FIRST (no TDZ issues) */
|
|
25208
|
-
var _a = React.useState(false),
|
|
25209
|
-
isOpen = _a[0],
|
|
25210
|
-
setIsOpen = _a[1]; // range pop-over
|
|
25211
|
-
var _b = React.useState(false),
|
|
25212
|
-
isSingleOpen = _b[0],
|
|
25213
|
-
setIsSingleOpen = _b[1]; // single pop-over
|
|
25214
|
-
var _c = React.useContext(QSMConfigurationContext),
|
|
25215
|
-
datesIcon = _c.datesIcon,
|
|
25216
|
-
_d = _c.showReturnDate,
|
|
25217
|
-
showReturnDate = _d === void 0 ? true : _d,
|
|
25218
|
-
minDate = _c.minDate,
|
|
25219
|
-
maxDate = _c.maxDate,
|
|
25220
|
-
_e = _c.dateFlexibility,
|
|
25221
|
-
dateFlexibility = _e === void 0 ? [] : _e;
|
|
25222
|
-
var isSingleDate = !showReturnDate;
|
|
25223
|
-
var dateInputWrapperRef = React.useRef(null);
|
|
25224
|
-
var dateInputRef = React.useRef(null);
|
|
25225
|
-
var today = dateFns.startOfDay(new Date());
|
|
25226
|
-
var effectiveMinDate = minDate !== null && minDate !== void 0 ? minDate : today;
|
|
25227
|
-
var effectiveMaxDate = maxDate !== null && maxDate !== void 0 ? maxDate : dateFns.addYears(today, 1);
|
|
25228
|
-
var _f = reactRedux.useSelector(function (state) {
|
|
25229
|
-
return {
|
|
25230
|
-
fromDate: state.qsm.fromDate,
|
|
25231
|
-
toDate: state.qsm.toDate
|
|
25232
|
-
};
|
|
25233
|
-
}),
|
|
25234
|
-
fromDate = _f.fromDate,
|
|
25235
|
-
toDate = _f.toDate;
|
|
25236
|
-
/* ----------------------- outside click close ----------------------- */
|
|
25237
|
-
React.useEffect(function () {
|
|
25238
|
-
var handleClickOutside = function (event) {
|
|
25239
|
-
if (
|
|
25240
|
-
dateInputWrapperRef.current &&
|
|
25241
|
-
!dateInputWrapperRef.current.contains(event.target) &&
|
|
25242
|
-
dateInputRef.current &&
|
|
25243
|
-
!dateInputRef.current.contains(event.target)
|
|
25244
|
-
) {
|
|
25245
|
-
setIsOpen(false);
|
|
25246
|
-
setIsSingleOpen(false);
|
|
25247
|
-
}
|
|
25248
|
-
};
|
|
25249
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
25250
|
-
return function () {
|
|
25251
|
-
return document.removeEventListener('mousedown', handleClickOutside);
|
|
25252
|
-
};
|
|
25253
|
-
}, []);
|
|
25254
|
-
/* ----------------------- min/max & flexibility sync ---------------- */
|
|
25255
|
-
React.useEffect(
|
|
25256
|
-
function () {
|
|
25257
|
-
dispatch(setMinDate(effectiveMinDate.toISOString()));
|
|
25258
|
-
dispatch(setMaxDate(effectiveMaxDate.toISOString()));
|
|
25259
|
-
},
|
|
25260
|
-
[dispatch, effectiveMinDate, effectiveMaxDate]
|
|
25261
|
-
);
|
|
25262
|
-
React.useEffect(
|
|
25263
|
-
function () {
|
|
25264
|
-
if (dateFlexibility.length) {
|
|
25265
|
-
dispatch(setDateFlexibility(dateFlexibility));
|
|
25266
|
-
}
|
|
25267
|
-
},
|
|
25268
|
-
[dispatch, JSON.stringify(dateFlexibility)]
|
|
25269
|
-
);
|
|
25270
|
-
/* =================== SINGLE DATE (only departure) ================= */
|
|
25271
|
-
if (isSingleDate) {
|
|
25272
|
-
return React__default['default'].createElement(
|
|
25273
|
-
'div',
|
|
25274
|
-
{ className: 'qsm__double-input', ref: dateInputWrapperRef },
|
|
25275
|
-
React__default['default'].createElement(
|
|
25276
|
-
'div',
|
|
25277
|
-
{
|
|
25278
|
-
className: 'qsm__input-wrapper',
|
|
25279
|
-
onClick: function () {
|
|
25280
|
-
if (isSmallScreen) {
|
|
25281
|
-
dispatch(setMobileDatePickerMode('single'));
|
|
25282
|
-
dispatch(setMobileFilterType('date'));
|
|
25283
|
-
} else {
|
|
25284
|
-
setIsSingleOpen(true);
|
|
25285
|
-
}
|
|
25286
|
-
}
|
|
25287
|
-
},
|
|
25288
|
-
datesIcon && React__default['default'].createElement('span', { className: 'qsm__input-icon' }, datesIcon),
|
|
25289
|
-
React__default['default'].createElement('label', { className: 'qsm__label' }, 'Vertrek'),
|
|
25290
|
-
React__default['default'].createElement('input', {
|
|
25291
|
-
type: 'text',
|
|
25292
|
-
className: 'qsm__input u-ps-2',
|
|
25293
|
-
placeholder: 'Datum',
|
|
25294
|
-
readOnly: true,
|
|
25295
|
-
value: fromDate ? dateFns.format(new Date(fromDate), 'dd/MM/yyyy') : ''
|
|
25296
|
-
})
|
|
25297
|
-
),
|
|
25298
|
-
!isSmallScreen &&
|
|
25299
|
-
isSingleOpen &&
|
|
25300
|
-
React__default['default'].createElement(
|
|
25301
|
-
'div',
|
|
25302
|
-
{ className: 'qsm__datepicker-popover', ref: dateInputRef },
|
|
25303
|
-
React__default['default'].createElement(DateRangePicker, {
|
|
25304
|
-
fromDate: fromDate ? new Date(fromDate) : undefined,
|
|
25305
|
-
onSelectionChange: function (from) {
|
|
25306
|
-
dispatch(setFromDate(from ? from.toISOString() : undefined));
|
|
25307
|
-
dispatch(setToDate(undefined));
|
|
25308
|
-
},
|
|
25309
|
-
onRequestClose: function () {
|
|
25310
|
-
return setIsSingleOpen(false);
|
|
25311
|
-
},
|
|
25312
|
-
isSingleDate: true
|
|
25313
|
-
})
|
|
25314
|
-
)
|
|
25315
|
-
);
|
|
25316
|
-
}
|
|
25317
|
-
/* ======================== RANGE PICKER ============================= */
|
|
25318
|
-
var handleFromDateClick = function () {
|
|
25319
|
-
if (isSmallScreen) {
|
|
25320
|
-
dispatch(setMobileDatePickerMode('range'));
|
|
25321
|
-
dispatch(setMobileFilterType('date'));
|
|
25322
|
-
} else {
|
|
25323
|
-
setIsOpen(true);
|
|
25324
|
-
}
|
|
25325
|
-
};
|
|
25326
|
-
return React__default['default'].createElement(
|
|
25327
|
-
'div',
|
|
25328
|
-
{ className: 'qsm__double-input', ref: dateInputWrapperRef },
|
|
25329
|
-
React__default['default'].createElement(
|
|
25330
|
-
'label',
|
|
25331
|
-
{ className: 'qsm__input-wrapper', onClick: handleFromDateClick },
|
|
25332
|
-
datesIcon && React__default['default'].createElement('span', { className: 'qsm__input-icon' }, datesIcon),
|
|
25333
|
-
React__default['default'].createElement('span', { className: 'qsm__label' }, 'Vertrek'),
|
|
25334
|
-
React__default['default'].createElement('input', {
|
|
25335
|
-
type: 'text',
|
|
25336
|
-
id: 'vertrek',
|
|
25337
|
-
className: 'qsm__input u-ps-2',
|
|
25338
|
-
placeholder: 'Datum',
|
|
25339
|
-
readOnly: true,
|
|
25340
|
-
value: fromDate ? dateFns.format(new Date(fromDate), 'dd/MM/yyyy') : ''
|
|
25341
|
-
}),
|
|
25342
|
-
React__default['default'].createElement('div', { className: 'qsm__input-line qsm__input-line--datepicker' })
|
|
25343
|
-
),
|
|
25344
|
-
React__default['default'].createElement(
|
|
25345
|
-
'label',
|
|
25346
|
-
{ className: 'qsm__input-wrapper', onClick: handleFromDateClick },
|
|
25347
|
-
datesIcon && React__default['default'].createElement('span', { className: 'qsm__input-icon' }, datesIcon),
|
|
25348
|
-
React__default['default'].createElement('span', { className: 'qsm__label qsm__label--second-input-label' }, 'Retour'),
|
|
25349
|
-
React__default['default'].createElement('input', {
|
|
25350
|
-
type: 'text',
|
|
25351
|
-
id: 'retour',
|
|
25352
|
-
className: 'qsm__input',
|
|
25353
|
-
placeholder: 'Datum',
|
|
25354
|
-
readOnly: true,
|
|
25355
|
-
value: toDate ? dateFns.format(new Date(toDate), 'dd/MM/yyyy') : ''
|
|
25356
|
-
})
|
|
25357
|
-
),
|
|
25358
|
-
isOpen &&
|
|
25359
|
-
!isSmallScreen &&
|
|
25360
|
-
React__default['default'].createElement(
|
|
25361
|
-
'div',
|
|
25362
|
-
{ className: 'qsm__datepicker-popover', ref: dateInputRef },
|
|
25363
|
-
React__default['default'].createElement(DateRangePicker, {
|
|
25364
|
-
fromDate: fromDate ? new Date(fromDate) : undefined,
|
|
25365
|
-
toDate: toDate ? new Date(toDate) : undefined,
|
|
25366
|
-
onSelectionChange: function (from, to) {
|
|
25367
|
-
dispatch(setFromDate(from ? from.toISOString() : undefined));
|
|
25368
|
-
dispatch(setToDate(to ? to.toISOString() : undefined));
|
|
25369
|
-
},
|
|
25370
|
-
onRequestClose: function () {
|
|
25371
|
-
return setIsOpen(false);
|
|
25372
|
-
}
|
|
25373
|
-
})
|
|
25374
|
-
)
|
|
25375
|
-
);
|
|
25376
|
-
};
|
|
25377
|
-
|
|
25378
25205
|
var selectTravelerSummary = function (state, areTravelersInRooms) {
|
|
25379
25206
|
var _a = state.qsm,
|
|
25380
25207
|
adults = _a.adults,
|
|
@@ -25498,11 +25325,7 @@ var ItemPicker$1 = function (_a) {
|
|
|
25498
25325
|
var _b = React.useState(false),
|
|
25499
25326
|
isDropdownOpen = _b[0],
|
|
25500
25327
|
setIsDropdownOpen = _b[1];
|
|
25501
|
-
var _c = React.useState('down'),
|
|
25502
|
-
openDirection = _c[0],
|
|
25503
|
-
setOpenDirection = _c[1];
|
|
25504
25328
|
var dropdownRef = React.useRef(null);
|
|
25505
|
-
var dropdownMenuRef = React.useRef(null);
|
|
25506
25329
|
var toggleButtonRef = React.useRef(null);
|
|
25507
25330
|
var handlePick = function (picked) {
|
|
25508
25331
|
setIsDropdownOpen(false);
|
|
@@ -25519,19 +25342,6 @@ var ItemPicker$1 = function (_a) {
|
|
|
25519
25342
|
document.removeEventListener('mousedown', handleClickOutside);
|
|
25520
25343
|
};
|
|
25521
25344
|
}, []);
|
|
25522
|
-
React.useEffect(
|
|
25523
|
-
function () {
|
|
25524
|
-
var _a, _b;
|
|
25525
|
-
if (isDropdownOpen && toggleButtonRef.current) {
|
|
25526
|
-
var buttonRect = toggleButtonRef.current.getBoundingClientRect();
|
|
25527
|
-
var spaceBelow = window.innerHeight - buttonRect.bottom;
|
|
25528
|
-
var spaceAbove = buttonRect.top;
|
|
25529
|
-
var dropdownHeight = (_b = (_a = dropdownMenuRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) !== null && _b !== void 0 ? _b : 16;
|
|
25530
|
-
setOpenDirection(spaceBelow < dropdownHeight && spaceAbove > spaceBelow ? 'up' : 'down');
|
|
25531
|
-
}
|
|
25532
|
-
},
|
|
25533
|
-
[isDropdownOpen]
|
|
25534
|
-
);
|
|
25535
25345
|
return React__default['default'].createElement(
|
|
25536
25346
|
'div',
|
|
25537
25347
|
{ className: 'dropdown__input ' + classModifier },
|
|
@@ -25556,7 +25366,7 @@ var ItemPicker$1 = function (_a) {
|
|
|
25556
25366
|
isDropdownOpen &&
|
|
25557
25367
|
React__default['default'].createElement(
|
|
25558
25368
|
'ul',
|
|
25559
|
-
{ className: 'dropdown-menu
|
|
25369
|
+
{ className: 'dropdown-menu' },
|
|
25560
25370
|
items.map(function (_a) {
|
|
25561
25371
|
var label = _a.label,
|
|
25562
25372
|
icon = _a.icon;
|
|
@@ -25625,17 +25435,97 @@ var TravelNationalityPicker = function () {
|
|
|
25625
25435
|
};
|
|
25626
25436
|
|
|
25627
25437
|
var QSMContainer = function () {
|
|
25438
|
+
var dispatch = reactRedux.useDispatch();
|
|
25628
25439
|
var isMobile = useMediaQuery('(max-width: 768px)');
|
|
25629
|
-
var
|
|
25630
|
-
return state.qsm
|
|
25440
|
+
var qsmState = reactRedux.useSelector(function (state) {
|
|
25441
|
+
return state.qsm;
|
|
25631
25442
|
});
|
|
25443
|
+
var mobileFilterType = qsmState.mobileFilterType,
|
|
25444
|
+
fromDate = qsmState.fromDate,
|
|
25445
|
+
toDate = qsmState.toDate;
|
|
25632
25446
|
var _a = React.useContext(QSMConfigurationContext),
|
|
25633
25447
|
searchFields = _a.searchFields,
|
|
25634
25448
|
askTravelers = _a.askTravelers,
|
|
25635
25449
|
submitIcon = _a.submitIcon,
|
|
25636
25450
|
submitLabel = _a.submitLabel,
|
|
25637
25451
|
onSubmit = _a.onSubmit;
|
|
25638
|
-
|
|
25452
|
+
React.useEffect(
|
|
25453
|
+
function () {
|
|
25454
|
+
if (fromDate || toDate) return;
|
|
25455
|
+
var startDate = dateFns.addMonths(new Date(), 1);
|
|
25456
|
+
var endDate = dateFns.addDays(startDate, 7);
|
|
25457
|
+
dispatch(setFromDate(startDate.toISOString()));
|
|
25458
|
+
dispatch(setToDate(endDate.toISOString()));
|
|
25459
|
+
},
|
|
25460
|
+
[fromDate, toDate, dispatch]
|
|
25461
|
+
);
|
|
25462
|
+
var dateRange = React.useMemo(
|
|
25463
|
+
function () {
|
|
25464
|
+
if (!fromDate || !toDate) return undefined;
|
|
25465
|
+
return {
|
|
25466
|
+
fromDate: new Date(fromDate),
|
|
25467
|
+
toDate: new Date(toDate)
|
|
25468
|
+
};
|
|
25469
|
+
},
|
|
25470
|
+
[fromDate, toDate]
|
|
25471
|
+
);
|
|
25472
|
+
var handleDateChange = function (value) {
|
|
25473
|
+
var _a, _b;
|
|
25474
|
+
dispatch(setFromDate((_a = value.fromDate) === null || _a === void 0 ? void 0 : _a.toISOString()));
|
|
25475
|
+
dispatch(setToDate((_b = value.toDate) === null || _b === void 0 ? void 0 : _b.toISOString()));
|
|
25476
|
+
};
|
|
25477
|
+
var handleSubmit = function () {
|
|
25478
|
+
if (!onSubmit) return;
|
|
25479
|
+
var selectedOrigin = qsmState.selectedOrigin,
|
|
25480
|
+
selectedDestination = qsmState.selectedDestination,
|
|
25481
|
+
selectedAirport = qsmState.selectedAirport,
|
|
25482
|
+
fromDate = qsmState.fromDate,
|
|
25483
|
+
toDate = qsmState.toDate,
|
|
25484
|
+
travelers = qsmState.travelers,
|
|
25485
|
+
selectedTravelClass = qsmState.selectedTravelClass,
|
|
25486
|
+
selectedTravelType = qsmState.selectedTravelType,
|
|
25487
|
+
selectedNationality = qsmState.selectedNationality,
|
|
25488
|
+
adults = qsmState.adults,
|
|
25489
|
+
kids = qsmState.kids,
|
|
25490
|
+
babies = qsmState.babies,
|
|
25491
|
+
rooms = qsmState.rooms,
|
|
25492
|
+
selectedFlexRange = qsmState.selectedFlexRange,
|
|
25493
|
+
language = qsmState.language;
|
|
25494
|
+
var payload = {
|
|
25495
|
+
selectedOrigin: selectedOrigin,
|
|
25496
|
+
selectedDestination: selectedDestination,
|
|
25497
|
+
selectedAirport: selectedAirport,
|
|
25498
|
+
fromDate: fromDate,
|
|
25499
|
+
toDate: toDate,
|
|
25500
|
+
travelers: travelers,
|
|
25501
|
+
travelClass: selectedTravelClass,
|
|
25502
|
+
travelType: selectedTravelType,
|
|
25503
|
+
nationality: selectedNationality,
|
|
25504
|
+
adults: adults,
|
|
25505
|
+
kids: kids,
|
|
25506
|
+
babies: babies,
|
|
25507
|
+
rooms: rooms,
|
|
25508
|
+
dateFlexibility: selectedFlexRange,
|
|
25509
|
+
language: language
|
|
25510
|
+
};
|
|
25511
|
+
addSearchFieldsToPayload(payload, searchFields, qsmState);
|
|
25512
|
+
onSubmit(payload);
|
|
25513
|
+
};
|
|
25514
|
+
var addSearchFieldsToPayload = function (payload, fields, state) {
|
|
25515
|
+
fields.forEach(function (field) {
|
|
25516
|
+
if (field.type === 'single') {
|
|
25517
|
+
var key = field.fieldKey;
|
|
25518
|
+
payload[key] = state[key];
|
|
25519
|
+
}
|
|
25520
|
+
if (field.type === 'double' && field.fields) {
|
|
25521
|
+
// recursively add each nested field
|
|
25522
|
+
field.fields.forEach(function (nestedField) {
|
|
25523
|
+
var key = nestedField.fieldKey;
|
|
25524
|
+
payload[key] = state[key];
|
|
25525
|
+
});
|
|
25526
|
+
}
|
|
25527
|
+
});
|
|
25528
|
+
};
|
|
25639
25529
|
return React__default['default'].createElement(
|
|
25640
25530
|
'div',
|
|
25641
25531
|
{ className: 'qsm' },
|
|
@@ -25757,6 +25647,8 @@ var QSMContainer = function () {
|
|
|
25757
25647
|
// onBlur={formik.handleBlur}
|
|
25758
25648
|
value: '',
|
|
25759
25649
|
// checked={formik.values.mainBookerId === travelerValues.id}
|
|
25650
|
+
checked: true,
|
|
25651
|
+
readOnly: true,
|
|
25760
25652
|
className: 'radiobutton__input'
|
|
25761
25653
|
}),
|
|
25762
25654
|
React__default['default'].createElement('span', null, 'One accommodation')
|
|
@@ -25775,7 +25667,8 @@ var QSMContainer = function () {
|
|
|
25775
25667
|
// onBlur={formik.handleBlur}
|
|
25776
25668
|
value: '',
|
|
25777
25669
|
// checked={formik.values.mainBookerId === travelerValues.id}
|
|
25778
|
-
className: 'radiobutton__input'
|
|
25670
|
+
className: 'radiobutton__input',
|
|
25671
|
+
disabled: true
|
|
25779
25672
|
}),
|
|
25780
25673
|
React__default['default'].createElement('span', null, 'Multiple accommodations')
|
|
25781
25674
|
)
|
|
@@ -25798,11 +25691,11 @@ var QSMContainer = function () {
|
|
|
25798
25691
|
}
|
|
25799
25692
|
return React__default['default'].createElement(SearchInputGroup, { key: idx, fieldKey: field.fieldKey });
|
|
25800
25693
|
}),
|
|
25801
|
-
React__default['default'].createElement(
|
|
25694
|
+
React__default['default'].createElement(Dates, { value: dateRange, onChange: handleDateChange }),
|
|
25802
25695
|
askTravelers && React__default['default'].createElement(TravelInputGroup, null),
|
|
25803
25696
|
React__default['default'].createElement(
|
|
25804
25697
|
'button',
|
|
25805
|
-
{ type: 'button', className: 'cta', onClick:
|
|
25698
|
+
{ type: 'button', className: 'cta', onClick: handleSubmit },
|
|
25806
25699
|
submitIcon && submitIcon.toString().length > 0 && React__default['default'].createElement('span', null, submitIcon),
|
|
25807
25700
|
React__default['default'].createElement('span', null, submitLabel)
|
|
25808
25701
|
)
|
|
@@ -44,6 +44,7 @@ export interface BaseFieldConfig {
|
|
|
44
44
|
label: string;
|
|
45
45
|
placeholder: string;
|
|
46
46
|
options: TypeaheadOption[];
|
|
47
|
+
autoComplete?: boolean;
|
|
47
48
|
}
|
|
48
49
|
export interface TypeaheadOption {
|
|
49
50
|
key: string;
|
|
@@ -97,6 +98,7 @@ export interface TravelType {
|
|
|
97
98
|
icon?: ReactNode;
|
|
98
99
|
}
|
|
99
100
|
export interface TravelClass {
|
|
101
|
+
id: number;
|
|
100
102
|
label: string;
|
|
101
103
|
icon?: ReactNode;
|
|
102
104
|
}
|
package/build/build-esm/index.js
CHANGED
|
@@ -22934,11 +22934,11 @@ var setMobileFilterType = _a$1.setMobileFilterType,
|
|
|
22934
22934
|
setActiveSearchFieldProps = _a$1.setActiveSearchFieldProps,
|
|
22935
22935
|
setSearchResults = _a$1.setSearchResults;
|
|
22936
22936
|
_a$1.setLanguage;
|
|
22937
|
-
|
|
22938
|
-
|
|
22939
|
-
|
|
22940
|
-
|
|
22941
|
-
|
|
22937
|
+
_a$1.setMobileDatePickerMode;
|
|
22938
|
+
_a$1.setMinDate;
|
|
22939
|
+
_a$1.setMaxDate;
|
|
22940
|
+
_a$1.setDateFlexibility;
|
|
22941
|
+
var setSelectedFlexRange = _a$1.setSelectedFlexRange;
|
|
22942
22942
|
_a$1.setTravelTypes;
|
|
22943
22943
|
var setSelectedTravelType = _a$1.setSelectedTravelType;
|
|
22944
22944
|
_a$1.setTravelClasses;
|
|
@@ -24721,7 +24721,8 @@ var SearchInputGroup = function (_a) {
|
|
|
24721
24721
|
}
|
|
24722
24722
|
var label = config.label,
|
|
24723
24723
|
placeholder = config.placeholder,
|
|
24724
|
-
options = config.options
|
|
24724
|
+
options = config.options,
|
|
24725
|
+
autoComplete = config.autoComplete;
|
|
24725
24726
|
var selector = useMemo(
|
|
24726
24727
|
function () {
|
|
24727
24728
|
return function (state) {
|
|
@@ -24754,7 +24755,7 @@ var SearchInputGroup = function (_a) {
|
|
|
24754
24755
|
dispatch(setFieldValue({ fieldKey: fieldKey, value: input }));
|
|
24755
24756
|
dispatch(setSearchResults([]));
|
|
24756
24757
|
if (small) return;
|
|
24757
|
-
if (input.length === 3) {
|
|
24758
|
+
if (input.length === 3 && autoComplete) {
|
|
24758
24759
|
var exactIataMatch = findExactIataMatch(options, input);
|
|
24759
24760
|
if (exactIataMatch) {
|
|
24760
24761
|
dispatch(setFieldValue({ fieldKey: fieldKey, value: exactIataMatch.value }));
|
|
@@ -25030,180 +25031,6 @@ var DoubleSearchInputGroup = function (_a) {
|
|
|
25030
25031
|
);
|
|
25031
25032
|
};
|
|
25032
25033
|
|
|
25033
|
-
var DatePicker = function () {
|
|
25034
|
-
var dispatch = useDispatch();
|
|
25035
|
-
var isSmallScreen = useMediaQuery('(max-width: 768px)');
|
|
25036
|
-
/* 🔑 STATE FIRST (no TDZ issues) */
|
|
25037
|
-
var _a = useState(false),
|
|
25038
|
-
isOpen = _a[0],
|
|
25039
|
-
setIsOpen = _a[1]; // range pop-over
|
|
25040
|
-
var _b = useState(false),
|
|
25041
|
-
isSingleOpen = _b[0],
|
|
25042
|
-
setIsSingleOpen = _b[1]; // single pop-over
|
|
25043
|
-
var _c = useContext(QSMConfigurationContext),
|
|
25044
|
-
datesIcon = _c.datesIcon,
|
|
25045
|
-
_d = _c.showReturnDate,
|
|
25046
|
-
showReturnDate = _d === void 0 ? true : _d,
|
|
25047
|
-
minDate = _c.minDate,
|
|
25048
|
-
maxDate = _c.maxDate,
|
|
25049
|
-
_e = _c.dateFlexibility,
|
|
25050
|
-
dateFlexibility = _e === void 0 ? [] : _e;
|
|
25051
|
-
var isSingleDate = !showReturnDate;
|
|
25052
|
-
var dateInputWrapperRef = useRef(null);
|
|
25053
|
-
var dateInputRef = useRef(null);
|
|
25054
|
-
var today = startOfDay(new Date());
|
|
25055
|
-
var effectiveMinDate = minDate !== null && minDate !== void 0 ? minDate : today;
|
|
25056
|
-
var effectiveMaxDate = maxDate !== null && maxDate !== void 0 ? maxDate : addYears(today, 1);
|
|
25057
|
-
var _f = useSelector(function (state) {
|
|
25058
|
-
return {
|
|
25059
|
-
fromDate: state.qsm.fromDate,
|
|
25060
|
-
toDate: state.qsm.toDate
|
|
25061
|
-
};
|
|
25062
|
-
}),
|
|
25063
|
-
fromDate = _f.fromDate,
|
|
25064
|
-
toDate = _f.toDate;
|
|
25065
|
-
/* ----------------------- outside click close ----------------------- */
|
|
25066
|
-
useEffect(function () {
|
|
25067
|
-
var handleClickOutside = function (event) {
|
|
25068
|
-
if (
|
|
25069
|
-
dateInputWrapperRef.current &&
|
|
25070
|
-
!dateInputWrapperRef.current.contains(event.target) &&
|
|
25071
|
-
dateInputRef.current &&
|
|
25072
|
-
!dateInputRef.current.contains(event.target)
|
|
25073
|
-
) {
|
|
25074
|
-
setIsOpen(false);
|
|
25075
|
-
setIsSingleOpen(false);
|
|
25076
|
-
}
|
|
25077
|
-
};
|
|
25078
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
25079
|
-
return function () {
|
|
25080
|
-
return document.removeEventListener('mousedown', handleClickOutside);
|
|
25081
|
-
};
|
|
25082
|
-
}, []);
|
|
25083
|
-
/* ----------------------- min/max & flexibility sync ---------------- */
|
|
25084
|
-
useEffect(
|
|
25085
|
-
function () {
|
|
25086
|
-
dispatch(setMinDate(effectiveMinDate.toISOString()));
|
|
25087
|
-
dispatch(setMaxDate(effectiveMaxDate.toISOString()));
|
|
25088
|
-
},
|
|
25089
|
-
[dispatch, effectiveMinDate, effectiveMaxDate]
|
|
25090
|
-
);
|
|
25091
|
-
useEffect(
|
|
25092
|
-
function () {
|
|
25093
|
-
if (dateFlexibility.length) {
|
|
25094
|
-
dispatch(setDateFlexibility(dateFlexibility));
|
|
25095
|
-
}
|
|
25096
|
-
},
|
|
25097
|
-
[dispatch, JSON.stringify(dateFlexibility)]
|
|
25098
|
-
);
|
|
25099
|
-
/* =================== SINGLE DATE (only departure) ================= */
|
|
25100
|
-
if (isSingleDate) {
|
|
25101
|
-
return React.createElement(
|
|
25102
|
-
'div',
|
|
25103
|
-
{ className: 'qsm__double-input', ref: dateInputWrapperRef },
|
|
25104
|
-
React.createElement(
|
|
25105
|
-
'div',
|
|
25106
|
-
{
|
|
25107
|
-
className: 'qsm__input-wrapper',
|
|
25108
|
-
onClick: function () {
|
|
25109
|
-
if (isSmallScreen) {
|
|
25110
|
-
dispatch(setMobileDatePickerMode('single'));
|
|
25111
|
-
dispatch(setMobileFilterType('date'));
|
|
25112
|
-
} else {
|
|
25113
|
-
setIsSingleOpen(true);
|
|
25114
|
-
}
|
|
25115
|
-
}
|
|
25116
|
-
},
|
|
25117
|
-
datesIcon && React.createElement('span', { className: 'qsm__input-icon' }, datesIcon),
|
|
25118
|
-
React.createElement('label', { className: 'qsm__label' }, 'Vertrek'),
|
|
25119
|
-
React.createElement('input', {
|
|
25120
|
-
type: 'text',
|
|
25121
|
-
className: 'qsm__input u-ps-2',
|
|
25122
|
-
placeholder: 'Datum',
|
|
25123
|
-
readOnly: true,
|
|
25124
|
-
value: fromDate ? format$1(new Date(fromDate), 'dd/MM/yyyy') : ''
|
|
25125
|
-
})
|
|
25126
|
-
),
|
|
25127
|
-
!isSmallScreen &&
|
|
25128
|
-
isSingleOpen &&
|
|
25129
|
-
React.createElement(
|
|
25130
|
-
'div',
|
|
25131
|
-
{ className: 'qsm__datepicker-popover', ref: dateInputRef },
|
|
25132
|
-
React.createElement(DateRangePicker, {
|
|
25133
|
-
fromDate: fromDate ? new Date(fromDate) : undefined,
|
|
25134
|
-
onSelectionChange: function (from) {
|
|
25135
|
-
dispatch(setFromDate(from ? from.toISOString() : undefined));
|
|
25136
|
-
dispatch(setToDate(undefined));
|
|
25137
|
-
},
|
|
25138
|
-
onRequestClose: function () {
|
|
25139
|
-
return setIsSingleOpen(false);
|
|
25140
|
-
},
|
|
25141
|
-
isSingleDate: true
|
|
25142
|
-
})
|
|
25143
|
-
)
|
|
25144
|
-
);
|
|
25145
|
-
}
|
|
25146
|
-
/* ======================== RANGE PICKER ============================= */
|
|
25147
|
-
var handleFromDateClick = function () {
|
|
25148
|
-
if (isSmallScreen) {
|
|
25149
|
-
dispatch(setMobileDatePickerMode('range'));
|
|
25150
|
-
dispatch(setMobileFilterType('date'));
|
|
25151
|
-
} else {
|
|
25152
|
-
setIsOpen(true);
|
|
25153
|
-
}
|
|
25154
|
-
};
|
|
25155
|
-
return React.createElement(
|
|
25156
|
-
'div',
|
|
25157
|
-
{ className: 'qsm__double-input', ref: dateInputWrapperRef },
|
|
25158
|
-
React.createElement(
|
|
25159
|
-
'label',
|
|
25160
|
-
{ className: 'qsm__input-wrapper', onClick: handleFromDateClick },
|
|
25161
|
-
datesIcon && React.createElement('span', { className: 'qsm__input-icon' }, datesIcon),
|
|
25162
|
-
React.createElement('span', { className: 'qsm__label' }, 'Vertrek'),
|
|
25163
|
-
React.createElement('input', {
|
|
25164
|
-
type: 'text',
|
|
25165
|
-
id: 'vertrek',
|
|
25166
|
-
className: 'qsm__input u-ps-2',
|
|
25167
|
-
placeholder: 'Datum',
|
|
25168
|
-
readOnly: true,
|
|
25169
|
-
value: fromDate ? format$1(new Date(fromDate), 'dd/MM/yyyy') : ''
|
|
25170
|
-
}),
|
|
25171
|
-
React.createElement('div', { className: 'qsm__input-line qsm__input-line--datepicker' })
|
|
25172
|
-
),
|
|
25173
|
-
React.createElement(
|
|
25174
|
-
'label',
|
|
25175
|
-
{ className: 'qsm__input-wrapper', onClick: handleFromDateClick },
|
|
25176
|
-
datesIcon && React.createElement('span', { className: 'qsm__input-icon' }, datesIcon),
|
|
25177
|
-
React.createElement('span', { className: 'qsm__label qsm__label--second-input-label' }, 'Retour'),
|
|
25178
|
-
React.createElement('input', {
|
|
25179
|
-
type: 'text',
|
|
25180
|
-
id: 'retour',
|
|
25181
|
-
className: 'qsm__input',
|
|
25182
|
-
placeholder: 'Datum',
|
|
25183
|
-
readOnly: true,
|
|
25184
|
-
value: toDate ? format$1(new Date(toDate), 'dd/MM/yyyy') : ''
|
|
25185
|
-
})
|
|
25186
|
-
),
|
|
25187
|
-
isOpen &&
|
|
25188
|
-
!isSmallScreen &&
|
|
25189
|
-
React.createElement(
|
|
25190
|
-
'div',
|
|
25191
|
-
{ className: 'qsm__datepicker-popover', ref: dateInputRef },
|
|
25192
|
-
React.createElement(DateRangePicker, {
|
|
25193
|
-
fromDate: fromDate ? new Date(fromDate) : undefined,
|
|
25194
|
-
toDate: toDate ? new Date(toDate) : undefined,
|
|
25195
|
-
onSelectionChange: function (from, to) {
|
|
25196
|
-
dispatch(setFromDate(from ? from.toISOString() : undefined));
|
|
25197
|
-
dispatch(setToDate(to ? to.toISOString() : undefined));
|
|
25198
|
-
},
|
|
25199
|
-
onRequestClose: function () {
|
|
25200
|
-
return setIsOpen(false);
|
|
25201
|
-
}
|
|
25202
|
-
})
|
|
25203
|
-
)
|
|
25204
|
-
);
|
|
25205
|
-
};
|
|
25206
|
-
|
|
25207
25034
|
var selectTravelerSummary = function (state, areTravelersInRooms) {
|
|
25208
25035
|
var _a = state.qsm,
|
|
25209
25036
|
adults = _a.adults,
|
|
@@ -25327,11 +25154,7 @@ var ItemPicker$1 = function (_a) {
|
|
|
25327
25154
|
var _b = useState(false),
|
|
25328
25155
|
isDropdownOpen = _b[0],
|
|
25329
25156
|
setIsDropdownOpen = _b[1];
|
|
25330
|
-
var _c = useState('down'),
|
|
25331
|
-
openDirection = _c[0],
|
|
25332
|
-
setOpenDirection = _c[1];
|
|
25333
25157
|
var dropdownRef = useRef(null);
|
|
25334
|
-
var dropdownMenuRef = useRef(null);
|
|
25335
25158
|
var toggleButtonRef = useRef(null);
|
|
25336
25159
|
var handlePick = function (picked) {
|
|
25337
25160
|
setIsDropdownOpen(false);
|
|
@@ -25348,19 +25171,6 @@ var ItemPicker$1 = function (_a) {
|
|
|
25348
25171
|
document.removeEventListener('mousedown', handleClickOutside);
|
|
25349
25172
|
};
|
|
25350
25173
|
}, []);
|
|
25351
|
-
useEffect(
|
|
25352
|
-
function () {
|
|
25353
|
-
var _a, _b;
|
|
25354
|
-
if (isDropdownOpen && toggleButtonRef.current) {
|
|
25355
|
-
var buttonRect = toggleButtonRef.current.getBoundingClientRect();
|
|
25356
|
-
var spaceBelow = window.innerHeight - buttonRect.bottom;
|
|
25357
|
-
var spaceAbove = buttonRect.top;
|
|
25358
|
-
var dropdownHeight = (_b = (_a = dropdownMenuRef.current) === null || _a === void 0 ? void 0 : _a.offsetHeight) !== null && _b !== void 0 ? _b : 16;
|
|
25359
|
-
setOpenDirection(spaceBelow < dropdownHeight && spaceAbove > spaceBelow ? 'up' : 'down');
|
|
25360
|
-
}
|
|
25361
|
-
},
|
|
25362
|
-
[isDropdownOpen]
|
|
25363
|
-
);
|
|
25364
25174
|
return React.createElement(
|
|
25365
25175
|
'div',
|
|
25366
25176
|
{ className: 'dropdown__input ' + classModifier },
|
|
@@ -25385,7 +25195,7 @@ var ItemPicker$1 = function (_a) {
|
|
|
25385
25195
|
isDropdownOpen &&
|
|
25386
25196
|
React.createElement(
|
|
25387
25197
|
'ul',
|
|
25388
|
-
{ className: 'dropdown-menu
|
|
25198
|
+
{ className: 'dropdown-menu' },
|
|
25389
25199
|
items.map(function (_a) {
|
|
25390
25200
|
var label = _a.label,
|
|
25391
25201
|
icon = _a.icon;
|
|
@@ -25454,17 +25264,97 @@ var TravelNationalityPicker = function () {
|
|
|
25454
25264
|
};
|
|
25455
25265
|
|
|
25456
25266
|
var QSMContainer = function () {
|
|
25267
|
+
var dispatch = useDispatch();
|
|
25457
25268
|
var isMobile = useMediaQuery('(max-width: 768px)');
|
|
25458
|
-
var
|
|
25459
|
-
return state.qsm
|
|
25269
|
+
var qsmState = useSelector(function (state) {
|
|
25270
|
+
return state.qsm;
|
|
25460
25271
|
});
|
|
25272
|
+
var mobileFilterType = qsmState.mobileFilterType,
|
|
25273
|
+
fromDate = qsmState.fromDate,
|
|
25274
|
+
toDate = qsmState.toDate;
|
|
25461
25275
|
var _a = useContext(QSMConfigurationContext),
|
|
25462
25276
|
searchFields = _a.searchFields,
|
|
25463
25277
|
askTravelers = _a.askTravelers,
|
|
25464
25278
|
submitIcon = _a.submitIcon,
|
|
25465
25279
|
submitLabel = _a.submitLabel,
|
|
25466
25280
|
onSubmit = _a.onSubmit;
|
|
25467
|
-
|
|
25281
|
+
useEffect(
|
|
25282
|
+
function () {
|
|
25283
|
+
if (fromDate || toDate) return;
|
|
25284
|
+
var startDate = addMonths(new Date(), 1);
|
|
25285
|
+
var endDate = addDays(startDate, 7);
|
|
25286
|
+
dispatch(setFromDate(startDate.toISOString()));
|
|
25287
|
+
dispatch(setToDate(endDate.toISOString()));
|
|
25288
|
+
},
|
|
25289
|
+
[fromDate, toDate, dispatch]
|
|
25290
|
+
);
|
|
25291
|
+
var dateRange = useMemo(
|
|
25292
|
+
function () {
|
|
25293
|
+
if (!fromDate || !toDate) return undefined;
|
|
25294
|
+
return {
|
|
25295
|
+
fromDate: new Date(fromDate),
|
|
25296
|
+
toDate: new Date(toDate)
|
|
25297
|
+
};
|
|
25298
|
+
},
|
|
25299
|
+
[fromDate, toDate]
|
|
25300
|
+
);
|
|
25301
|
+
var handleDateChange = function (value) {
|
|
25302
|
+
var _a, _b;
|
|
25303
|
+
dispatch(setFromDate((_a = value.fromDate) === null || _a === void 0 ? void 0 : _a.toISOString()));
|
|
25304
|
+
dispatch(setToDate((_b = value.toDate) === null || _b === void 0 ? void 0 : _b.toISOString()));
|
|
25305
|
+
};
|
|
25306
|
+
var handleSubmit = function () {
|
|
25307
|
+
if (!onSubmit) return;
|
|
25308
|
+
var selectedOrigin = qsmState.selectedOrigin,
|
|
25309
|
+
selectedDestination = qsmState.selectedDestination,
|
|
25310
|
+
selectedAirport = qsmState.selectedAirport,
|
|
25311
|
+
fromDate = qsmState.fromDate,
|
|
25312
|
+
toDate = qsmState.toDate,
|
|
25313
|
+
travelers = qsmState.travelers,
|
|
25314
|
+
selectedTravelClass = qsmState.selectedTravelClass,
|
|
25315
|
+
selectedTravelType = qsmState.selectedTravelType,
|
|
25316
|
+
selectedNationality = qsmState.selectedNationality,
|
|
25317
|
+
adults = qsmState.adults,
|
|
25318
|
+
kids = qsmState.kids,
|
|
25319
|
+
babies = qsmState.babies,
|
|
25320
|
+
rooms = qsmState.rooms,
|
|
25321
|
+
selectedFlexRange = qsmState.selectedFlexRange,
|
|
25322
|
+
language = qsmState.language;
|
|
25323
|
+
var payload = {
|
|
25324
|
+
selectedOrigin: selectedOrigin,
|
|
25325
|
+
selectedDestination: selectedDestination,
|
|
25326
|
+
selectedAirport: selectedAirport,
|
|
25327
|
+
fromDate: fromDate,
|
|
25328
|
+
toDate: toDate,
|
|
25329
|
+
travelers: travelers,
|
|
25330
|
+
travelClass: selectedTravelClass,
|
|
25331
|
+
travelType: selectedTravelType,
|
|
25332
|
+
nationality: selectedNationality,
|
|
25333
|
+
adults: adults,
|
|
25334
|
+
kids: kids,
|
|
25335
|
+
babies: babies,
|
|
25336
|
+
rooms: rooms,
|
|
25337
|
+
dateFlexibility: selectedFlexRange,
|
|
25338
|
+
language: language
|
|
25339
|
+
};
|
|
25340
|
+
addSearchFieldsToPayload(payload, searchFields, qsmState);
|
|
25341
|
+
onSubmit(payload);
|
|
25342
|
+
};
|
|
25343
|
+
var addSearchFieldsToPayload = function (payload, fields, state) {
|
|
25344
|
+
fields.forEach(function (field) {
|
|
25345
|
+
if (field.type === 'single') {
|
|
25346
|
+
var key = field.fieldKey;
|
|
25347
|
+
payload[key] = state[key];
|
|
25348
|
+
}
|
|
25349
|
+
if (field.type === 'double' && field.fields) {
|
|
25350
|
+
// recursively add each nested field
|
|
25351
|
+
field.fields.forEach(function (nestedField) {
|
|
25352
|
+
var key = nestedField.fieldKey;
|
|
25353
|
+
payload[key] = state[key];
|
|
25354
|
+
});
|
|
25355
|
+
}
|
|
25356
|
+
});
|
|
25357
|
+
};
|
|
25468
25358
|
return React.createElement(
|
|
25469
25359
|
'div',
|
|
25470
25360
|
{ className: 'qsm' },
|
|
@@ -25554,6 +25444,8 @@ var QSMContainer = function () {
|
|
|
25554
25444
|
// onBlur={formik.handleBlur}
|
|
25555
25445
|
value: '',
|
|
25556
25446
|
// checked={formik.values.mainBookerId === travelerValues.id}
|
|
25447
|
+
checked: true,
|
|
25448
|
+
readOnly: true,
|
|
25557
25449
|
className: 'radiobutton__input'
|
|
25558
25450
|
}),
|
|
25559
25451
|
React.createElement('span', null, 'One accommodation')
|
|
@@ -25572,7 +25464,8 @@ var QSMContainer = function () {
|
|
|
25572
25464
|
// onBlur={formik.handleBlur}
|
|
25573
25465
|
value: '',
|
|
25574
25466
|
// checked={formik.values.mainBookerId === travelerValues.id}
|
|
25575
|
-
className: 'radiobutton__input'
|
|
25467
|
+
className: 'radiobutton__input',
|
|
25468
|
+
disabled: true
|
|
25576
25469
|
}),
|
|
25577
25470
|
React.createElement('span', null, 'Multiple accommodations')
|
|
25578
25471
|
)
|
|
@@ -25595,11 +25488,11 @@ var QSMContainer = function () {
|
|
|
25595
25488
|
}
|
|
25596
25489
|
return React.createElement(SearchInputGroup, { key: idx, fieldKey: field.fieldKey });
|
|
25597
25490
|
}),
|
|
25598
|
-
React.createElement(
|
|
25491
|
+
React.createElement(Dates, { value: dateRange, onChange: handleDateChange }),
|
|
25599
25492
|
askTravelers && React.createElement(TravelInputGroup, null),
|
|
25600
25493
|
React.createElement(
|
|
25601
25494
|
'button',
|
|
25602
|
-
{ type: 'button', className: 'cta', onClick:
|
|
25495
|
+
{ type: 'button', className: 'cta', onClick: handleSubmit },
|
|
25603
25496
|
submitIcon && submitIcon.toString().length > 0 && React.createElement('span', null, submitIcon),
|
|
25604
25497
|
React.createElement('span', null, submitLabel)
|
|
25605
25498
|
)
|
|
@@ -44,6 +44,7 @@ export interface BaseFieldConfig {
|
|
|
44
44
|
label: string;
|
|
45
45
|
placeholder: string;
|
|
46
46
|
options: TypeaheadOption[];
|
|
47
|
+
autoComplete?: boolean;
|
|
47
48
|
}
|
|
48
49
|
export interface TypeaheadOption {
|
|
49
50
|
key: string;
|
|
@@ -97,6 +98,7 @@ export interface TravelType {
|
|
|
97
98
|
icon?: ReactNode;
|
|
98
99
|
}
|
|
99
100
|
export interface TravelClass {
|
|
101
|
+
id: number;
|
|
100
102
|
label: string;
|
|
101
103
|
icon?: ReactNode;
|
|
102
104
|
}
|
package/package.json
CHANGED
|
@@ -1,30 +1,111 @@
|
|
|
1
|
-
import React, { useContext } from 'react';
|
|
2
|
-
import { useSelector } from 'react-redux';
|
|
1
|
+
import React, { useContext, useEffect, useMemo } from 'react';
|
|
2
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
3
3
|
import { QSMRootState } from '../../store/qsm-store';
|
|
4
4
|
import QSMConfigurationContext from '../../qsm-configuration-context';
|
|
5
5
|
import useMediaQuery from '../../../shared/utils/use-media-query-util';
|
|
6
6
|
import MobileFilterModal from '../mobile-filter-modal';
|
|
7
7
|
import SearchInputGroup from '../search-input-group';
|
|
8
8
|
import DoubleSearchInputGroup from '../double-search-input-group';
|
|
9
|
-
import
|
|
9
|
+
import Dates from '../../../booking-product/components/dates';
|
|
10
10
|
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
14
|
import TravelNationalityPicker from '../travel-nationality-picker';
|
|
15
|
+
import { addDays, addMonths } from 'date-fns';
|
|
16
|
+
import { DateRange } from '../../../booking-product/types';
|
|
17
|
+
import { setFromDate, setToDate } from '../../store/qsm-slice';
|
|
15
18
|
|
|
16
19
|
const QSMContainer: React.FC = () => {
|
|
20
|
+
const dispatch = useDispatch();
|
|
17
21
|
const isMobile = useMediaQuery('(max-width: 768px)');
|
|
18
|
-
const
|
|
22
|
+
const qsmState = useSelector((state: QSMRootState) => state.qsm);
|
|
23
|
+
const { mobileFilterType, fromDate, toDate } = qsmState;
|
|
24
|
+
const { searchFields, askTravelers, submitIcon, submitLabel, onSubmit } = useContext(QSMConfigurationContext);
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (fromDate || toDate) return;
|
|
28
|
+
|
|
29
|
+
const startDate = addMonths(new Date(), 1);
|
|
30
|
+
const endDate = addDays(startDate, 7);
|
|
31
|
+
|
|
32
|
+
dispatch(setFromDate(startDate.toISOString()));
|
|
33
|
+
dispatch(setToDate(endDate.toISOString()));
|
|
34
|
+
}, [fromDate, toDate, dispatch]);
|
|
35
|
+
|
|
36
|
+
const dateRange = useMemo<DateRange | undefined>(() => {
|
|
37
|
+
if (!fromDate || !toDate) return undefined;
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
fromDate: new Date(fromDate),
|
|
41
|
+
toDate: new Date(toDate)
|
|
42
|
+
};
|
|
43
|
+
}, [fromDate, toDate]);
|
|
44
|
+
|
|
45
|
+
const handleDateChange = (value: DateRange) => {
|
|
46
|
+
dispatch(setFromDate(value.fromDate?.toISOString()));
|
|
47
|
+
dispatch(setToDate(value.toDate?.toISOString()));
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleSubmit = () => {
|
|
51
|
+
if (!onSubmit) return;
|
|
52
|
+
|
|
53
|
+
const {
|
|
54
|
+
selectedOrigin,
|
|
55
|
+
selectedDestination,
|
|
56
|
+
selectedAirport,
|
|
57
|
+
fromDate,
|
|
58
|
+
toDate,
|
|
59
|
+
travelers,
|
|
60
|
+
selectedTravelClass,
|
|
61
|
+
selectedTravelType,
|
|
62
|
+
selectedNationality,
|
|
63
|
+
adults,
|
|
64
|
+
kids,
|
|
65
|
+
babies,
|
|
66
|
+
rooms,
|
|
67
|
+
selectedFlexRange,
|
|
68
|
+
language
|
|
69
|
+
} = qsmState;
|
|
70
|
+
|
|
71
|
+
const payload = {
|
|
72
|
+
selectedOrigin,
|
|
73
|
+
selectedDestination,
|
|
74
|
+
selectedAirport,
|
|
75
|
+
fromDate,
|
|
76
|
+
toDate,
|
|
77
|
+
travelers,
|
|
78
|
+
travelClass: selectedTravelClass,
|
|
79
|
+
travelType: selectedTravelType,
|
|
80
|
+
nationality: selectedNationality,
|
|
81
|
+
adults,
|
|
82
|
+
kids,
|
|
83
|
+
babies,
|
|
84
|
+
rooms,
|
|
85
|
+
dateFlexibility: selectedFlexRange,
|
|
86
|
+
language
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
addSearchFieldsToPayload(payload, searchFields, qsmState);
|
|
90
|
+
onSubmit(payload);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const addSearchFieldsToPayload = (payload: any, fields: typeof searchFields, state: any) => {
|
|
94
|
+
fields.forEach((field) => {
|
|
95
|
+
if (field.type === 'single') {
|
|
96
|
+
const key = field.fieldKey;
|
|
97
|
+
payload[key] = state[key];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (field.type === 'double' && field.fields) {
|
|
101
|
+
// recursively add each nested field
|
|
102
|
+
field.fields.forEach((nestedField) => {
|
|
103
|
+
const key = nestedField.fieldKey;
|
|
104
|
+
payload[key] = state[key];
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
28
109
|
|
|
29
110
|
return (
|
|
30
111
|
<div className="qsm">
|
|
@@ -98,6 +179,8 @@ const QSMContainer: React.FC = () => {
|
|
|
98
179
|
// onBlur={formik.handleBlur}
|
|
99
180
|
value=""
|
|
100
181
|
// checked={formik.values.mainBookerId === travelerValues.id}
|
|
182
|
+
checked={true}
|
|
183
|
+
readOnly
|
|
101
184
|
className="radiobutton__input"
|
|
102
185
|
/>
|
|
103
186
|
<span>One accommodation</span>
|
|
@@ -113,6 +196,7 @@ const QSMContainer: React.FC = () => {
|
|
|
113
196
|
value=""
|
|
114
197
|
// checked={formik.values.mainBookerId === travelerValues.id}
|
|
115
198
|
className="radiobutton__input"
|
|
199
|
+
disabled={true}
|
|
116
200
|
/>
|
|
117
201
|
<span>Multiple accommodations</span>
|
|
118
202
|
</label>
|
|
@@ -132,34 +216,11 @@ const QSMContainer: React.FC = () => {
|
|
|
132
216
|
return <SearchInputGroup key={idx} fieldKey={field.fieldKey} />;
|
|
133
217
|
})}
|
|
134
218
|
|
|
135
|
-
<
|
|
219
|
+
<Dates value={dateRange} onChange={handleDateChange} />
|
|
136
220
|
|
|
137
221
|
{askTravelers && <TravelInputGroup />}
|
|
138
222
|
|
|
139
|
-
|
|
140
|
-
<svg id="qsm-marker-icon" viewBox="0 0 12.974 15.967" className="qsm__input-icon" width={13} height={16}>
|
|
141
|
-
<path
|
|
142
|
-
id="location_on_16dp_UNDEFINED_FILL0_wght400_GRAD0_opsz20"
|
|
143
|
-
d="M174.491-856.016a1.432,1.432,0,0,0,1.056-.441,1.454,1.454,0,0,0,.437-1.06,1.431,1.431,0,0,0-.441-1.056,1.453,1.453,0,0,0-1.06-.437,1.431,1.431,0,0,0-1.056.441,1.453,1.453,0,0,0-.437,1.06,1.431,1.431,0,0,0,.441,1.056A1.453,1.453,0,0,0,174.491-856.016Zm0,6.009a23.088,23.088,0,0,0,3.732-4.1,6.21,6.21,0,0,0,1.258-3.347,4.923,4.923,0,0,0-1.424-3.618,4.819,4.819,0,0,0-3.566-1.435,4.819,4.819,0,0,0-3.566,1.435,4.923,4.923,0,0,0-1.424,3.618,6.21,6.21,0,0,0,1.258,3.347A23.086,23.086,0,0,0,174.487-850.008Zm0,1.975a26.673,26.673,0,0,1-4.875-5.064A7.813,7.813,0,0,1,168-857.451a6.394,6.394,0,0,1,1.85-4.668A6.222,6.222,0,0,1,174.476-864a6.256,6.256,0,0,1,4.636,1.882,6.375,6.375,0,0,1,1.861,4.668,7.8,7.8,0,0,1-1.6,4.345A26.652,26.652,0,0,1,174.487-848.033ZM174.487-857.513Z"
|
|
144
|
-
transform="translate(-168 864)"
|
|
145
|
-
// fill="#707070"
|
|
146
|
-
/>
|
|
147
|
-
</svg>
|
|
148
|
-
|
|
149
|
-
<span className="qsm__label">hotel</span>
|
|
150
|
-
|
|
151
|
-
<input
|
|
152
|
-
type="text"
|
|
153
|
-
// value= 1
|
|
154
|
-
// readOnly={small}
|
|
155
|
-
// onClick={click}
|
|
156
|
-
// onChange={(e) => !small && !readOnlyForced && change(e.target.value)}
|
|
157
|
-
className="qsm__input"
|
|
158
|
-
placeholder="bestemming of hotel"
|
|
159
|
-
/>
|
|
160
|
-
</label> */}
|
|
161
|
-
|
|
162
|
-
<button type="button" className="cta" onClick={onSubmit}>
|
|
223
|
+
<button type="button" className="cta" onClick={handleSubmit}>
|
|
163
224
|
{submitIcon && submitIcon.toString().length > 0 && <span>{submitIcon}</span>}
|
|
164
225
|
<span>{submitLabel}</span>
|
|
165
226
|
</button>
|
|
@@ -15,9 +15,7 @@ const ItemPicker: React.FC<ItemPickerProps> = ({ items, selection, label, placeh
|
|
|
15
15
|
const dispatch = useDispatch();
|
|
16
16
|
|
|
17
17
|
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
|
|
18
|
-
const [openDirection, setOpenDirection] = useState<'down' | 'up'>('down');
|
|
19
18
|
const dropdownRef = useRef<HTMLDivElement | null>(null);
|
|
20
|
-
const dropdownMenuRef = useRef<HTMLUListElement | null>(null);
|
|
21
19
|
const toggleButtonRef = useRef<HTMLButtonElement | null>(null);
|
|
22
20
|
|
|
23
21
|
const handlePick = (picked: string) => {
|
|
@@ -38,16 +36,6 @@ const ItemPicker: React.FC<ItemPickerProps> = ({ items, selection, label, placeh
|
|
|
38
36
|
};
|
|
39
37
|
}, []);
|
|
40
38
|
|
|
41
|
-
useEffect(() => {
|
|
42
|
-
if (isDropdownOpen && toggleButtonRef.current) {
|
|
43
|
-
const buttonRect = toggleButtonRef.current.getBoundingClientRect();
|
|
44
|
-
const spaceBelow = window.innerHeight - buttonRect.bottom;
|
|
45
|
-
const spaceAbove = buttonRect.top;
|
|
46
|
-
const dropdownHeight = dropdownMenuRef.current?.offsetHeight ?? 16;
|
|
47
|
-
setOpenDirection(spaceBelow < dropdownHeight && spaceAbove > spaceBelow ? 'up' : 'down');
|
|
48
|
-
}
|
|
49
|
-
}, [isDropdownOpen]);
|
|
50
|
-
|
|
51
39
|
return (
|
|
52
40
|
<div className={'dropdown__input ' + classModifier}>
|
|
53
41
|
<span className="dropdown__label">{label}</span>
|
|
@@ -60,7 +48,7 @@ const ItemPicker: React.FC<ItemPickerProps> = ({ items, selection, label, placeh
|
|
|
60
48
|
<span className="arrow">▾</span>
|
|
61
49
|
</button>
|
|
62
50
|
{isDropdownOpen && (
|
|
63
|
-
<ul className=
|
|
51
|
+
<ul className="dropdown-menu">
|
|
64
52
|
{items.map(({ label, icon }) => (
|
|
65
53
|
<li
|
|
66
54
|
key={label}
|
|
@@ -49,7 +49,7 @@ const SearchInputGroup: React.FC<Props> = ({
|
|
|
49
49
|
return null;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const { label, placeholder, options } = config;
|
|
52
|
+
const { label, placeholder, options, autoComplete } = config;
|
|
53
53
|
|
|
54
54
|
const selector = useMemo(() => (state: QSMRootState) => ((state.qsm as any)[fieldKey] ?? '') as string, [fieldKey]);
|
|
55
55
|
const value = useSelector(selector);
|
|
@@ -74,7 +74,7 @@ const SearchInputGroup: React.FC<Props> = ({
|
|
|
74
74
|
|
|
75
75
|
if (small) return;
|
|
76
76
|
|
|
77
|
-
if (input.length === 3) {
|
|
77
|
+
if (input.length === 3 && autoComplete) {
|
|
78
78
|
const exactIataMatch = findExactIataMatch(options, input);
|
|
79
79
|
|
|
80
80
|
if (exactIataMatch) {
|
package/src/qsm/types.ts
CHANGED
|
@@ -63,6 +63,7 @@ export interface BaseFieldConfig {
|
|
|
63
63
|
label: string;
|
|
64
64
|
placeholder: string;
|
|
65
65
|
options: TypeaheadOption[];
|
|
66
|
+
autoComplete?: boolean;
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
export interface TypeaheadOption {
|
|
@@ -131,6 +132,7 @@ export interface TravelType {
|
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
export interface TravelClass {
|
|
135
|
+
id: number;
|
|
134
136
|
label: string;
|
|
135
137
|
icon?: ReactNode;
|
|
136
138
|
}
|