mautourco-components 0.2.45 → 0.2.47
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/dist/components/atoms/Inputs/Input/Input.js +1 -1
- package/dist/components/molecules/AgeSelector/AgeSelector.d.ts +20 -0
- package/dist/components/molecules/AgeSelector/AgeSelector.js +84 -0
- package/dist/components/molecules/LocationDropdown/LocationDropdown.js +1 -1
- package/dist/components/organisms/PaxSelector/PaxSelector.d.ts +5 -0
- package/dist/components/organisms/PaxSelector/PaxSelector.js +100 -114
- package/dist/components/organisms/QuoteHeader/QuoteHeader.js +31 -6
- package/dist/components/organisms/RoundTrip/RoundTrip.d.ts +2 -0
- package/dist/components/organisms/RoundTrip/RoundTrip.js +7 -7
- package/dist/components/organisms/SearchBarTransfer/SearchBarTransfer.d.ts +4 -0
- package/dist/components/organisms/SearchBarTransfer/SearchBarTransfer.js +19 -57
- package/dist/components/organisms/Table/columns/booking-columns.js +1 -8
- package/dist/components/organisms/Table/columns/quotation-columns.js +1 -8
- package/dist/components/organisms/TransferLine/TransferLine.d.ts +9 -5
- package/dist/components/organisms/TransferLine/TransferLine.js +52 -35
- package/dist/index.d.ts +19 -16
- package/dist/index.js +3 -1
- package/dist/styles/components/molecule/age-selector.css +216 -0
- package/dist/styles/components/molecule/calendarInput.css +25 -6
- package/dist/styles/components/molecule/location-dropdown.css +16 -4
- package/dist/styles/components/organism/pax-selector.css +27 -189
- package/dist/styles/components/organism/transfer-line.css +40 -0
- package/dist/styles/mautourco.css +1 -0
- package/package.json +1 -1
- package/src/components/atoms/Inputs/Input/Input.tsx +1 -1
- package/src/components/molecules/AgeSelector/AgeSelector.tsx +172 -0
- package/src/components/molecules/LocationDropdown/LocationDropdown.tsx +1 -1
- package/src/components/organisms/PaxSelector/PaxSelector.tsx +132 -208
- package/src/components/organisms/QuoteHeader/QuoteHeader.tsx +37 -6
- package/src/components/organisms/RoundTrip/RoundTrip.tsx +7 -0
- package/src/components/organisms/SearchBarTransfer/SearchBarTransfer.tsx +34 -54
- package/src/components/organisms/Table/columns/booking-columns.tsx +1 -17
- package/src/components/organisms/Table/columns/quotation-columns.tsx +1 -17
- package/src/components/organisms/TransferLine/TransferLine.tsx +107 -85
- package/src/styles/components/molecule/age-selector.css +136 -0
- package/src/styles/components/molecule/calendarInput.css +12 -4
- package/src/styles/components/molecule/location-dropdown.css +9 -2
- package/src/styles/components/organism/pax-selector.css +25 -186
- package/src/styles/components/organism/transfer-line.css +31 -0
|
@@ -11,6 +11,6 @@ var Input = function (_a) {
|
|
|
11
11
|
disabled: 'input-field--disabled',
|
|
12
12
|
};
|
|
13
13
|
var inputClasses = "".concat(baseClasses, " ").concat(variantClasses[variant], " ").concat(icon ? "input-field--with-icon input-field--icon-".concat(iconPosition) : '', " ").concat(className).trim();
|
|
14
|
-
return (_jsxs("div", { className: "input-wrapper ".concat(icon ? 'input-wrapper--with-icon' : '').trim(), children: [icon && iconPosition === 'leading' && (_jsx("span", { className: "input-icon input-icon--leading", children: _jsx(Icon, { name: icon, size: "sm" }) })), _jsx("input", { id: id, type: type, className: inputClasses, placeholder: placeholder, value: value, disabled: disabled || variant === 'disabled',
|
|
14
|
+
return (_jsxs("div", { className: "input-wrapper ".concat(icon ? 'input-wrapper--with-icon' : '').trim(), children: [icon && iconPosition === 'leading' && (_jsx("span", { className: "input-icon input-icon--leading", children: _jsx(Icon, { name: icon, size: "sm" }) })), _jsx("input", { id: id, type: type, className: inputClasses, placeholder: placeholder, value: value, disabled: disabled || variant === 'disabled', onInput: onChange, onFocus: onFocus, onBlur: onBlur }), icon && iconPosition === 'trailing' && (_jsx("span", { className: "input-icon input-icon--trailing", children: _jsx(Icon, { name: icon, size: "sm" }) }))] }));
|
|
15
15
|
};
|
|
16
16
|
export default Input;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '../../../styles/components/molecule/age-selector.css';
|
|
3
|
+
export interface AgeSelectorProps {
|
|
4
|
+
/** Label for the selector */
|
|
5
|
+
label: string;
|
|
6
|
+
/** Current selected age value */
|
|
7
|
+
value: number | undefined;
|
|
8
|
+
/** Callback when age changes */
|
|
9
|
+
onChange: (age: number) => void;
|
|
10
|
+
/** Available age range */
|
|
11
|
+
ageRange: number[];
|
|
12
|
+
/** Whether the field is required */
|
|
13
|
+
required?: boolean;
|
|
14
|
+
/** Additional CSS classes */
|
|
15
|
+
className?: string;
|
|
16
|
+
/** Placeholder text */
|
|
17
|
+
placeholder?: string;
|
|
18
|
+
}
|
|
19
|
+
declare const AgeSelector: React.FC<AgeSelectorProps>;
|
|
20
|
+
export default AgeSelector;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import '../../../styles/components/molecule/age-selector.css';
|
|
4
|
+
import Icon from '../../atoms/Icon/Icon';
|
|
5
|
+
import { Text } from '../../atoms/Typography/Typography';
|
|
6
|
+
var AgeSelector = function (_a) {
|
|
7
|
+
var label = _a.label, value = _a.value, onChange = _a.onChange, ageRange = _a.ageRange, _b = _a.required, required = _b === void 0 ? false : _b, _c = _a.className, className = _c === void 0 ? '' : _c, _d = _a.placeholder, placeholder = _d === void 0 ? '--' : _d;
|
|
8
|
+
var _e = useState(false), isOpen = _e[0], setIsOpen = _e[1];
|
|
9
|
+
var _f = useState(value !== undefined ? value.toString() : ''), inputValue = _f[0], setInputValue = _f[1];
|
|
10
|
+
var containerRef = useRef(null);
|
|
11
|
+
var inputRef = useRef(null);
|
|
12
|
+
// Sync input value when prop value changes
|
|
13
|
+
useEffect(function () {
|
|
14
|
+
setInputValue(value !== undefined ? value.toString() : '');
|
|
15
|
+
}, [value]);
|
|
16
|
+
useEffect(function () {
|
|
17
|
+
var handleClickOutside = function (event) {
|
|
18
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
19
|
+
setIsOpen(false);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
if (isOpen) {
|
|
23
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
24
|
+
}
|
|
25
|
+
return function () {
|
|
26
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
27
|
+
};
|
|
28
|
+
}, [isOpen]);
|
|
29
|
+
var handleInputChange = function (e) {
|
|
30
|
+
var newValue = e.target.value;
|
|
31
|
+
// Only allow numeric input or empty string
|
|
32
|
+
if (newValue === '' || /^\d+$/.test(newValue)) {
|
|
33
|
+
setInputValue(newValue);
|
|
34
|
+
// Only update if it's a valid number within range
|
|
35
|
+
var numValue = parseInt(newValue, 10);
|
|
36
|
+
if (newValue === '') {
|
|
37
|
+
// Allow empty input - don't update onChange
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
else if (!isNaN(numValue) && ageRange.includes(numValue)) {
|
|
41
|
+
onChange(numValue);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
var handleInputBlur = function () {
|
|
46
|
+
// Validate and set to valid value or clear if invalid
|
|
47
|
+
var numValue = parseInt(inputValue, 10);
|
|
48
|
+
if (inputValue === '') {
|
|
49
|
+
// Keep empty if user cleared it
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
else if (isNaN(numValue) || !ageRange.includes(numValue)) {
|
|
53
|
+
// Reset to current value if invalid
|
|
54
|
+
setInputValue(value !== undefined ? value.toString() : '');
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
// Ensure the input value matches the validated value
|
|
58
|
+
setInputValue(numValue.toString());
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var handleInputKeyDown = function (e) {
|
|
62
|
+
var _a;
|
|
63
|
+
if (e.key === 'Enter') {
|
|
64
|
+
e.preventDefault();
|
|
65
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.blur();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
var handleSelect = function (age) {
|
|
69
|
+
var numAge = parseInt(age, 10);
|
|
70
|
+
onChange(numAge);
|
|
71
|
+
setIsOpen(false);
|
|
72
|
+
setInputValue(age);
|
|
73
|
+
};
|
|
74
|
+
var handleDropdownToggle = function () {
|
|
75
|
+
setIsOpen(!isOpen);
|
|
76
|
+
};
|
|
77
|
+
var ageOptions = ageRange.map(function (age) { return age.toString(); });
|
|
78
|
+
return (_jsxs("div", { className: "age-selector ".concat(className), ref: containerRef, children: [_jsxs(Text, { size: "sm", variant: "regular", className: "age-selector__label", children: [label, required && _jsx("span", { className: "age-selector__required", children: " *" })] }), _jsxs("div", { className: "age-selector__container", children: [_jsxs("div", { className: "age-selector__input ".concat(isOpen ? 'age-selector__input--open' : '', " ").concat(value !== undefined ? 'age-selector__input--selected' : 'age-selector__input--default'), children: [_jsx("input", { ref: inputRef, type: "text", inputMode: "numeric", className: "age-selector__input-field", value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleInputKeyDown, onFocus: function () { return setIsOpen(false); }, placeholder: placeholder, "aria-label": "".concat(label, " age") }), _jsx("button", { type: "button", className: "age-selector__dropdown-btn", onClick: function (e) {
|
|
79
|
+
e.preventDefault();
|
|
80
|
+
e.stopPropagation();
|
|
81
|
+
handleDropdownToggle();
|
|
82
|
+
}, "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-label": "Open age dropdown", children: _jsx(Icon, { name: "chevron-down", size: "sm", className: "age-selector__icon ".concat(isOpen ? 'age-selector__icon--open' : '') }) })] }), isOpen && (_jsx("div", { className: "age-selector__dropdown", role: "listbox", children: ageOptions.map(function (age) { return (_jsx("div", { className: "age-selector__option ".concat((value === null || value === void 0 ? void 0 : value.toString()) === age ? 'age-selector__option--selected' : ''), onClick: function () { return handleSelect(age); }, role: "option", "aria-selected": (value === null || value === void 0 ? void 0 : value.toString()) === age, children: age }, age)); }) }))] })] }));
|
|
83
|
+
};
|
|
84
|
+
export default AgeSelector;
|
|
@@ -115,7 +115,7 @@ var LocationDropdown = function (_a) {
|
|
|
115
115
|
var SkeletonOption = function () { return (_jsxs("div", { className: "location-dropdown__option location-dropdown__option--skeleton", children: [_jsx("div", { className: "location-dropdown__skeleton-icon" }), _jsx("div", { className: "location-dropdown__skeleton-text" })] })); };
|
|
116
116
|
// Render skeleton loading state
|
|
117
117
|
var renderSkeletonLoading = function () { return (_jsx("div", { className: "location-dropdown__panel", children: _jsx("div", { className: "location-dropdown__content", style: { maxHeight: "".concat(maxHeight, "px") }, children: _jsx("div", { className: "location-dropdown__options-wrapper", children: _jsx("div", { className: "location-dropdown__group", children: _jsx("div", { className: "location-dropdown__group-options", children: __spreadArray([], Array(5), true).map(function (_, index) { return (_jsx(SkeletonOption, {}, "skeleton-".concat(index))); }) }) }) }) }) })); };
|
|
118
|
-
return (_jsxs("div", { ref: dropdownRef, className: "location-dropdown location-dropdown--".concat(type, " ").concat(className), children: [label && (_jsx("div", { className: "location-dropdown__label", children: _jsx(Text, { size: "sm", variant: "medium", children: label }) })), _jsxs("div", { ref: inputRef, className: "location-dropdown__input location-dropdown__input--".concat(getDropdownState()), onClick: handleToggleDropdown, children: [_jsxs("div", { className: "location-dropdown__input-content", children: [_jsx(Icon, { name: getInputIcon(), size: "sm", className: "location-dropdown__input-icon ".concat(!selectedOption ? 'location-dropdown__input-icon--placeholder' : '') }), _jsx("span", { className: "location-dropdown__input-text ".concat(!selectedOption ? 'location-dropdown__input-text--placeholder' : ''), children: displayText })] }), _jsx(Icon, { name: "chevron-down", size: "sm", className: "location-dropdown__input-chevron" })] }), isOpen &&
|
|
118
|
+
return (_jsxs("div", { ref: dropdownRef, className: "location-dropdown location-dropdown--".concat(type, " ").concat(disabled ? 'location-dropdown--disabled' : '', " ").concat(className), children: [label && (_jsx("div", { className: "location-dropdown__label", children: _jsx(Text, { size: "sm", variant: "medium", children: label }) })), _jsxs("div", { ref: inputRef, className: "location-dropdown__input location-dropdown__input--".concat(getDropdownState()), onClick: handleToggleDropdown, children: [_jsxs("div", { className: "location-dropdown__input-content", children: [_jsx(Icon, { name: getInputIcon(), size: "sm", className: "location-dropdown__input-icon ".concat(!selectedOption ? 'location-dropdown__input-icon--placeholder' : '') }), _jsx("span", { className: "location-dropdown__input-text ".concat(!selectedOption ? 'location-dropdown__input-text--placeholder' : ''), children: displayText })] }), _jsx(Icon, { name: "chevron-down", size: "sm", className: "location-dropdown__input-chevron" })] }), isOpen &&
|
|
119
119
|
(loading ? (renderSkeletonLoading()) : (_jsx("div", { className: "location-dropdown__panel", children: _jsx("div", { className: "location-dropdown__content", style: { maxHeight: "".concat(maxHeight, "px") }, children: _jsx("div", { className: "location-dropdown__options-wrapper", children: allOptions.map(function (group, groupIndex) { return (_jsxs("div", { className: "location-dropdown__group", children: [showGroupTitles && group.label && groups.length > 0 && (_jsxs(_Fragment, { children: [groupIndex > 0 && _jsx("div", { className: "location-dropdown__divider" }), _jsx("div", { className: "location-dropdown__group-header", children: _jsx(Text, { size: "xs", variant: "bold", children: group.label }) })] })), _jsx("div", { className: "location-dropdown__group-options", children: group.options.map(function (option) {
|
|
120
120
|
var isSelected = selectedValue === option.id;
|
|
121
121
|
var isDisabled = option.disabled || disabled;
|
|
@@ -58,9 +58,14 @@ export interface PaxSelectorProps {
|
|
|
58
58
|
onRemoveRoom?: (roomId: string) => void;
|
|
59
59
|
/** Default pax data for single room mode (will trigger onChange on mount) */
|
|
60
60
|
defaultPaxData?: PaxData;
|
|
61
|
+
/** Whether the selector is disabled */
|
|
62
|
+
disabled?: boolean;
|
|
61
63
|
/** Whether to scroll to the input when the dropdown opens */
|
|
62
64
|
scrollOnOpen?: boolean;
|
|
65
|
+
/** Age range for child categories */
|
|
66
|
+
ageRange?: number[];
|
|
63
67
|
}
|
|
64
68
|
export declare const DEFAULT_PAX_DATA_WITH_ADULTS: PaxData;
|
|
69
|
+
export declare const CHILD_CATEGORY_AGES: number[];
|
|
65
70
|
declare const PaxSelector: React.FC<PaxSelectorProps>;
|
|
66
71
|
export default PaxSelector;
|
|
@@ -19,10 +19,11 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
19
19
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
20
20
|
};
|
|
21
21
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
22
|
-
import { useEffect, useRef, useState } from 'react';
|
|
22
|
+
import { Fragment, useEffect, useRef, useState } from 'react';
|
|
23
23
|
import { scrollIntoViewOnOpen } from '../../../lib/utils';
|
|
24
24
|
import Icon from '../../atoms/Icon/Icon';
|
|
25
25
|
import { Text } from '../../atoms/Typography/Typography';
|
|
26
|
+
import AgeSelector from '../../molecules/AgeSelector/AgeSelector';
|
|
26
27
|
var DEFAULT_PAX_DATA = {
|
|
27
28
|
adults: 0,
|
|
28
29
|
teens: 0,
|
|
@@ -45,99 +46,7 @@ export var DEFAULT_PAX_DATA_WITH_ADULTS = {
|
|
|
45
46
|
};
|
|
46
47
|
var CLIENT_TYPES = ['Standard client', 'VIP', 'VVIP', 'Honeymooners'];
|
|
47
48
|
// Age range for all child categories (teens, children, infants)
|
|
48
|
-
var CHILD_CATEGORY_AGES = Array.from({ length: 18 }, function (_, i) { return i + 1; }); // 1-18 years
|
|
49
|
-
var AgeSelector = function (_a) {
|
|
50
|
-
var label = _a.label, value = _a.value, onChange = _a.onChange, ageRange = _a.ageRange, required = _a.required;
|
|
51
|
-
var _b = useState(false), isOpen = _b[0], setIsOpen = _b[1];
|
|
52
|
-
var _c = useState(value !== undefined ? value.toString() : ''), inputValue = _c[0], setInputValue = _c[1];
|
|
53
|
-
var containerRef = useRef(null);
|
|
54
|
-
var inputRef = useRef(null);
|
|
55
|
-
// Sync input value when prop value changes
|
|
56
|
-
useEffect(function () {
|
|
57
|
-
setInputValue(value !== undefined ? value.toString() : '');
|
|
58
|
-
}, [value]);
|
|
59
|
-
useEffect(function () {
|
|
60
|
-
var handleClickOutside = function (event) {
|
|
61
|
-
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
62
|
-
setIsOpen(false);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
if (isOpen) {
|
|
66
|
-
document.addEventListener('mousedown', handleClickOutside);
|
|
67
|
-
}
|
|
68
|
-
return function () {
|
|
69
|
-
document.removeEventListener('mousedown', handleClickOutside);
|
|
70
|
-
};
|
|
71
|
-
}, [isOpen]);
|
|
72
|
-
var handleInputChange = function (e) {
|
|
73
|
-
var newValue = e.target.value;
|
|
74
|
-
// Only allow numeric input or empty string
|
|
75
|
-
if (newValue === '' || /^\d+$/.test(newValue)) {
|
|
76
|
-
setInputValue(newValue);
|
|
77
|
-
// Only update if it's a valid number within range
|
|
78
|
-
var numValue = parseInt(newValue, 10);
|
|
79
|
-
if (newValue === '') {
|
|
80
|
-
// Allow empty input - don't update onChange
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
else if (!isNaN(numValue) && ageRange.includes(numValue)) {
|
|
84
|
-
onChange(numValue);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
var handleInputBlur = function () {
|
|
89
|
-
// Validate and set to valid value or clear if invalid
|
|
90
|
-
var numValue = parseInt(inputValue, 10);
|
|
91
|
-
if (inputValue === '') {
|
|
92
|
-
// Keep empty if user cleared it
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
else if (isNaN(numValue) || !ageRange.includes(numValue)) {
|
|
96
|
-
// Reset to current value if invalid
|
|
97
|
-
setInputValue(value !== undefined ? value.toString() : '');
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
// Ensure the input value matches the validated value
|
|
101
|
-
setInputValue(numValue.toString());
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
var handleInputKeyDown = function (e) {
|
|
105
|
-
var _a;
|
|
106
|
-
if (e.key === 'Enter') {
|
|
107
|
-
e.preventDefault();
|
|
108
|
-
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.blur();
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
var handleSelect = function (age) {
|
|
112
|
-
var numAge = parseInt(age, 10);
|
|
113
|
-
onChange(numAge);
|
|
114
|
-
setIsOpen(false);
|
|
115
|
-
setInputValue(age);
|
|
116
|
-
};
|
|
117
|
-
var handleDropdownToggle = function () {
|
|
118
|
-
setIsOpen(!isOpen);
|
|
119
|
-
};
|
|
120
|
-
var ageOptions = ageRange.map(function (age) { return age.toString(); });
|
|
121
|
-
var displayValue = inputValue || undefined;
|
|
122
|
-
return (_jsxs("div", { className: "pax-selector__age-selector", ref: containerRef, children: [_jsxs(Text, { size: "sm", variant: "regular", className: "pax-selector__age-label", children: [label, required && _jsx("span", { className: "pax-selector__age-required", children: " *" })] }), _jsxs("div", { className: "dropdown-container pax-selector__age-dropdown-container", children: [_jsxs("div", { className: "dropdown-input ".concat(isOpen ? 'dropdown-input--open pax-selector__age-dropdown-input--open' : '', " ").concat(value !== undefined ? 'dropdown-input--selected' : 'dropdown-input--default', " pax-selector__age-dropdown-input"), children: [_jsx("input", { ref: inputRef, type: "text", inputMode: "numeric", className: "dropdown-input__text pax-selector__age-input-text", value: inputValue, onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: handleInputKeyDown, onFocus: function () { return setIsOpen(false); }, placeholder: "--", "aria-label": "".concat(label, " age"), style: {
|
|
123
|
-
background: 'transparent',
|
|
124
|
-
border: 'none',
|
|
125
|
-
outline: 'none',
|
|
126
|
-
width: '100%',
|
|
127
|
-
cursor: 'text',
|
|
128
|
-
} }), _jsx("button", { type: "button", className: "pax-selector__age-dropdown-btn", onClick: function (e) {
|
|
129
|
-
e.preventDefault();
|
|
130
|
-
e.stopPropagation();
|
|
131
|
-
handleDropdownToggle();
|
|
132
|
-
}, "aria-expanded": isOpen, "aria-haspopup": "listbox", "aria-label": "Open age dropdown", style: {
|
|
133
|
-
background: 'transparent',
|
|
134
|
-
border: 'none',
|
|
135
|
-
cursor: 'pointer',
|
|
136
|
-
padding: 0,
|
|
137
|
-
display: 'flex',
|
|
138
|
-
alignItems: 'center',
|
|
139
|
-
}, children: _jsx(Icon, { name: "chevron-down", size: "sm", className: "dropdown-input__icon dropdown-input__icon--chevron" }) })] }), isOpen && (_jsx("div", { className: "dropdown-menu", role: "listbox", children: ageOptions.map(function (age) { return (_jsx("div", { className: "dropdown-option ".concat((value === null || value === void 0 ? void 0 : value.toString()) === age ? 'dropdown-option--selected' : ''), onClick: function () { return handleSelect(age); }, role: "option", "aria-selected": (value === null || value === void 0 ? void 0 : value.toString()) === age, children: age }, age)); }) }))] })] }));
|
|
140
|
-
};
|
|
49
|
+
export var CHILD_CATEGORY_AGES = Array.from({ length: 18 }, function (_, i) { return i + 1; }); // 1-18 years
|
|
141
50
|
var StepperRow = function (_a) {
|
|
142
51
|
var label = _a.label, value = _a.value, _b = _a.min, min = _b === void 0 ? 0 : _b, _c = _a.max, max = _c === void 0 ? 99 : _c, onChange = _a.onChange;
|
|
143
52
|
var handleDecrement = function () {
|
|
@@ -176,7 +85,9 @@ var ClientTypeSelector = function (_a) {
|
|
|
176
85
|
return (_jsxs("div", { className: "pax-selector__client-type", children: [_jsx(Text, { size: "sm", variant: "regular", className: "pax-selector__client-type-label", children: "Client type" }), _jsxs("div", { className: "pax-selector__client-type-select", ref: containerRef, children: [_jsxs("button", { type: "button", className: "pax-selector__client-type-trigger", onClick: function () { return setIsOpen(!isOpen); }, "aria-expanded": isOpen, "aria-haspopup": "listbox", children: [_jsxs("div", { className: "pax-selector__client-type-content", children: [_jsx(Icon, { name: "user-icon", size: "sm", className: "pax-selector__client-type-icon" }), _jsx("span", { className: "pax-selector__client-type-text", children: value })] }), _jsx(Icon, { name: "chevron-down", size: "sm", className: "pax-selector__client-type-chevron ".concat(isOpen ? 'pax-selector__client-type-chevron--open' : '') })] }), isOpen && (_jsx("div", { className: "pax-selector__client-type-dropdown", role: "listbox", children: CLIENT_TYPES.map(function (type) { return (_jsxs("button", { type: "button", className: "pax-selector__client-type-option ".concat(value === type ? 'pax-selector__client-type-option--selected' : ''), onClick: function () { return handleSelect(type); }, role: "option", "aria-selected": value === type, children: [_jsx(Icon, { name: "user-icon", size: "sm" }), type] }, type)); }) }))] })] }));
|
|
177
86
|
};
|
|
178
87
|
var RoomEditor = function (_a) {
|
|
179
|
-
var room = _a.room, roomNumber = _a.roomNumber, showRemove = _a.showRemove, maxAdults = _a.maxAdults, maxTeens = _a.maxTeens, maxChildren = _a.maxChildren, maxInfants = _a.maxInfants, onChange = _a.onChange, onRemove = _a.onRemove;
|
|
88
|
+
var room = _a.room, roomNumber = _a.roomNumber, showRemove = _a.showRemove, maxAdults = _a.maxAdults, maxTeens = _a.maxTeens, maxChildren = _a.maxChildren, maxInfants = _a.maxInfants, onChange = _a.onChange, onRemove = _a.onRemove, scrollToRef = _a.scrollToRef, ageRange = _a.ageRange;
|
|
89
|
+
var roomAgesSectionRef = useRef(null);
|
|
90
|
+
var previousRoomCounts = useRef({ teens: 0, children: 0, infants: 0 });
|
|
180
91
|
var handleFieldChange = function (field, value) {
|
|
181
92
|
var _a;
|
|
182
93
|
onChange(__assign(__assign({}, room), (_a = {}, _a[field] = value, _a)));
|
|
@@ -186,6 +97,33 @@ var RoomEditor = function (_a) {
|
|
|
186
97
|
ages[index] = age;
|
|
187
98
|
handleFieldChange(category, ages);
|
|
188
99
|
};
|
|
100
|
+
// Scroll to age section when new age inputs are added in this room
|
|
101
|
+
useEffect(function () {
|
|
102
|
+
var prev = previousRoomCounts.current;
|
|
103
|
+
var curr = {
|
|
104
|
+
teens: room.teens,
|
|
105
|
+
children: room.children,
|
|
106
|
+
infants: room.infants,
|
|
107
|
+
};
|
|
108
|
+
// Check if any count increased
|
|
109
|
+
var hasIncrease = curr.teens > prev.teens ||
|
|
110
|
+
curr.children > prev.children ||
|
|
111
|
+
curr.infants > prev.infants;
|
|
112
|
+
if (hasIncrease && roomAgesSectionRef.current) {
|
|
113
|
+
// Scroll to the age section after a short delay to ensure DOM is updated
|
|
114
|
+
setTimeout(function () {
|
|
115
|
+
if (roomAgesSectionRef.current) {
|
|
116
|
+
roomAgesSectionRef.current.scrollIntoView({
|
|
117
|
+
behavior: 'smooth',
|
|
118
|
+
block: 'nearest',
|
|
119
|
+
inline: 'nearest',
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}, 100);
|
|
123
|
+
}
|
|
124
|
+
// Update previous counts
|
|
125
|
+
previousRoomCounts.current = curr;
|
|
126
|
+
}, [room.teens, room.children, room.infants]);
|
|
189
127
|
// Generate age arrays based on counts
|
|
190
128
|
useEffect(function () {
|
|
191
129
|
var teenAges = room.teenAges || [];
|
|
@@ -224,34 +162,37 @@ var RoomEditor = function (_a) {
|
|
|
224
162
|
var teenAgeChunks = chunkAges(room.teenAges || [], 'Teen');
|
|
225
163
|
var childAgeChunks = chunkAges(room.childAges || [], 'Child');
|
|
226
164
|
var infantAgeChunks = chunkAges(room.infantAges || [], 'Infant');
|
|
227
|
-
return (_jsxs("div", { className: "pax-selector__room-container", children: [_jsxs("div", { className: "pax-selector__room-header", children: [_jsxs("div", { className: "pax-selector__room-title", children: [_jsxs(Text, { size: "lg", variant: "bold", color: "accent", className: "pax-selector__room-name", children: ["Room ", roomNumber] }), _jsx(Icon, { name: "home", size: "md", className: "pax-selector__room-icon" })] }), showRemove && (_jsxs("button", { type: "button", className: "pax-selector__room-remove", onClick: onRemove, "aria-label": "Remove room ".concat(roomNumber), children: [_jsx(Icon, { name: "close", size: "sm", className: "pax-selector__room-remove-icon" }), _jsx("span", { className: "pax-selector__room-remove-text", children: "Remove" })] }))] }), _jsxs("div", { className: "pax-selector__room-content", children: [_jsxs("div", { className: "pax-selector__steppers", children: [_jsx(StepperRow, { label: "Adult", value: room.adults, max: maxAdults, onChange: function (val) { return handleFieldChange('adults', val); } }), _jsx(StepperRow, { label: "Teen", value: room.teens, max: maxTeens, onChange: function (val) { return handleFieldChange('teens', val); } }), _jsx(StepperRow, { label: "Child", value: room.children, max: maxChildren, onChange: function (val) { return handleFieldChange('children', val); } }), _jsx(StepperRow, { label: "Infant", value: room.infants, max: maxInfants, onChange: function (val) { return handleFieldChange('infants', val); } })] }), (room.teens > 0 || room.children > 0 || room.infants > 0) && (_jsxs("div", { className: "pax-selector__age-section", children: [_jsx(Text, { size: "base", variant: "bold", color: "default", className: "pax-selector__age-section-title", children: "Please specify the age :" }), _jsxs("div", { className: "pax-selector__age-groups", children: [room.teens > 0 &&
|
|
228
|
-
teenAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(
|
|
165
|
+
return (_jsxs("div", { className: "pax-selector__room-container", ref: scrollToRef, children: [_jsxs("div", { className: "pax-selector__room-header", children: [_jsxs("div", { className: "pax-selector__room-title", children: [_jsxs(Text, { size: "lg", variant: "bold", color: "accent", className: "pax-selector__room-name", children: ["Room ", roomNumber] }), _jsx(Icon, { name: "home", size: "md", className: "pax-selector__room-icon" })] }), showRemove && (_jsxs("button", { type: "button", className: "pax-selector__room-remove", onClick: onRemove, "aria-label": "Remove room ".concat(roomNumber), children: [_jsx(Icon, { name: "close", size: "sm", className: "pax-selector__room-remove-icon" }), _jsx("span", { className: "pax-selector__room-remove-text", children: "Remove" })] }))] }), _jsxs("div", { className: "pax-selector__room-content", children: [_jsxs("div", { className: "pax-selector__steppers", children: [_jsx(StepperRow, { label: "Adult", value: room.adults, max: maxAdults, onChange: function (val) { return handleFieldChange('adults', val); } }), _jsx(StepperRow, { label: "Teen", value: room.teens, max: maxTeens, onChange: function (val) { return handleFieldChange('teens', val); } }), _jsx(StepperRow, { label: "Child", value: room.children, max: maxChildren, onChange: function (val) { return handleFieldChange('children', val); } }), _jsx(StepperRow, { label: "Infant", value: room.infants, max: maxInfants, onChange: function (val) { return handleFieldChange('infants', val); } })] }), (room.teens > 0 || room.children > 0 || room.infants > 0) && (_jsxs("div", { className: "pax-selector__age-section", ref: roomAgesSectionRef, children: [_jsx(Text, { size: "base", variant: "bold", color: "default", className: "pax-selector__age-section-title", children: "Please specify the age :" }), _jsxs("div", { className: "pax-selector__age-groups", children: [room.teens > 0 &&
|
|
166
|
+
teenAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(Fragment, { children: chunk.map(function (age, ageIndex) {
|
|
229
167
|
var actualIndex = chunkIndex * 2 + ageIndex;
|
|
230
168
|
return (_jsx(AgeSelector, { label: "Teen", value: age, onChange: function (selectedAge) {
|
|
231
169
|
return handleAgeChange('teenAges', actualIndex, selectedAge);
|
|
232
|
-
}, ageRange:
|
|
170
|
+
}, ageRange: ageRange, required: true }, "teen-".concat(actualIndex)));
|
|
233
171
|
}) }, "teen-chunk-".concat(chunkIndex))); }), room.children > 0 &&
|
|
234
|
-
childAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(
|
|
172
|
+
childAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(Fragment, { children: chunk.map(function (age, ageIndex) {
|
|
235
173
|
var actualIndex = chunkIndex * 2 + ageIndex;
|
|
236
174
|
return (_jsx(AgeSelector, { label: "Child", value: age, onChange: function (selectedAge) {
|
|
237
175
|
return handleAgeChange('childAges', actualIndex, selectedAge);
|
|
238
|
-
}, ageRange:
|
|
176
|
+
}, ageRange: ageRange, required: true }, "child-".concat(actualIndex)));
|
|
239
177
|
}) }, "child-chunk-".concat(chunkIndex))); }), room.infants > 0 &&
|
|
240
|
-
infantAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(
|
|
178
|
+
infantAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(Fragment, { children: chunk.map(function (age, ageIndex) {
|
|
241
179
|
var actualIndex = chunkIndex * 2 + ageIndex;
|
|
242
180
|
return (_jsx(AgeSelector, { label: "Infant", value: age, onChange: function (selectedAge) {
|
|
243
181
|
return handleAgeChange('infantAges', actualIndex, selectedAge);
|
|
244
|
-
}, ageRange:
|
|
182
|
+
}, ageRange: ageRange, required: true }, "infant-".concat(actualIndex)));
|
|
245
183
|
}) }, "infant-chunk-".concat(chunkIndex))); })] })] })), _jsx(ClientTypeSelector, { value: room.clientType, onChange: function (val) { return handleFieldChange('clientType', val); } })] })] }));
|
|
246
184
|
};
|
|
247
185
|
var PaxSelector = function (_a) {
|
|
248
|
-
var _b = _a.label, label = _b === void 0 ? 'Number of pax' : _b, value = _a.value, onChange = _a.onChange, onAddRoom = _a.onAddRoom, onDone = _a.onDone, _c = _a.placeholder, placeholder = _c === void 0 ? 'Select pax' : _c, _d = _a.className, className = _d === void 0 ? '' : _d, _e = _a.maxAdults, maxAdults = _e === void 0 ? 10 : _e, _f = _a.maxTeens, maxTeens = _f === void 0 ? 10 : _f, _g = _a.maxChildren, maxChildren = _g === void 0 ? 10 : _g, _h = _a.maxInfants, maxInfants = _h === void 0 ? 10 : _h, _j = _a.showAddRoom, showAddRoom = _j === void 0 ? true : _j, _k = _a.multipleRooms, multipleRooms = _k === void 0 ? false : _k, defaultRooms = _a.defaultRooms, onRoomsChange = _a.onRoomsChange, onRemoveRoom = _a.onRemoveRoom, _l = _a.defaultPaxData, defaultPaxData = _l === void 0 ? DEFAULT_PAX_DATA_WITH_ADULTS : _l, _m = _a.scrollOnOpen, scrollOnOpen =
|
|
249
|
-
var
|
|
250
|
-
var
|
|
251
|
-
var
|
|
186
|
+
var _b = _a.label, label = _b === void 0 ? 'Number of pax' : _b, value = _a.value, onChange = _a.onChange, onAddRoom = _a.onAddRoom, onDone = _a.onDone, _c = _a.placeholder, placeholder = _c === void 0 ? 'Select pax' : _c, _d = _a.className, className = _d === void 0 ? '' : _d, _e = _a.maxAdults, maxAdults = _e === void 0 ? 10 : _e, _f = _a.maxTeens, maxTeens = _f === void 0 ? 10 : _f, _g = _a.maxChildren, maxChildren = _g === void 0 ? 10 : _g, _h = _a.maxInfants, maxInfants = _h === void 0 ? 10 : _h, _j = _a.showAddRoom, showAddRoom = _j === void 0 ? true : _j, _k = _a.multipleRooms, multipleRooms = _k === void 0 ? false : _k, defaultRooms = _a.defaultRooms, onRoomsChange = _a.onRoomsChange, onRemoveRoom = _a.onRemoveRoom, _l = _a.defaultPaxData, defaultPaxData = _l === void 0 ? DEFAULT_PAX_DATA_WITH_ADULTS : _l, _m = _a.ageRange, ageRange = _m === void 0 ? CHILD_CATEGORY_AGES : _m, _o = _a.scrollOnOpen, scrollOnOpen = _o === void 0 ? false : _o, _p = _a.disabled, disabled = _p === void 0 ? false : _p;
|
|
187
|
+
var _q = useState(false), isOpen = _q[0], setIsOpen = _q[1];
|
|
188
|
+
var _r = useState(value || defaultPaxData || DEFAULT_PAX_DATA), internalData = _r[0], setInternalData = _r[1];
|
|
189
|
+
var _s = useState(defaultRooms || [__assign(__assign({}, DEFAULT_PAX_DATA), { roomId: '1' })]), rooms = _s[0], setRooms = _s[1];
|
|
252
190
|
var containerRef = useRef(null);
|
|
253
191
|
var triggerRef = useRef(null);
|
|
254
192
|
var hasInitialized = useRef(false);
|
|
193
|
+
var lastRoomRef = useRef(null);
|
|
194
|
+
var agesSectionRef = useRef(null);
|
|
195
|
+
var previousCounts = useRef({ teens: 0, children: 0, infants: 0 });
|
|
255
196
|
// Sync internal data with external value prop
|
|
256
197
|
useEffect(function () {
|
|
257
198
|
if (value && !multipleRooms) {
|
|
@@ -329,6 +270,41 @@ var PaxSelector = function (_a) {
|
|
|
329
270
|
useEffect(function () {
|
|
330
271
|
scrollIntoViewOnOpen(triggerRef, isOpen, scrollOnOpen);
|
|
331
272
|
}, [isOpen, scrollOnOpen]);
|
|
273
|
+
// Scroll to age section when new age inputs are added (single room mode)
|
|
274
|
+
useEffect(function () {
|
|
275
|
+
if (!multipleRooms && isOpen) {
|
|
276
|
+
var prev = previousCounts.current;
|
|
277
|
+
var curr = {
|
|
278
|
+
teens: internalData.teens,
|
|
279
|
+
children: internalData.children,
|
|
280
|
+
infants: internalData.infants,
|
|
281
|
+
};
|
|
282
|
+
// Check if any count increased
|
|
283
|
+
var hasIncrease = curr.teens > prev.teens ||
|
|
284
|
+
curr.children > prev.children ||
|
|
285
|
+
curr.infants > prev.infants;
|
|
286
|
+
if (hasIncrease && agesSectionRef.current) {
|
|
287
|
+
// Scroll to the age section after a short delay to ensure DOM is updated
|
|
288
|
+
setTimeout(function () {
|
|
289
|
+
if (agesSectionRef.current) {
|
|
290
|
+
agesSectionRef.current.scrollIntoView({
|
|
291
|
+
behavior: 'smooth',
|
|
292
|
+
block: 'nearest',
|
|
293
|
+
inline: 'nearest',
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}, 100);
|
|
297
|
+
}
|
|
298
|
+
// Update previous counts
|
|
299
|
+
previousCounts.current = curr;
|
|
300
|
+
}
|
|
301
|
+
}, [
|
|
302
|
+
internalData.teens,
|
|
303
|
+
internalData.children,
|
|
304
|
+
internalData.infants,
|
|
305
|
+
multipleRooms,
|
|
306
|
+
isOpen,
|
|
307
|
+
]);
|
|
332
308
|
var handleDataChange = function (field, newValue) {
|
|
333
309
|
var _a;
|
|
334
310
|
var newData = __assign(__assign({}, internalData), (_a = {}, _a[field] = newValue, _a));
|
|
@@ -357,6 +333,16 @@ var PaxSelector = function (_a) {
|
|
|
357
333
|
setRooms(updatedRooms);
|
|
358
334
|
onRoomsChange === null || onRoomsChange === void 0 ? void 0 : onRoomsChange(updatedRooms);
|
|
359
335
|
onAddRoom === null || onAddRoom === void 0 ? void 0 : onAddRoom();
|
|
336
|
+
// Scroll to the newly added room after a short delay
|
|
337
|
+
setTimeout(function () {
|
|
338
|
+
if (lastRoomRef.current) {
|
|
339
|
+
lastRoomRef.current.scrollIntoView({
|
|
340
|
+
behavior: 'smooth',
|
|
341
|
+
block: 'nearest',
|
|
342
|
+
inline: 'nearest',
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
}, 100);
|
|
360
346
|
};
|
|
361
347
|
var handleRemoveRoom = function (roomId) {
|
|
362
348
|
var updatedRooms = rooms.filter(function (room) { return room.roomId !== roomId; });
|
|
@@ -386,11 +372,11 @@ var PaxSelector = function (_a) {
|
|
|
386
372
|
return "".concat(total, " pax");
|
|
387
373
|
};
|
|
388
374
|
var hasPax = getTotalPax() > 0;
|
|
389
|
-
return (_jsxs("div", { className: "pax-selector ".concat(className), ref: containerRef, children: [_jsxs("button", { ref: triggerRef, type: "button", className: "pax-selector__trigger", onClick: function () { return setIsOpen(!isOpen); }, "aria-expanded": isOpen, "aria-haspopup": "true", children: [_jsx(Text, { size: "sm", variant: "regular", className: "pax-selector__label", children: label }), _jsxs("div", { className: "pax-selector__input ".concat(isOpen ? 'pax-selector__input--active' : ''), children: [_jsxs("div", { className: "pax-selector__input-content", children: [_jsx(Icon, { name: "user-icon", size: "sm", className: "pax-selector__input-icon" }), _jsx("span", { className: "pax-selector__input-text ".concat(!hasPax ? 'pax-selector__input-placeholder' : ''), children: getDisplayText() })] }), _jsx(Icon, { name: "chevron-down", size: "sm", className: "pax-selector__chevron ".concat(isOpen ? 'pax-selector__chevron--open' : '') })] })] }), isOpen && (_jsxs("div", { className: "pax-selector__dropdown", children: [multipleRooms ? (_jsxs(_Fragment, { children: [showAddRoom && (_jsxs("button", { type: "button", className: "pax-selector__add-room", onClick: handleAddRoom, children: [_jsx(Icon, { name: "home", size: "sm", className: "pax-selector__add-room-icon" }), "Add a room", _jsx(Icon, { name: "plus", size: "sm", className: "pax-selector__add-room-icon" })] })), _jsx("div", { className: "pax-selector__rooms", children: rooms.map(function (room, index) { return (_jsx(RoomEditor, { room: room, roomNumber: index + 1, showRemove: rooms.length > 1, maxAdults: maxAdults, maxTeens: maxTeens, maxChildren: maxChildren, maxInfants: maxInfants, onChange: function (updatedRoom) { return handleRoomChange(room.roomId, updatedRoom); }, onRemove: function () { return handleRemoveRoom(room.roomId); } }, room.roomId)); }) })] })) : (
|
|
375
|
+
return (_jsxs("div", { className: "pax-selector ".concat(disabled ? 'pax-selector--disabled' : '', " ").concat(className), ref: containerRef, children: [_jsxs("button", { ref: triggerRef, type: "button", className: "pax-selector__trigger", onClick: function () { return !disabled && setIsOpen(!isOpen); }, "aria-expanded": isOpen, "aria-haspopup": "true", disabled: disabled, children: [_jsx(Text, { size: "sm", variant: "regular", className: "pax-selector__label", children: label }), _jsxs("div", { className: "pax-selector__input ".concat(isOpen ? 'pax-selector__input--active' : '', " ").concat(disabled ? 'pax-selector__input--disabled' : ''), children: [_jsxs("div", { className: "pax-selector__input-content", children: [_jsx(Icon, { name: "user-icon", size: "sm", className: "pax-selector__input-icon" }), _jsx("span", { className: "pax-selector__input-text ".concat(!hasPax ? 'pax-selector__input-placeholder' : ''), children: getDisplayText() })] }), _jsx(Icon, { name: "chevron-down", size: "sm", className: "pax-selector__chevron ".concat(isOpen ? 'pax-selector__chevron--open' : '') })] })] }), isOpen && (_jsxs("div", { className: "pax-selector__dropdown", children: [multipleRooms ? (_jsxs(_Fragment, { children: [showAddRoom && (_jsxs("button", { type: "button", className: "pax-selector__add-room", onClick: handleAddRoom, children: [_jsx(Icon, { name: "home", size: "sm", className: "pax-selector__add-room-icon" }), "Add a room", _jsx(Icon, { name: "plus", size: "sm", className: "pax-selector__add-room-icon" })] })), _jsx("div", { className: "pax-selector__rooms", children: rooms.map(function (room, index) { return (_jsx(RoomEditor, { room: room, roomNumber: index + 1, showRemove: rooms.length > 1, maxAdults: maxAdults, maxTeens: maxTeens, maxChildren: maxChildren, maxInfants: maxInfants, onChange: function (updatedRoom) { return handleRoomChange(room.roomId, updatedRoom); }, onRemove: function () { return handleRemoveRoom(room.roomId); }, scrollToRef: index === rooms.length - 1 ? lastRoomRef : undefined, ageRange: ageRange }, room.roomId)); }) })] })) : (
|
|
390
376
|
/* Single Room Mode */
|
|
391
377
|
_jsxs(_Fragment, { children: [_jsxs("div", { className: "pax-selector__steppers", children: [_jsx(StepperRow, { label: "Adult", value: internalData.adults, max: maxAdults, onChange: function (val) { return handleDataChange('adults', val); } }), _jsx(StepperRow, { label: "Teen", value: internalData.teens, max: maxTeens, onChange: function (val) { return handleDataChange('teens', val); } }), _jsx(StepperRow, { label: "Child", value: internalData.children, max: maxChildren, onChange: function (val) { return handleDataChange('children', val); } }), _jsx(StepperRow, { label: "Infant", value: internalData.infants, max: maxInfants, onChange: function (val) { return handleDataChange('infants', val); } })] }), (internalData.teens > 0 ||
|
|
392
378
|
internalData.children > 0 ||
|
|
393
|
-
internalData.infants > 0) && (_jsxs("div", { className: "pax-selector__age-section", children: [_jsx(Text, { size: "base", variant: "bold", color: "default", className: "pax-selector__age-section-title", children: "Please specify the age :" }), _jsx("div", { className: "pax-selector__age-groups", children: (function () {
|
|
379
|
+
internalData.infants > 0) && (_jsxs("div", { className: "pax-selector__age-section", ref: agesSectionRef, children: [_jsx(Text, { size: "base", variant: "bold", color: "default", className: "pax-selector__age-section-title", children: "Please specify the age :" }), _jsx("div", { className: "pax-selector__age-groups", children: (function () {
|
|
394
380
|
var chunkAges = function (ages, category) {
|
|
395
381
|
var chunks = [];
|
|
396
382
|
for (var i = 0; i < ages.length; i += 2) {
|
|
@@ -407,23 +393,23 @@ var PaxSelector = function (_a) {
|
|
|
407
393
|
handleDataChange(category, ages);
|
|
408
394
|
};
|
|
409
395
|
return (_jsxs(_Fragment, { children: [internalData.teens > 0 &&
|
|
410
|
-
teenAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(
|
|
396
|
+
teenAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(Fragment, { children: chunk.map(function (age, ageIndex) {
|
|
411
397
|
var actualIndex = chunkIndex * 2 + ageIndex;
|
|
412
398
|
return (_jsx(AgeSelector, { label: "Teen", value: age, onChange: function (selectedAge) {
|
|
413
399
|
return handleAgeChange('teenAges', actualIndex, selectedAge);
|
|
414
|
-
}, ageRange:
|
|
400
|
+
}, ageRange: ageRange, required: true }, "teen-".concat(actualIndex)));
|
|
415
401
|
}) }, "teen-chunk-".concat(chunkIndex))); }), internalData.children > 0 &&
|
|
416
|
-
childAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(
|
|
402
|
+
childAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(Fragment, { children: chunk.map(function (age, ageIndex) {
|
|
417
403
|
var actualIndex = chunkIndex * 2 + ageIndex;
|
|
418
404
|
return (_jsx(AgeSelector, { label: "Child", value: age, onChange: function (selectedAge) {
|
|
419
405
|
return handleAgeChange('childAges', actualIndex, selectedAge);
|
|
420
|
-
}, ageRange:
|
|
406
|
+
}, ageRange: ageRange, required: true }, "child-".concat(actualIndex)));
|
|
421
407
|
}) }, "child-chunk-".concat(chunkIndex))); }), internalData.infants > 0 &&
|
|
422
|
-
infantAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(
|
|
408
|
+
infantAgeChunks.map(function (chunk, chunkIndex) { return (_jsx(Fragment, { children: chunk.map(function (age, ageIndex) {
|
|
423
409
|
var actualIndex = chunkIndex * 2 + ageIndex;
|
|
424
410
|
return (_jsx(AgeSelector, { label: "Infant", value: age, onChange: function (selectedAge) {
|
|
425
411
|
return handleAgeChange('infantAges', actualIndex, selectedAge);
|
|
426
|
-
}, ageRange:
|
|
412
|
+
}, ageRange: ageRange, required: true }, "infant-".concat(actualIndex)));
|
|
427
413
|
}) }, "infant-chunk-".concat(chunkIndex))); })] }));
|
|
428
414
|
})() })] })), _jsx(ClientTypeSelector, { value: internalData.clientType, onChange: function (val) { return handleDataChange('clientType', val); } })] })), _jsxs("div", { className: "pax-selector__actions", children: [_jsx("button", { type: "button", className: "pax-selector__clear-btn", onClick: handleClear, children: "Clear Pax" }), _jsx("button", { type: "button", className: "pax-selector__done-btn", onClick: handleDone, children: "Done" })] })] }))] }));
|
|
429
415
|
};
|
|
@@ -21,7 +21,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
21
21
|
return t;
|
|
22
22
|
};
|
|
23
23
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
24
|
-
import
|
|
24
|
+
import debounce from 'lodash/debounce';
|
|
25
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
25
26
|
import Button from '../../atoms/Button/Button';
|
|
26
27
|
import DropdownInput from '../../atoms/Inputs/DropdownInput/DropdownInput';
|
|
27
28
|
import Input from '../../atoms/Inputs/Input/Input';
|
|
@@ -52,6 +53,34 @@ export function QuoteHeader(props) {
|
|
|
52
53
|
search: '',
|
|
53
54
|
}), currentValue = _c[0], setCurrentValue = _c[1];
|
|
54
55
|
var _d = useState((_a = currentFilter === null || currentFilter === void 0 ? void 0 : currentFilter.search) !== null && _a !== void 0 ? _a : ''), searchValue = _d[0], setSearchValue = _d[1];
|
|
56
|
+
// Create a ref to store the debounced function
|
|
57
|
+
var debouncedFilterChangeRef = useRef(debounce(function (value) {
|
|
58
|
+
onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange('search', value);
|
|
59
|
+
setCurrentValue(function (prev) { return (__assign(__assign({}, prev), { search: value })); });
|
|
60
|
+
}, 500));
|
|
61
|
+
// Update the debounced function when onFilterChange changes
|
|
62
|
+
useEffect(function () {
|
|
63
|
+
// Cancel the previous debounced function
|
|
64
|
+
debouncedFilterChangeRef.current.cancel();
|
|
65
|
+
// Create a new debounced function
|
|
66
|
+
debouncedFilterChangeRef.current = debounce(function (value) {
|
|
67
|
+
onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange('search', value);
|
|
68
|
+
setCurrentValue(function (prev) { return (__assign(__assign({}, prev), { search: value })); });
|
|
69
|
+
}, 500);
|
|
70
|
+
}, [onFilterChange]);
|
|
71
|
+
// Cleanup debounced function on unmount
|
|
72
|
+
useEffect(function () {
|
|
73
|
+
return function () {
|
|
74
|
+
debouncedFilterChangeRef.current.cancel();
|
|
75
|
+
};
|
|
76
|
+
}, []);
|
|
77
|
+
var handleInputChange = useCallback(function (e) {
|
|
78
|
+
var value = e.target.value;
|
|
79
|
+
// Update input value immediately for responsive UI
|
|
80
|
+
setSearchValue(value);
|
|
81
|
+
// Debounce the filter change callback
|
|
82
|
+
debouncedFilterChangeRef.current(value);
|
|
83
|
+
}, []);
|
|
55
84
|
useEffect(function () {
|
|
56
85
|
if (currentFilter && Object.keys(currentFilter).length > 0) {
|
|
57
86
|
var search = currentFilter.search, rest = __rest(currentFilter, ["search"]);
|
|
@@ -63,11 +92,7 @@ export function QuoteHeader(props) {
|
|
|
63
92
|
setSearchValue('');
|
|
64
93
|
}
|
|
65
94
|
}, [currentFilter]);
|
|
66
|
-
return (_jsxs("div", { className: "quote-header", children: [_jsx(Heading, { level: 4, as: "h1", className: "quote-header__title", color: "accent", children: "Quotation & Booking" }), _jsxs("div", { className: "flex gap-4", children: [_jsx(Button, { variant: current === 'quotation' ? 'primary' : 'outline-primary', className: "quote-header__button", onClick: function () { return onNavigate('quotation'); }, children: "Quotation" }), _jsx(Button, { variant: current === 'booking' ? 'primary' : 'outline-primary', className: "quote-header__button", onClick: function () { return onNavigate('booking'); }, children: "Booking" })] }), _jsxs("div", { className: "quote-header__search-container", children: [_jsx(Input, { placeholder: "Search", icon: "search", iconPosition: "leading", className: "quote-header__search", value: searchValue, onChange: function (
|
|
67
|
-
onFilterChange === null || onFilterChange === void 0 ? void 0 : onFilterChange('search', e.target.value);
|
|
68
|
-
setCurrentValue(__assign(__assign({}, currentValue), { search: e.target.value }));
|
|
69
|
-
setSearchValue(e.target.value);
|
|
70
|
-
} }), _jsx(Button, { variant: "primary", leadingIcon: "plus-circle", iconSize: "md", size: "sm", onClick: onNewQuote, children: "New quote" })] }), _jsx("div", { className: "quote-header__filters", children: Object.entries(filterConfig).map(function (_a) {
|
|
95
|
+
return (_jsxs("div", { className: "quote-header", children: [_jsx(Heading, { level: 4, as: "h1", className: "quote-header__title", color: "accent", children: "Quotation & Booking" }), _jsxs("div", { className: "flex gap-4", children: [_jsx(Button, { variant: current === 'quotation' ? 'primary' : 'outline-primary', className: "quote-header__button", onClick: function () { return onNavigate('quotation'); }, children: "Quotation" }), _jsx(Button, { variant: current === 'booking' ? 'primary' : 'outline-primary', className: "quote-header__button", onClick: function () { return onNavigate('booking'); }, children: "Booking" })] }), _jsxs("div", { className: "quote-header__search-container", children: [_jsx(Input, { placeholder: "Search", icon: "search", iconPosition: "leading", className: "quote-header__search", value: searchValue, onChange: handleInputChange }), _jsx(Button, { variant: "primary", leadingIcon: "plus-circle", iconSize: "md", size: "sm", onClick: onNewQuote, children: "New quote" })] }), _jsx("div", { className: "quote-header__filters", children: Object.entries(filterConfig).map(function (_a) {
|
|
71
96
|
var key = _a[0], value = _a[1];
|
|
72
97
|
return (_jsx(DropdownInput, { placeholder: value.placeholder, options: value.options, value: currentValue[key], onSelect: function (value) {
|
|
73
98
|
var _a;
|
|
@@ -51,6 +51,8 @@ export interface RoundTripProps {
|
|
|
51
51
|
className?: string;
|
|
52
52
|
/** Whether to check if inputs are empty */
|
|
53
53
|
checkEmpty?: boolean;
|
|
54
|
+
/** Whether to scroll to the input when the calendar opens */
|
|
55
|
+
scrollOnOpen?: boolean;
|
|
54
56
|
}
|
|
55
57
|
declare const RoundTrip: React.FC<RoundTripProps>;
|
|
56
58
|
export default RoundTrip;
|
|
@@ -26,12 +26,12 @@ import LocationDropdown from "../../molecules/LocationDropdown/LocationDropdown"
|
|
|
26
26
|
import DateTimePicker from "../DateTimePicker/DateTimePicker";
|
|
27
27
|
import PaxSelector from "../PaxSelector/PaxSelector";
|
|
28
28
|
var RoundTrip = function (_a) {
|
|
29
|
-
var id = _a.id, paxData = _a.paxData, arrivalDate = _a.arrivalDate, departureDate = _a.departureDate, pickupDropoffPoint = _a.pickupDropoffPoint, accommodation = _a.accommodation, _b = _a.locations, locations = _b === void 0 ? { options: [], groups: [] } : _b, onPaxChange = _a.onPaxChange, onDatesChange = _a.onDatesChange, onPickupDropoffChange = _a.onPickupDropoffChange, onAccommodationChange = _a.onAccommodationChange, onChange = _a.onChange, _c = _a.className, className = _c === void 0 ? "" : _c, _d = _a.checkEmpty, checkEmpty = _d === void 0 ? false : _d;
|
|
30
|
-
var
|
|
31
|
-
var
|
|
32
|
-
var
|
|
33
|
-
var
|
|
34
|
-
var
|
|
29
|
+
var id = _a.id, paxData = _a.paxData, arrivalDate = _a.arrivalDate, departureDate = _a.departureDate, pickupDropoffPoint = _a.pickupDropoffPoint, accommodation = _a.accommodation, _b = _a.locations, locations = _b === void 0 ? { options: [], groups: [] } : _b, onPaxChange = _a.onPaxChange, onDatesChange = _a.onDatesChange, onPickupDropoffChange = _a.onPickupDropoffChange, onAccommodationChange = _a.onAccommodationChange, onChange = _a.onChange, _c = _a.className, className = _c === void 0 ? "" : _c, _d = _a.checkEmpty, checkEmpty = _d === void 0 ? false : _d, _e = _a.scrollOnOpen, scrollOnOpen = _e === void 0 ? false : _e;
|
|
30
|
+
var _f = useState(paxData), internalPaxData = _f[0], setInternalPaxData = _f[1];
|
|
31
|
+
var _g = useState(arrivalDate), internalArrivalDate = _g[0], setInternalArrivalDate = _g[1];
|
|
32
|
+
var _h = useState(departureDate), internalDepartureDate = _h[0], setInternalDepartureDate = _h[1];
|
|
33
|
+
var _j = useState(null), internalPickupDropoffPoint = _j[0], setInternalPickupDropoffPoint = _j[1];
|
|
34
|
+
var _k = useState(null), internalAccommodation = _k[0], setInternalAccommodation = _k[1];
|
|
35
35
|
// Helper function to get all locations (from options and groups)
|
|
36
36
|
var getAllLocations = function (options, groups) {
|
|
37
37
|
var groupOptions = groups.flatMap(function (group) { return group.options; });
|
|
@@ -184,6 +184,6 @@ var RoundTrip = function (_a) {
|
|
|
184
184
|
var isAccommodationEmpty = checkEmpty && !internalAccommodation;
|
|
185
185
|
var pickupDropoffOptions = getPickupDropoffOptions();
|
|
186
186
|
var accommodationOptions = getAccommodationOptions();
|
|
187
|
-
return (_jsx("div", { className: "round-trip ".concat(className), "data-round-trip-id": id, children: _jsxs("div", { className: "round-trip__content", children: [_jsx("div", { className: "round-trip__field round-trip__field--pax ".concat(isPaxEmpty ? 'round-trip__field--error' : ''), children: _jsx(PaxSelector, { label: "Number of pax", value: internalPaxData, onChange: handlePaxChange, placeholder: "2 pax", className: isPaxEmpty ? 'pax-selector--error' : '' }) }), _jsxs("div", { className: "round-trip__field round-trip__field--dates", children: [_jsx(Text, { size: "sm", variant: "regular", className: "round-trip__field-label", children: "Arrival date - Departure date" }), _jsx(DateTimePicker, { placeholder: "DD/MM/YYYY - DD/MM/YYYY", mode: "calendar", iconPosition: "left", numberOfMonths: 2, iconBGFull: false, showChevron: true, onValueChange: handleDateRangeChange, selectionMode: "range", defaultValue: internalArrivalDate && internalDepartureDate ? [internalArrivalDate, internalDepartureDate] : undefined, inputClassName: "round-trip__date-picker--input", state: isDateEmpty ? 'error' : undefined })] }), _jsx("div", { className: "round-trip__field round-trip__field--pickup-dropoff", children: _jsx(LocationDropdown, { label: "Pick up / Drop-off point", options: pickupDropoffOptions.options, groups: pickupDropoffOptions.groups, selectedValue: (internalPickupDropoffPoint === null || internalPickupDropoffPoint === void 0 ? void 0 : internalPickupDropoffPoint.id) || null, onSelectionChange: handlePickupDropoffChange, placeholder: "Select pick-up / drop-off point", direction: undefined, type: "airport-port", showGroupTitles: true, error: isPickupDropoffEmpty }) }), _jsx("div", { className: "round-trip__field round-trip__field--accommodation", children: _jsx(LocationDropdown, { label: "Accommodation", options: accommodationOptions.options, groups: accommodationOptions.groups, selectedValue: (internalAccommodation === null || internalAccommodation === void 0 ? void 0 : internalAccommodation.id) || null, onSelectionChange: handleAccommodationChange, placeholder: "Select accommodation", direction: "dropoff", type: "accommodation", showGroupTitles: false, error: isAccommodationEmpty }) })] }) }));
|
|
187
|
+
return (_jsx("div", { className: "round-trip ".concat(className), "data-round-trip-id": id, children: _jsxs("div", { className: "round-trip__content", children: [_jsx("div", { className: "round-trip__field round-trip__field--pax ".concat(isPaxEmpty ? 'round-trip__field--error' : ''), children: _jsx(PaxSelector, { label: "Number of pax", value: internalPaxData, onChange: handlePaxChange, placeholder: "2 pax", className: isPaxEmpty ? 'pax-selector--error' : '', scrollOnOpen: scrollOnOpen }) }), _jsxs("div", { className: "round-trip__field round-trip__field--dates", children: [_jsx(Text, { size: "sm", variant: "regular", className: "round-trip__field-label", children: "Arrival date - Departure date" }), _jsx(DateTimePicker, { placeholder: "DD/MM/YYYY - DD/MM/YYYY", mode: "calendar", iconPosition: "left", numberOfMonths: 2, iconBGFull: false, showChevron: true, onValueChange: handleDateRangeChange, selectionMode: "range", defaultValue: internalArrivalDate && internalDepartureDate ? [internalArrivalDate, internalDepartureDate] : undefined, inputClassName: "round-trip__date-picker--input", state: isDateEmpty ? 'error' : undefined, scrollOnOpen: scrollOnOpen })] }), _jsx("div", { className: "round-trip__field round-trip__field--pickup-dropoff", children: _jsx(LocationDropdown, { label: "Pick up / Drop-off point", options: pickupDropoffOptions.options, groups: pickupDropoffOptions.groups, selectedValue: (internalPickupDropoffPoint === null || internalPickupDropoffPoint === void 0 ? void 0 : internalPickupDropoffPoint.id) || null, onSelectionChange: handlePickupDropoffChange, placeholder: "Select pick-up / drop-off point", direction: undefined, type: "airport-port", showGroupTitles: true, error: isPickupDropoffEmpty, scrollOnOpen: scrollOnOpen }) }), _jsx("div", { className: "round-trip__field round-trip__field--accommodation", children: _jsx(LocationDropdown, { label: "Accommodation", options: accommodationOptions.options, groups: accommodationOptions.groups, selectedValue: (internalAccommodation === null || internalAccommodation === void 0 ? void 0 : internalAccommodation.id) || null, onSelectionChange: handleAccommodationChange, placeholder: "Select accommodation", direction: "dropoff", type: "accommodation", showGroupTitles: false, error: isAccommodationEmpty, scrollOnOpen: scrollOnOpen }) })] }) }));
|
|
188
188
|
};
|
|
189
189
|
export default RoundTrip;
|
|
@@ -28,8 +28,12 @@ export interface SearchBarTransferProps {
|
|
|
28
28
|
onSearch?: (data: SearchBarTransferData) => void;
|
|
29
29
|
/** Callback when data changes */
|
|
30
30
|
onChange?: (data: SearchBarTransferData) => void;
|
|
31
|
+
/** Callback when a transfer line is removed */
|
|
32
|
+
onRemove?: (index: number, transferLine: TransferLineData) => void;
|
|
31
33
|
/** Additional CSS classes */
|
|
32
34
|
className?: string;
|
|
35
|
+
/** Whether to scroll to the input when the calendar opens */
|
|
36
|
+
scrollOnOpen?: boolean;
|
|
33
37
|
}
|
|
34
38
|
declare const SearchBarTransfer: React.FC<SearchBarTransferProps>;
|
|
35
39
|
export default SearchBarTransfer;
|