ublo-lib 1.26.3 → 1.26.5
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/es/common/components/date-picker/calendar.js +120 -127
- package/es/common/components/date-picker/calendar.module.css +37 -34
- package/es/common/components/date-picker/data.js +15 -20
- package/es/common/components/date-picker/date-item.js +75 -66
- package/es/common/components/date-picker/date-item.module.css +39 -37
- package/es/common/components/date-picker/date-picker.js +21 -83
- package/es/common/components/date-picker/date-picker.module.css +2 -70
- package/es/common/components/date-picker/helper.js +35 -17
- package/es/common/components/date-picker/helper.module.css +57 -53
- package/es/common/components/date-picker/messages.js +18 -2
- package/es/common/components/date-picker/month.js +11 -16
- package/es/common/components/date-picker/month.module.css +11 -31
- package/es/common/components/date-picker/utils.js +8 -9
- package/es/common/components/msem-preset-editor/components/widget-list-item.js +0 -1
- package/es/common/components/msem-preset-editor/services/offers.js +17 -1
- package/es/common/components/msem-preset-editor/services/preset.js +4 -0
- package/es/common/hooks/use-window-sizes.js +5 -4
- package/package.json +1 -1
- package/es/common/components/date-picker/modes.js +0 -38
- package/es/common/components/date-picker/modes.module.css +0 -90
|
@@ -2,7 +2,7 @@ import * as React from "react";
|
|
|
2
2
|
import classNames from "classnames";
|
|
3
3
|
import { useUbloContext } from "ublo/with-ublo";
|
|
4
4
|
import Month from "./month";
|
|
5
|
-
import Popup from "
|
|
5
|
+
import Popup from "ublo-lib/es/common/components/popup";
|
|
6
6
|
import Helper from "./helper";
|
|
7
7
|
import Button from "dt-design-system/es/button";
|
|
8
8
|
import * as Icons from "dt-design-system/es/icons";
|
|
@@ -13,23 +13,17 @@ import datePickerStyles from "./date-picker.module.css";
|
|
|
13
13
|
import styles from "./calendar.module.css";
|
|
14
14
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
15
15
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
16
|
-
export default
|
|
17
|
-
function Calendar({
|
|
16
|
+
export default function Calendar({
|
|
18
17
|
date,
|
|
19
|
-
mode,
|
|
20
|
-
setMode,
|
|
21
18
|
display,
|
|
22
19
|
stayDates = [],
|
|
23
20
|
min,
|
|
24
21
|
max,
|
|
25
22
|
onSubmit,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
rules,
|
|
29
|
-
hideModes,
|
|
23
|
+
availabilities,
|
|
24
|
+
close,
|
|
30
25
|
singleDate,
|
|
31
26
|
submitOnSelectionEnd,
|
|
32
|
-
availabilities,
|
|
33
27
|
disableConfirmModal
|
|
34
28
|
}) {
|
|
35
29
|
const isDateObject = Utils.isDate(date);
|
|
@@ -50,7 +44,8 @@ function Calendar({
|
|
|
50
44
|
const [lastSelectedDate, setLastSelectedDate] = React.useState();
|
|
51
45
|
const [showPopup, setShowPopup] = React.useState(false);
|
|
52
46
|
const [stays, setStays] = React.useState();
|
|
53
|
-
const
|
|
47
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
48
|
+
const [error, setError] = React.useState();
|
|
54
49
|
const gotoPreviousMonth = () => {
|
|
55
50
|
const {
|
|
56
51
|
month: newMonth,
|
|
@@ -67,6 +62,12 @@ function Calendar({
|
|
|
67
62
|
setMonth(newMonth);
|
|
68
63
|
setYear(newYear);
|
|
69
64
|
};
|
|
65
|
+
const reset = () => {
|
|
66
|
+
setSelectedDates([]);
|
|
67
|
+
setSelecting(false);
|
|
68
|
+
setFirstSelectedDate(undefined);
|
|
69
|
+
setLastSelectedDate(undefined);
|
|
70
|
+
};
|
|
70
71
|
const submit = dates => {
|
|
71
72
|
const hasCart = window.sessionStorage.cartId !== undefined;
|
|
72
73
|
if (!disableConfirmModal && hasCart) {
|
|
@@ -79,66 +80,28 @@ function Calendar({
|
|
|
79
80
|
if (month === 12) {
|
|
80
81
|
setMonthAlt(1);
|
|
81
82
|
setYearAlt(year + 1);
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
if (month === 11) {
|
|
83
|
+
} else if (month === 11) {
|
|
85
84
|
setMonthAlt(month + 1);
|
|
86
85
|
setYearAlt(year);
|
|
87
|
-
|
|
86
|
+
} else {
|
|
87
|
+
setMonthAlt(month + 1);
|
|
88
88
|
}
|
|
89
|
-
setMonthAlt(month + 1);
|
|
90
89
|
}, [month, year]);
|
|
91
|
-
React.useEffect(() => {
|
|
92
|
-
if (!firstRangeDate) return;
|
|
93
|
-
const from = Utils.formatDate(firstRangeDate);
|
|
94
|
-
const matchingRule = rules.find(rule => rule.trigger === from);
|
|
95
|
-
setSpecialRule(matchingRule);
|
|
96
|
-
if (matchingRule) return;
|
|
97
|
-
if (display !== Data.DISPLAYS.PHONE && mode === Data.MODES.SATURDAY && Utils.isSunday(firstRangeDate) && Utils.isSunday(selectedDates[selectedDates.length - 1])) {
|
|
98
|
-
const newSelectedDates = selectedDates.map(date => {
|
|
99
|
-
const d = new Date(date);
|
|
100
|
-
const newDate = new Date(d.setDate(d.getDate() - 1));
|
|
101
|
-
return newDate;
|
|
102
|
-
});
|
|
103
|
-
setSelectedDates(newSelectedDates);
|
|
104
|
-
}
|
|
105
|
-
if (display !== Data.DISPLAYS.PHONE && mode === Data.MODES.SUNDAY && Utils.isSaturday(firstRangeDate) && Utils.isSaturday(selectedDates[selectedDates.length - 1])) {
|
|
106
|
-
const newSelectedDates = selectedDates.map(date => {
|
|
107
|
-
const d = new Date(date);
|
|
108
|
-
const newDate = new Date(d.setDate(d.getDate() + 1));
|
|
109
|
-
return newDate;
|
|
110
|
-
});
|
|
111
|
-
setSelectedDates(newSelectedDates);
|
|
112
|
-
}
|
|
113
|
-
if ((mode === Data.MODES.SATURDAY || mode === Data.MODES.SUNDAY) && !mustKeepSelected) {
|
|
114
|
-
setSelectedDates([]);
|
|
115
|
-
}
|
|
116
|
-
}, [display, firstRangeDate, mode, mustKeepSelected, rules, selectedDates, setSpecialRule]);
|
|
117
|
-
React.useEffect(() => {
|
|
118
|
-
if (specialRule) {
|
|
119
|
-
const {
|
|
120
|
-
interval,
|
|
121
|
-
mode
|
|
122
|
-
} = specialRule;
|
|
123
|
-
const from = new Date(interval.from);
|
|
124
|
-
from.setHours(0, 0, 0, 0);
|
|
125
|
-
const to = new Date(interval.to);
|
|
126
|
-
to.setHours(0, 0, 0, 0);
|
|
127
|
-
const dateInterval = Utils.getDateInterval(from, to);
|
|
128
|
-
setMode(mode);
|
|
129
|
-
setSelecting(false);
|
|
130
|
-
setSelectedDates(dateInterval);
|
|
131
|
-
}
|
|
132
|
-
}, [setMode, specialRule]);
|
|
133
90
|
const now = new Date();
|
|
134
91
|
const currentMonth = now.getMonth() + 1;
|
|
135
92
|
const currentYear = now.getFullYear();
|
|
136
93
|
const isPast = month <= currentMonth && year <= currentYear;
|
|
137
|
-
const
|
|
94
|
+
const showReset = !singleDate && selectedDates.length > 0;
|
|
95
|
+
const submitEnabled = !submitOnSelectionEnd && selectedDates.length > 0 && !selecting;
|
|
138
96
|
const hide2ndMonth = display !== Data.DISPLAYS.DESKTOP;
|
|
97
|
+
const enableAvailability = Boolean(stays);
|
|
98
|
+
const matchingStays = Utils.getMatchingStays(stays, selectedDates);
|
|
99
|
+
const allMatchingStaysEnd = enableAvailability ? matchingStays?.map(stay => Utils.formatDate(stay.end)) : undefined;
|
|
139
100
|
React.useEffect(() => {
|
|
140
101
|
if (availabilities) {
|
|
141
102
|
const fetchAvailabilities = async () => {
|
|
103
|
+
setIsLoading(true);
|
|
104
|
+
setError(undefined);
|
|
142
105
|
setStays(undefined);
|
|
143
106
|
const bareStart = `${year}-${Utils.zeroPad(month, 2)}-01`;
|
|
144
107
|
const start = Utils.formatDate(Utils.addDays(bareStart, -7));
|
|
@@ -147,89 +110,119 @@ function Calendar({
|
|
|
147
110
|
fetcher,
|
|
148
111
|
...rest
|
|
149
112
|
} = availabilities;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (stays?.length) {
|
|
158
|
-
const formatedStays = stays.map(stay => {
|
|
159
|
-
return {
|
|
160
|
-
start: new Date(stay.start),
|
|
161
|
-
end: new Date(stay.end)
|
|
162
|
-
};
|
|
113
|
+
try {
|
|
114
|
+
const {
|
|
115
|
+
stays
|
|
116
|
+
} = await fetcher({
|
|
117
|
+
...rest,
|
|
118
|
+
start,
|
|
119
|
+
numberDays
|
|
163
120
|
});
|
|
164
|
-
|
|
121
|
+
if (stays?.length) {
|
|
122
|
+
const formatedStays = stays.map(stay => {
|
|
123
|
+
return {
|
|
124
|
+
start: new Date(stay.start),
|
|
125
|
+
end: new Date(stay.end)
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
setStays(formatedStays);
|
|
129
|
+
}
|
|
130
|
+
} catch (e) {
|
|
131
|
+
setError(Messages.get(lang, "availability-loading-error"));
|
|
165
132
|
}
|
|
133
|
+
setIsLoading(false);
|
|
166
134
|
};
|
|
167
135
|
fetchAvailabilities();
|
|
168
136
|
}
|
|
169
|
-
}, [availabilities, hide2ndMonth, month, year]);
|
|
137
|
+
}, [availabilities, hide2ndMonth, lang, month, year]);
|
|
170
138
|
const classes = classNames(styles.calendar, {
|
|
171
139
|
[styles.calendarTouch]: hide2ndMonth,
|
|
172
|
-
[styles.
|
|
140
|
+
[styles.calendarLoading]: isLoading
|
|
173
141
|
});
|
|
174
142
|
return _jsxs("div", {
|
|
175
143
|
className: classes,
|
|
176
144
|
children: [!singleDate && _jsx(Helper, {
|
|
177
145
|
lang: lang,
|
|
178
146
|
selecting: selecting,
|
|
179
|
-
selectedDates: selectedDates
|
|
147
|
+
selectedDates: selectedDates,
|
|
148
|
+
availabilities: availabilities,
|
|
149
|
+
isLoading: isLoading,
|
|
150
|
+
error: error
|
|
180
151
|
}), _jsxs("div", {
|
|
181
|
-
className: styles.
|
|
182
|
-
children: [
|
|
183
|
-
className: styles.
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
152
|
+
className: styles.months,
|
|
153
|
+
children: [_jsxs("div", {
|
|
154
|
+
className: styles.controls,
|
|
155
|
+
children: [_jsx(Button, {
|
|
156
|
+
variant: "transparent",
|
|
157
|
+
className: styles.control,
|
|
158
|
+
onClick: gotoPreviousMonth,
|
|
159
|
+
disabled: isPast,
|
|
160
|
+
children: _jsx(Icons.ChevronLeft, {})
|
|
161
|
+
}), _jsx(Button, {
|
|
162
|
+
variant: "transparent",
|
|
163
|
+
className: styles.control,
|
|
164
|
+
onClick: gotoNextMonth,
|
|
165
|
+
children: _jsx(Icons.ChevronRight, {})
|
|
166
|
+
})]
|
|
167
|
+
}), _jsx(Month, {
|
|
168
|
+
display: display,
|
|
169
|
+
month: month,
|
|
170
|
+
year: year,
|
|
171
|
+
min: min,
|
|
172
|
+
max: max,
|
|
173
|
+
selecting: selecting,
|
|
174
|
+
setSelecting: setSelecting,
|
|
175
|
+
selectedDates: selectedDates,
|
|
176
|
+
setSelectedDates: setSelectedDates,
|
|
177
|
+
firstSelectedDate: firstSelectedDate,
|
|
178
|
+
setFirstSelectedDate: setFirstSelectedDate,
|
|
179
|
+
lastSelectedDate: lastSelectedDate,
|
|
180
|
+
setLastSelectedDate: setLastSelectedDate,
|
|
181
|
+
singleDate: singleDate,
|
|
182
|
+
submitOnSelectionEnd: submitOnSelectionEnd,
|
|
183
|
+
onSubmit: submit,
|
|
184
|
+
stays: stays,
|
|
185
|
+
matchingStays: matchingStays,
|
|
186
|
+
allMatchingStaysEnd: allMatchingStaysEnd
|
|
187
|
+
}), !hide2ndMonth && _jsx(Month, {
|
|
188
|
+
display: display,
|
|
189
|
+
month: monthAlt,
|
|
190
|
+
year: yearAlt,
|
|
191
|
+
min: min,
|
|
192
|
+
max: max,
|
|
193
|
+
selecting: selecting,
|
|
194
|
+
setSelecting: setSelecting,
|
|
195
|
+
selectedDates: selectedDates,
|
|
196
|
+
setSelectedDates: setSelectedDates,
|
|
197
|
+
firstSelectedDate: firstSelectedDate,
|
|
198
|
+
setFirstSelectedDate: setFirstSelectedDate,
|
|
199
|
+
lastSelectedDate: lastSelectedDate,
|
|
200
|
+
setLastSelectedDate: setLastSelectedDate,
|
|
201
|
+
singleDate: singleDate,
|
|
202
|
+
submitOnSelectionEnd: submitOnSelectionEnd,
|
|
203
|
+
onSubmit: submit,
|
|
204
|
+
stays: stays,
|
|
205
|
+
matchingStays: matchingStays,
|
|
206
|
+
allMatchingStaysEnd: allMatchingStaysEnd
|
|
207
|
+
})]
|
|
208
|
+
}), _jsxs("div", {
|
|
209
|
+
className: styles.buttons,
|
|
210
|
+
children: [_jsx(Button, {
|
|
211
|
+
variant: "transparent",
|
|
212
|
+
className: styles.close,
|
|
213
|
+
onClick: close,
|
|
214
|
+
children: Messages.get(lang, "close")
|
|
215
|
+
}), showReset && _jsx(Button, {
|
|
216
|
+
variant: "link",
|
|
217
|
+
className: styles.reset,
|
|
218
|
+
onClick: reset,
|
|
219
|
+
children: Messages.get(lang, "reset")
|
|
220
|
+
}), _jsxs(Button, {
|
|
221
|
+
className: styles.submit,
|
|
222
|
+
onClick: () => submit(selectedDates),
|
|
223
|
+
disabled: !submitEnabled,
|
|
224
|
+
children: [_jsx(Icons.Check, {}), Messages.get(lang, "submit")]
|
|
188
225
|
})]
|
|
189
|
-
}), _jsx(Month, {
|
|
190
|
-
mode: mode,
|
|
191
|
-
setMode: setMode,
|
|
192
|
-
display: display,
|
|
193
|
-
month: month,
|
|
194
|
-
year: year,
|
|
195
|
-
min: min,
|
|
196
|
-
max: max,
|
|
197
|
-
selecting: selecting,
|
|
198
|
-
setSelecting: setSelecting,
|
|
199
|
-
selectedDates: selectedDates,
|
|
200
|
-
setSelectedDates: setSelectedDates,
|
|
201
|
-
firstSelectedDate: firstSelectedDate,
|
|
202
|
-
setFirstSelectedDate: setFirstSelectedDate,
|
|
203
|
-
lastSelectedDate: lastSelectedDate,
|
|
204
|
-
setLastSelectedDate: setLastSelectedDate,
|
|
205
|
-
singleDate: singleDate,
|
|
206
|
-
submitOnSelectionEnd: submitOnSelectionEnd,
|
|
207
|
-
onSubmit: submit,
|
|
208
|
-
stays: stays
|
|
209
|
-
}), !hide2ndMonth && _jsx(Month, {
|
|
210
|
-
mode: mode,
|
|
211
|
-
setMode: setMode,
|
|
212
|
-
display: display,
|
|
213
|
-
month: monthAlt,
|
|
214
|
-
year: yearAlt,
|
|
215
|
-
min: min,
|
|
216
|
-
max: max,
|
|
217
|
-
selecting: selecting,
|
|
218
|
-
setSelecting: setSelecting,
|
|
219
|
-
selectedDates: selectedDates,
|
|
220
|
-
setSelectedDates: setSelectedDates,
|
|
221
|
-
firstSelectedDate: firstSelectedDate,
|
|
222
|
-
setFirstSelectedDate: setFirstSelectedDate,
|
|
223
|
-
lastSelectedDate: lastSelectedDate,
|
|
224
|
-
setLastSelectedDate: setLastSelectedDate,
|
|
225
|
-
singleDate: singleDate,
|
|
226
|
-
submitOnSelectionEnd: submitOnSelectionEnd,
|
|
227
|
-
onSubmit: submit,
|
|
228
|
-
stays: stays
|
|
229
|
-
}), showSubmit && _jsxs(Button, {
|
|
230
|
-
className: styles.submit,
|
|
231
|
-
onClick: () => submit(selectedDates),
|
|
232
|
-
children: [Messages.get(lang, "submit"), _jsx(Icons.Check, {})]
|
|
233
226
|
}), showPopup && _jsx(Popup, {
|
|
234
227
|
title: Messages.get(lang, "warning-date-change-title"),
|
|
235
228
|
className: datePickerStyles.popup,
|
|
@@ -2,16 +2,13 @@
|
|
|
2
2
|
grid-column: auto;
|
|
3
3
|
position: relative;
|
|
4
4
|
display: flex;
|
|
5
|
-
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
padding: 12px;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
|
-
@media (min-width:
|
|
9
|
+
@media (min-width: 746px) {
|
|
9
10
|
.calendar {
|
|
10
|
-
padding: 20px
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
.hiddenModes {
|
|
14
|
-
padding: 20px 10px;
|
|
11
|
+
padding: 20px;
|
|
15
12
|
}
|
|
16
13
|
}
|
|
17
14
|
|
|
@@ -19,21 +16,32 @@
|
|
|
19
16
|
flex: 0 0 auto;
|
|
20
17
|
}
|
|
21
18
|
|
|
19
|
+
.calendarLoading * {
|
|
20
|
+
cursor: wait !important;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.months {
|
|
24
|
+
position: relative;
|
|
25
|
+
display: flex;
|
|
26
|
+
gap: 20px;
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
.controls {
|
|
23
30
|
position: absolute;
|
|
24
|
-
top:
|
|
31
|
+
top: -4px;
|
|
25
32
|
left: 0;
|
|
26
33
|
width: 100%;
|
|
27
|
-
height:
|
|
34
|
+
height: 40px;
|
|
28
35
|
display: flex;
|
|
29
|
-
padding: 0
|
|
36
|
+
padding: 0 6px;
|
|
30
37
|
pointer-events: none;
|
|
31
38
|
touch-action: none;
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
.control {
|
|
35
|
-
|
|
36
|
-
height:
|
|
42
|
+
flex: 0 0 30px;
|
|
43
|
+
height: 30px;
|
|
44
|
+
padding: 2px;
|
|
37
45
|
fill: var(--ds-grey-500, #484848);
|
|
38
46
|
cursor: pointer;
|
|
39
47
|
user-select: none;
|
|
@@ -45,33 +53,28 @@
|
|
|
45
53
|
margin-left: auto;
|
|
46
54
|
}
|
|
47
55
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
56
|
+
.buttons {
|
|
57
|
+
display: flex;
|
|
58
|
+
justify-content: flex-end;
|
|
59
|
+
gap: 20px;
|
|
60
|
+
}
|
|
51
61
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
font-size:
|
|
57
|
-
|
|
58
|
-
animation: date-picker-submit-button-appearance 320ms
|
|
59
|
-
var(--ds-transition-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
60
|
-
border-radius: 0 0 var(--ds-radius-100, 3px) var(--ds-radius-100, 3px);
|
|
62
|
+
button.submit,
|
|
63
|
+
button.close {
|
|
64
|
+
--padding: 10px;
|
|
65
|
+
|
|
66
|
+
font-size: 16px;
|
|
67
|
+
border-radius: var(--ds-radius-200, 10px);
|
|
61
68
|
}
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
font-size: 20px;
|
|
66
|
-
}
|
|
70
|
+
button.close {
|
|
71
|
+
display: none;
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
@
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
60% {
|
|
74
|
-
transform: scale(1.15);
|
|
74
|
+
@media (min-width: 746px) {
|
|
75
|
+
button.close {
|
|
76
|
+
display: block;
|
|
77
|
+
margin-right: auto;
|
|
75
78
|
}
|
|
76
79
|
}
|
|
77
80
|
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import * as Utils from "./utils";
|
|
2
|
-
export const MODES = {
|
|
3
|
-
SATURDAY: 0,
|
|
4
|
-
SUNDAY: 1,
|
|
5
|
-
CUSTOM: 2
|
|
6
|
-
};
|
|
7
2
|
export const DISPLAYS = {
|
|
8
3
|
DESKTOP: 0,
|
|
9
4
|
TABLET: 1,
|
|
10
5
|
PHONE: 2
|
|
11
6
|
};
|
|
12
7
|
export const BREAKPOINTS = {
|
|
13
|
-
TABLET:
|
|
8
|
+
TABLET: 745,
|
|
14
9
|
PHONE: 650
|
|
15
10
|
};
|
|
16
11
|
export const THIS_YEAR = new Date().getFullYear();
|
|
@@ -47,22 +42,22 @@ export const MONTHS = {
|
|
|
47
42
|
};
|
|
48
43
|
export const WEEK_DAYS = {
|
|
49
44
|
fr: {
|
|
50
|
-
monday: "
|
|
51
|
-
tuesday: "
|
|
52
|
-
wednesday: "
|
|
53
|
-
thursday: "
|
|
54
|
-
friday: "
|
|
55
|
-
saturday: "
|
|
56
|
-
sunday: "
|
|
45
|
+
monday: "Lun.",
|
|
46
|
+
tuesday: "Mar.",
|
|
47
|
+
wednesday: "Mer.",
|
|
48
|
+
thursday: "Jeu.",
|
|
49
|
+
friday: "Ven.",
|
|
50
|
+
saturday: "Sam.",
|
|
51
|
+
sunday: "Dim."
|
|
57
52
|
},
|
|
58
53
|
en: {
|
|
59
|
-
monday: "
|
|
60
|
-
tuesday: "
|
|
61
|
-
wednesday: "
|
|
62
|
-
thursday: "
|
|
63
|
-
friday: "
|
|
64
|
-
saturday: "
|
|
65
|
-
sunday: "
|
|
54
|
+
monday: "Mon.",
|
|
55
|
+
tuesday: "Tue",
|
|
56
|
+
wednesday: "Wed.",
|
|
57
|
+
thursday: "Tue.",
|
|
58
|
+
friday: "Fri.",
|
|
59
|
+
saturday: "Sat.",
|
|
60
|
+
sunday: "Sun."
|
|
66
61
|
}
|
|
67
62
|
};
|
|
68
63
|
export const CALENDAR_WEEKS = 6;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import classNames from "classnames";
|
|
3
|
-
import
|
|
3
|
+
import { useUbloContext } from "ublo/with-ublo";
|
|
4
|
+
import Popover from "dt-design-system/es/popover";
|
|
5
|
+
import Button from "dt-design-system/es/button";
|
|
4
6
|
import * as Utils from "./utils";
|
|
7
|
+
import * as Messages from "./messages";
|
|
5
8
|
import styles from "./date-item.module.css";
|
|
6
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
export default function DateItem({
|
|
9
12
|
date,
|
|
10
13
|
index,
|
|
11
14
|
month,
|
|
@@ -16,34 +19,55 @@ const DateItem = ({
|
|
|
16
19
|
setSelectedDates,
|
|
17
20
|
setFirstSelectedDate,
|
|
18
21
|
setLastSelectedDate,
|
|
19
|
-
mode,
|
|
20
|
-
setMode,
|
|
21
22
|
selecting,
|
|
22
23
|
setSelecting,
|
|
23
24
|
singleDate,
|
|
24
25
|
submitOnSelectionEnd,
|
|
25
26
|
onSubmit,
|
|
26
|
-
stays
|
|
27
|
-
|
|
27
|
+
stays,
|
|
28
|
+
matchingStays,
|
|
29
|
+
allMatchingStaysEnd
|
|
30
|
+
}) {
|
|
31
|
+
const {
|
|
32
|
+
lang
|
|
33
|
+
} = useUbloContext();
|
|
28
34
|
const today = new Date();
|
|
29
|
-
const _date = new Date(date.join("-"));
|
|
35
|
+
const _date = React.useMemo(() => new Date(date.join("-")), [date]);
|
|
30
36
|
_date.setHours(0, 0, 0, 0);
|
|
31
37
|
const isToday = Utils.isSameDay(_date, today);
|
|
32
|
-
const
|
|
33
|
-
const
|
|
38
|
+
const isInMonth = month && year && Utils.isSameMonth(_date, new Date([Utils.zeroPad(year, 2), Utils.zeroPad(month, 2), "01"].join("-")));
|
|
39
|
+
const firstSelectedDate = selectedDates[0];
|
|
40
|
+
const isFirstSelected = selectedDates.map(Number).indexOf(Number(_date)) === 0;
|
|
41
|
+
const isLastSelected = selectedDates.map(Number).indexOf(Number(_date)) === selectedDates.length - 1;
|
|
42
|
+
const isPastDate = Utils.isPast(date) || selecting && firstSelectedDate && Utils.isBefore(date, firstSelectedDate);
|
|
43
|
+
const isSelected = selectedDates.some(d => d.getTime() === _date.getTime());
|
|
34
44
|
const enableAvailability = Boolean(stays);
|
|
35
45
|
const isAvailable = stays?.some(stay => {
|
|
36
|
-
|
|
46
|
+
const {
|
|
47
|
+
start,
|
|
48
|
+
end
|
|
49
|
+
} = stay;
|
|
50
|
+
const formatedStart = Utils.formatDate(start);
|
|
51
|
+
const formatedEnd = Utils.formatDate(end);
|
|
52
|
+
const formatedDate = Utils.formatDate(date);
|
|
53
|
+
return formatedStart === formatedDate || selecting && formatedEnd === formatedDate;
|
|
37
54
|
}) || false;
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
55
|
+
const shortestMatchingStaysLength = enableAvailability && matchingStays?.reduce((acc, stay) => {
|
|
56
|
+
const fromDate = new Date(stay.start);
|
|
57
|
+
const toDate = new Date(stay.end);
|
|
58
|
+
const days = Utils.getDateInterval(fromDate, toDate);
|
|
59
|
+
const nights = days.length - 1;
|
|
60
|
+
if (nights < acc) {
|
|
61
|
+
return nights;
|
|
62
|
+
}
|
|
63
|
+
return acc;
|
|
64
|
+
}, Infinity);
|
|
65
|
+
const isDisabled = enableAvailability && selecting && allMatchingStaysEnd?.length && !allMatchingStaysEnd.includes(date.join("-")) || enableAvailability && !isAvailable || isPastDate || !isInMonth || Utils.isBefore(date, min) || Utils.isAfter(date, max);
|
|
42
66
|
React.useEffect(() => {
|
|
43
67
|
if (isFirstSelected) setFirstSelectedDate(index);
|
|
44
68
|
if (isLastSelected) setLastSelectedDate(index);
|
|
45
69
|
}, [index, isFirstSelected, isLastSelected, setFirstSelectedDate, setLastSelectedDate]);
|
|
46
|
-
const updateDateSelection = () => {
|
|
70
|
+
const updateDateSelection = React.useCallback(() => {
|
|
47
71
|
if (isPastDate || isDisabled) return;
|
|
48
72
|
if (singleDate) {
|
|
49
73
|
setSelectedDates([_date]);
|
|
@@ -53,66 +77,51 @@ const DateItem = ({
|
|
|
53
77
|
}
|
|
54
78
|
return;
|
|
55
79
|
}
|
|
56
|
-
if (
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (Utils.isSaturday(date)) {
|
|
65
|
-
if (mode !== Data.MODES.SATURDAY) setMode(Data.MODES.SATURDAY);
|
|
66
|
-
setSelecting(false);
|
|
67
|
-
}
|
|
68
|
-
if (Utils.isSunday(date)) {
|
|
69
|
-
if (mode !== Data.MODES.SUNDAY) setMode(Data.MODES.SUNDAY);
|
|
70
|
-
setSelecting(false);
|
|
71
|
-
}
|
|
72
|
-
setSelectedDates(dates);
|
|
80
|
+
if (selecting) {
|
|
81
|
+
const isPastDate = _date < firstSelectedDate;
|
|
82
|
+
const interval = isPastDate ? Utils.getDateInterval(_date, firstSelectedDate) : Utils.getDateInterval(firstSelectedDate, _date);
|
|
83
|
+
setSelectedDates(interval);
|
|
84
|
+
setSelecting(false);
|
|
85
|
+
} else {
|
|
86
|
+
setSelectedDates([_date]);
|
|
87
|
+
setSelecting(true);
|
|
73
88
|
if (submitOnSelectionEnd) {
|
|
74
|
-
onSubmit(
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
if (mode === Data.MODES.CUSTOM || !Utils.isSaturday(date) && !Utils.isSunday(date) || display === Data.DISPLAYS.PHONE) {
|
|
78
|
-
if (mode !== Data.MODES.CUSTOM) setMode(Data.MODES.CUSTOM);
|
|
79
|
-
if (selecting) {
|
|
80
|
-
const isPastDate = _date < firstDate;
|
|
81
|
-
const interval = isPastDate ? Utils.getDateInterval(_date, firstDate) : Utils.getDateInterval(firstDate, _date);
|
|
82
|
-
setSelectedDates(interval);
|
|
83
|
-
if (interval.length === 8) {
|
|
84
|
-
if (Utils.isSaturday(interval[0]) && Utils.isSaturday(interval[7])) setMode(Data.MODES.SATURDAY);
|
|
85
|
-
if (Utils.isSunday(interval[0]) && Utils.isSunday(interval[7])) setMode(Data.MODES.SUNDAY);
|
|
86
|
-
}
|
|
87
|
-
setSelecting(false);
|
|
88
|
-
} else {
|
|
89
|
-
setSelectedDates([_date]);
|
|
90
|
-
setSelecting(true);
|
|
91
|
-
if (submitOnSelectionEnd) {
|
|
92
|
-
onSubmit([_date]);
|
|
93
|
-
}
|
|
89
|
+
onSubmit([_date]);
|
|
94
90
|
}
|
|
95
91
|
}
|
|
96
|
-
};
|
|
97
|
-
const isSelected = !!selectedDates.find(d => d.getTime() === _date.getTime());
|
|
92
|
+
}, [_date, firstSelectedDate, isDisabled, isPastDate, onSubmit, selecting, setSelectedDates, setSelecting, singleDate, submitOnSelectionEnd]);
|
|
98
93
|
const classes = classNames(styles.date, {
|
|
99
94
|
[styles.dateToday]: isToday,
|
|
100
95
|
[styles.dateSelected]: isSelected,
|
|
101
96
|
[styles.dateFirstSelected]: isFirstSelected,
|
|
102
97
|
[styles.dateLastSelected]: isLastSelected,
|
|
103
|
-
[styles.dateNotInMonth]: !
|
|
104
|
-
[styles.dateIsPast]:
|
|
105
|
-
[styles.dateSaturday]: mode === Data.MODES.SATURDAY && Utils.isSaturday(date),
|
|
106
|
-
[styles.dateSunday]: mode === Data.MODES.SUNDAY && Utils.isSunday(date),
|
|
98
|
+
[styles.dateNotInMonth]: !isInMonth,
|
|
99
|
+
[styles.dateIsPast]: !isSelected && isDisabled,
|
|
107
100
|
[styles.available]: enableAvailability && isAvailable,
|
|
108
|
-
[styles.notAvailable]: enableAvailability && !isAvailable
|
|
101
|
+
[styles.notAvailable]: enableAvailability && !isAvailable && !isSelected
|
|
109
102
|
});
|
|
110
|
-
|
|
103
|
+
const dateComponent = _jsx(Button, {
|
|
111
104
|
className: classes,
|
|
112
105
|
onClick: updateDateSelection,
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
disabled: !isSelected && isDisabled,
|
|
107
|
+
children: _jsx("span", {
|
|
108
|
+
children: _date.getDate()
|
|
109
|
+
})
|
|
116
110
|
});
|
|
117
|
-
|
|
118
|
-
|
|
111
|
+
const showPopover = enableAvailability && isInMonth && isFirstSelected && shortestMatchingStaysLength && selecting;
|
|
112
|
+
if (showPopover) {
|
|
113
|
+
const tooltip = Messages.get(lang, shortestMatchingStaysLength > 1 ? "min-nights-plural" : "min-nights-singular");
|
|
114
|
+
return _jsxs(Popover, {
|
|
115
|
+
trigger: dateComponent,
|
|
116
|
+
open: true,
|
|
117
|
+
className: styles.popover,
|
|
118
|
+
innerClassName: "nights-number-hint__inner",
|
|
119
|
+
contentProps: {
|
|
120
|
+
side: "top"
|
|
121
|
+
},
|
|
122
|
+
children: [shortestMatchingStaysLength, " ", tooltip]
|
|
123
|
+
});
|
|
124
|
+
} else {
|
|
125
|
+
return dateComponent;
|
|
126
|
+
}
|
|
127
|
+
}
|