ublo-lib 1.2.4 → 1.3.0
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/hooks/use-in-view.js +40 -37
- package/es/esf/components/magic-box/services/api.js +1 -1
- package/es/esf/components/period-picker/controls.js +47 -0
- package/es/esf/components/period-picker/controls.module.css +36 -0
- package/es/esf/components/period-picker/date-display.js +67 -0
- package/es/esf/components/period-picker/date-display.module.css +18 -0
- package/es/esf/components/period-picker/days.js +112 -0
- package/es/esf/components/period-picker/days.module.css +113 -0
- package/es/esf/components/period-picker/extended-stay-picker.js +61 -0
- package/es/esf/components/period-picker/extended-stay-picker.module.css +50 -0
- package/es/esf/components/period-picker/index.js +4 -0
- package/es/esf/components/period-picker/messages.js +39 -0
- package/es/esf/components/period-picker/period-picker.js +202 -0
- package/es/esf/components/period-picker/period-picker.module.css +160 -0
- package/es/esf/components/period-picker/popup.js +42 -0
- package/es/esf/components/period-picker/popup.module.css +21 -0
- package/es/esf/components/period-picker/services/dates.js +101 -0
- package/es/esf/components/period-picker/services/events.js +7 -0
- package/es/esf/components/period-picker/services/motions.js +38 -0
- package/es/esf/components/period-picker/services/sections.js +24 -0
- package/es/esf/components/period-picker/services/stay.js +27 -0
- package/es/esf/components/period-picker/services/utils.js +0 -0
- package/es/esf/components/period-picker/title.js +33 -0
- package/es/esf/components/period-picker/title.module.css +6 -0
- package/es/esf/components/period-picker/warning.js +59 -0
- package/es/esf/components/period-picker/warning.module.css +53 -0
- package/es/esf/components/period-picker/weeks.js +120 -0
- package/es/esf/components/period-picker/weeks.module.css +194 -0
- package/package.json +1 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import classnames from "classnames";
|
|
3
|
+
import { useUbloContext } from "ublo/with-ublo";
|
|
4
|
+
import * as Icons from "dt-design-system/es/icons";
|
|
5
|
+
import Title from "./title";
|
|
6
|
+
import Controls from "./controls";
|
|
7
|
+
import Weeks from "./weeks";
|
|
8
|
+
import Warning from "./warning";
|
|
9
|
+
import ExtendedStayPicker from "./extended-stay-picker";
|
|
10
|
+
import Popup from "./popup";
|
|
11
|
+
import * as Sections from "./services/sections";
|
|
12
|
+
import * as Dates from "./services/dates";
|
|
13
|
+
import * as Stay from "./services/stay";
|
|
14
|
+
import css from "./period-picker.module.css";
|
|
15
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
16
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
17
|
+
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
18
|
+
const WEEK_STORAGE = "stayWeek";
|
|
19
|
+
const EXTEND_STAY_PICKER_APPEARANCE_DELAY = 1000;
|
|
20
|
+
|
|
21
|
+
const PeriodPicker = ({
|
|
22
|
+
setClosed,
|
|
23
|
+
force,
|
|
24
|
+
onChange,
|
|
25
|
+
isPopup
|
|
26
|
+
}) => {
|
|
27
|
+
const ref = React.useRef();
|
|
28
|
+
const {
|
|
29
|
+
config,
|
|
30
|
+
cmsMode,
|
|
31
|
+
metadata
|
|
32
|
+
} = useUbloContext();
|
|
33
|
+
const {
|
|
34
|
+
start,
|
|
35
|
+
end,
|
|
36
|
+
forceSeasonSwitch = false,
|
|
37
|
+
extend
|
|
38
|
+
} = config.season;
|
|
39
|
+
const [stay, setStay] = React.useState();
|
|
40
|
+
const [warn, setWarn] = React.useState(false);
|
|
41
|
+
const [chosenWeek, setChosenWeek] = React.useState();
|
|
42
|
+
const [opened, setOpened] = React.useState(true);
|
|
43
|
+
const [selected, setSelected] = React.useState();
|
|
44
|
+
const [extendedOpened, setExtendedOpened] = React.useState(false);
|
|
45
|
+
const [extendedTimeout, setExtendedTimeout] = React.useState();
|
|
46
|
+
const mustFilterSections = cmsMode === undefined;
|
|
47
|
+
const weeks = Dates.buildWeeks(start, end);
|
|
48
|
+
const beginWeek = weeks[0];
|
|
49
|
+
const endWeek = weeks[weeks.length - 1];
|
|
50
|
+
const showDialog = force && selected === null;
|
|
51
|
+
const pickerClasses = classnames(css.picker, {
|
|
52
|
+
[css.pickerDialogOpened]: showDialog && mustFilterSections,
|
|
53
|
+
[css.pickerEditing]: !mustFilterSections
|
|
54
|
+
});
|
|
55
|
+
const openExtendedPicker = React.useCallback(() => {
|
|
56
|
+
if (extend) {
|
|
57
|
+
clearTimeout(extendedTimeout);
|
|
58
|
+
setExtendedTimeout(setTimeout(() => setExtendedOpened(true), EXTEND_STAY_PICKER_APPEARANCE_DELAY));
|
|
59
|
+
}
|
|
60
|
+
}, [extend, extendedTimeout]);
|
|
61
|
+
const selectWeek = React.useCallback((week, force = false) => {
|
|
62
|
+
const hasCart = window.sessionStorage.getItem("cartId");
|
|
63
|
+
|
|
64
|
+
if (force || !hasCart) {
|
|
65
|
+
setSelected(previousWeek => {
|
|
66
|
+
if (previousWeek !== undefined && previousWeek !== null && previousWeek !== week) {
|
|
67
|
+
window.sessionStorage.removeItem("cartId");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
setWarn(false);
|
|
71
|
+
setChosenWeek(undefined);
|
|
72
|
+
return week;
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (mustFilterSections && week !== null && week !== undefined) {
|
|
76
|
+
Sections.filter(week, mustFilterSections);
|
|
77
|
+
} else {
|
|
78
|
+
Sections.removeFilter();
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
setWarn(true);
|
|
82
|
+
setChosenWeek(week);
|
|
83
|
+
}
|
|
84
|
+
}, [mustFilterSections]);
|
|
85
|
+
const getStoredStay = React.useCallback(e => {
|
|
86
|
+
const storedStay = window.sessionStorage.getItem("stay");
|
|
87
|
+
|
|
88
|
+
if (storedStay) {
|
|
89
|
+
const newStay = JSON.parse(storedStay);
|
|
90
|
+
setStay(newStay);
|
|
91
|
+
}
|
|
92
|
+
}, []);
|
|
93
|
+
const updateStay = React.useCallback(e => {
|
|
94
|
+
setStay(e.detail);
|
|
95
|
+
}, []);
|
|
96
|
+
React.useEffect(() => {
|
|
97
|
+
getStoredStay();
|
|
98
|
+
window.addEventListener("msem-stay-changed", updateStay);
|
|
99
|
+
return () => {
|
|
100
|
+
window.removeEventListener("msem-stay-changed", updateStay);
|
|
101
|
+
};
|
|
102
|
+
}, [getStoredStay, updateStay]);
|
|
103
|
+
React.useEffect(() => {
|
|
104
|
+
if (!mustFilterSections) {
|
|
105
|
+
Sections.removeFilter();
|
|
106
|
+
}
|
|
107
|
+
}, [mustFilterSections]);
|
|
108
|
+
React.useEffect(() => {
|
|
109
|
+
const stored = window.sessionStorage.getItem(WEEK_STORAGE);
|
|
110
|
+
selectWeek(stored !== null ? Number(stored) : null, true);
|
|
111
|
+
}, [selectWeek]);
|
|
112
|
+
React.useEffect(() => {
|
|
113
|
+
if (selected !== null && selected !== undefined) {
|
|
114
|
+
const stored = window.sessionStorage.getItem(WEEK_STORAGE);
|
|
115
|
+
const storedSelected = stored !== null ? Number(stored) : null;
|
|
116
|
+
|
|
117
|
+
if (storedSelected !== selected) {
|
|
118
|
+
const startDate = Dates.weekToDate(selected, endWeek, forceSeasonSwitch);
|
|
119
|
+
const endDate = Dates.weekToDate(selected + 1, endWeek, forceSeasonSwitch);
|
|
120
|
+
const range = {
|
|
121
|
+
from: Dates.format(startDate),
|
|
122
|
+
to: Dates.format(endDate)
|
|
123
|
+
};
|
|
124
|
+
window.sessionStorage.setItem(WEEK_STORAGE, selected);
|
|
125
|
+
Stay.update(range);
|
|
126
|
+
|
|
127
|
+
if (typeof onChange === "function") {
|
|
128
|
+
onChange(range);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}, [endWeek, forceSeasonSwitch, onChange, selected]);
|
|
133
|
+
if (metadata?.disableWeekpicker) return null;
|
|
134
|
+
|
|
135
|
+
const select = week => {
|
|
136
|
+
selectWeek(week);
|
|
137
|
+
|
|
138
|
+
if (setClosed !== undefined) {
|
|
139
|
+
setClosed(week);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const selectAndClose = week => {
|
|
144
|
+
selectWeek(week);
|
|
145
|
+
setOpened(false);
|
|
146
|
+
openExtendedPicker();
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
return _jsxs(_Fragment, {
|
|
150
|
+
children: [_jsx("div", {
|
|
151
|
+
className: pickerClasses,
|
|
152
|
+
children: _jsxs("div", {
|
|
153
|
+
className: css.inner,
|
|
154
|
+
children: [_jsxs("div", {
|
|
155
|
+
className: css.header,
|
|
156
|
+
children: [_jsx("div", {
|
|
157
|
+
className: css.iconContainer,
|
|
158
|
+
children: _jsx(Icons.Calendar, {
|
|
159
|
+
className: css.icon
|
|
160
|
+
})
|
|
161
|
+
}), _jsx(Title, {
|
|
162
|
+
stay: stay
|
|
163
|
+
}), _jsx(Controls, {
|
|
164
|
+
barRef: ref,
|
|
165
|
+
distance: 200
|
|
166
|
+
})]
|
|
167
|
+
}), _jsx(Weeks, {
|
|
168
|
+
ref: ref,
|
|
169
|
+
weeks: weeks,
|
|
170
|
+
beginWeek: beginWeek,
|
|
171
|
+
endWeek: endWeek,
|
|
172
|
+
selected: selected,
|
|
173
|
+
select: select,
|
|
174
|
+
forceSeasonSwitch: forceSeasonSwitch,
|
|
175
|
+
openExtendedPicker: openExtendedPicker,
|
|
176
|
+
isPopup: isPopup
|
|
177
|
+
}), _jsx(Warning, {
|
|
178
|
+
warn: warn,
|
|
179
|
+
setWarn: setWarn,
|
|
180
|
+
selectWeek: selectWeek,
|
|
181
|
+
chosenWeek: chosenWeek
|
|
182
|
+
}), _jsx(ExtendedStayPicker, {
|
|
183
|
+
stay: stay,
|
|
184
|
+
extend: extend,
|
|
185
|
+
week: selected,
|
|
186
|
+
endWeek: endWeek,
|
|
187
|
+
forceSeasonSwitch: forceSeasonSwitch,
|
|
188
|
+
opened: extendedOpened,
|
|
189
|
+
setExtendedOpened: setExtendedOpened
|
|
190
|
+
})]
|
|
191
|
+
})
|
|
192
|
+
}), _jsx(Popup, {
|
|
193
|
+
mustFilterSections: mustFilterSections,
|
|
194
|
+
showDialog: showDialog,
|
|
195
|
+
opened: opened,
|
|
196
|
+
selectAndClose: selectAndClose,
|
|
197
|
+
onChange: onChange
|
|
198
|
+
})]
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
export default React.memo(PeriodPicker);
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
.picker {
|
|
2
|
+
color: var(--ds-grey-700, #171e30);
|
|
3
|
+
background-color: var(--ds-grey-000, #ffffff);
|
|
4
|
+
border-radius: inherit;
|
|
5
|
+
box-shadow: var(--ds-shadow-200, 0 5px 10px rgba(0, 0, 0, 0.12));
|
|
6
|
+
transition: opacity 160ms
|
|
7
|
+
var(--ds-transition-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
8
|
+
animation: period-picker-appearance 320ms
|
|
9
|
+
var(--ds-transition-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
10
|
+
overflow: hidden;
|
|
11
|
+
|
|
12
|
+
/* @media (prefers-color-scheme: dark) {
|
|
13
|
+
--ds-grey-000: #171e30;
|
|
14
|
+
--ds-grey-100: #2d303c;
|
|
15
|
+
--ds-grey-200: #484848;
|
|
16
|
+
--ds-grey-300: #d2d2d2;
|
|
17
|
+
--ds-grey-400: #d4d4d4;
|
|
18
|
+
--ds-grey-500: #efefef;
|
|
19
|
+
--ds-grey-600: #f5f5f5;
|
|
20
|
+
--ds-grey-700: #fff;
|
|
21
|
+
} */
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@keyframes period-picker-appearance {
|
|
25
|
+
0% {
|
|
26
|
+
opacity: 0;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.picker * {
|
|
31
|
+
outline: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.picker *:focus-visible {
|
|
35
|
+
outline: var(--ds-focus-ring-width, 2px) solid
|
|
36
|
+
var(--ds-focus-ring-color, var(--ds-blue-400, #4177f6));
|
|
37
|
+
outline-offset: var(--ds-focus-ring-offset, 2px);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.inner {
|
|
41
|
+
position: relative;
|
|
42
|
+
display: flex;
|
|
43
|
+
flex-direction: column;
|
|
44
|
+
gap: 32px;
|
|
45
|
+
padding: 24px 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@media (min-width: 1100px) {
|
|
49
|
+
.inner {
|
|
50
|
+
padding: 46px 0;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.header {
|
|
55
|
+
position: relative;
|
|
56
|
+
width: 100%;
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
justify-content: center;
|
|
60
|
+
align-items: center;
|
|
61
|
+
gap: 12px;
|
|
62
|
+
margin: 0 auto;
|
|
63
|
+
padding: 0 10px;
|
|
64
|
+
text-align: center;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@media (min-width: 640px) {
|
|
68
|
+
.header {
|
|
69
|
+
flex-direction: row;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.iconContainer {
|
|
74
|
+
flex: 0 0 38px;
|
|
75
|
+
width: 38px;
|
|
76
|
+
height: 38px;
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: center;
|
|
80
|
+
background-color: var(--ds-secondary, var(--ds-blue-400, #4177f6));
|
|
81
|
+
border-radius: calc(var(--ds-radius-100, 3px) * 2);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.icon {
|
|
85
|
+
width: 22px;
|
|
86
|
+
height: 22px;
|
|
87
|
+
fill: var(--ds-grey-000, #ffffff);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.title {
|
|
91
|
+
flex: 0 0 auto;
|
|
92
|
+
font-size: 20px;
|
|
93
|
+
text-transform: uppercase;
|
|
94
|
+
text-align: center;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.content {
|
|
98
|
+
position: relative;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* CMS EDITING OVERRIDE */
|
|
102
|
+
@media (min-width: 565px) {
|
|
103
|
+
.pickerEditing {
|
|
104
|
+
position: relative;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.pickerEditing::before {
|
|
108
|
+
content: "";
|
|
109
|
+
position: absolute;
|
|
110
|
+
top: 0;
|
|
111
|
+
left: 0;
|
|
112
|
+
width: 100%;
|
|
113
|
+
height: 100%;
|
|
114
|
+
backdrop-filter: blur(var(--ds-blur, 8px));
|
|
115
|
+
background-color: rgba(0, 0, 0, 0.05);
|
|
116
|
+
pointer-events: none;
|
|
117
|
+
touch-action: none;
|
|
118
|
+
opacity: 0;
|
|
119
|
+
z-index: 2;
|
|
120
|
+
transition: opacity 160ms
|
|
121
|
+
var(--ds-transition-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.pickerEditing:not(:hover)::before {
|
|
125
|
+
opacity: 1;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.pickerEditing::after {
|
|
129
|
+
content: "Sélecteur de séjour désactivé en mode édition";
|
|
130
|
+
position: absolute;
|
|
131
|
+
top: 50%;
|
|
132
|
+
left: 50%;
|
|
133
|
+
font-size: 14px;
|
|
134
|
+
color: var(--ds-grey-000, #ffffff);
|
|
135
|
+
text-transform: uppercase;
|
|
136
|
+
font-family: "Open Sans", sans-serif;
|
|
137
|
+
letter-spacing: 1px;
|
|
138
|
+
background: var(
|
|
139
|
+
--cms-blue-gradient,
|
|
140
|
+
linear-gradient(
|
|
141
|
+
175deg,
|
|
142
|
+
var(--cms-blue-400, #4177f6),
|
|
143
|
+
var(--cms-blue-500, #004cc2)
|
|
144
|
+
)
|
|
145
|
+
);
|
|
146
|
+
padding: 5px 20px;
|
|
147
|
+
border-radius: var(--ds-radius-200, 10px);
|
|
148
|
+
transform: translate(-50%, -50%);
|
|
149
|
+
opacity: 0;
|
|
150
|
+
pointer-events: none;
|
|
151
|
+
touch-action: none;
|
|
152
|
+
transition: opacity 160ms
|
|
153
|
+
var(--ds-transition-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
154
|
+
z-index: 2;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.pickerEditing:not(:hover)::after {
|
|
158
|
+
opacity: 1;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as ReactDOM from "react-dom";
|
|
3
|
+
import { AnimatePresence, motion } from "framer-motion";
|
|
4
|
+
import PeriodPicker from "./period-picker";
|
|
5
|
+
import * as Motions from "./services/motions";
|
|
6
|
+
import css from "./popup.module.css";
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
|
|
9
|
+
const Popup = ({
|
|
10
|
+
mustFilterSections,
|
|
11
|
+
showDialog,
|
|
12
|
+
opened,
|
|
13
|
+
onChange,
|
|
14
|
+
selectAndClose
|
|
15
|
+
}) => {
|
|
16
|
+
const [ready, setReady] = React.useState(false);
|
|
17
|
+
React.useEffect(() => {
|
|
18
|
+
setReady(true);
|
|
19
|
+
}, []);
|
|
20
|
+
if (!ready) return null;
|
|
21
|
+
const isVisible = mustFilterSections && showDialog && opened;
|
|
22
|
+
return ReactDOM.createPortal(_jsx(AnimatePresence, {
|
|
23
|
+
mode: "wait",
|
|
24
|
+
children: isVisible && _jsx("div", {
|
|
25
|
+
className: css.popup,
|
|
26
|
+
children: _jsx(motion.div, {
|
|
27
|
+
initial: "hidden",
|
|
28
|
+
animate: "visible",
|
|
29
|
+
exit: "hidden",
|
|
30
|
+
variants: Motions.fading,
|
|
31
|
+
className: css.inner,
|
|
32
|
+
children: _jsx(PeriodPicker, {
|
|
33
|
+
onChange: onChange,
|
|
34
|
+
setClosed: selectAndClose,
|
|
35
|
+
isPopup: true
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
}), document.body);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default Popup;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.popup {
|
|
2
|
+
position: fixed;
|
|
3
|
+
top: 0;
|
|
4
|
+
left: 0;
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100%;
|
|
7
|
+
display: flex;
|
|
8
|
+
align-items: center;
|
|
9
|
+
justify-content: center;
|
|
10
|
+
padding: 5px;
|
|
11
|
+
backdrop-filter: blur(var(--ds-blur, 8px));
|
|
12
|
+
background-color: rgba(0, 0, 0, 0.24);
|
|
13
|
+
transition: opacity 160ms
|
|
14
|
+
var(--ds-transition-easing, cubic-bezier(0.4, 0, 0.2, 1));
|
|
15
|
+
z-index: var(--ds-floating-z-index, 100);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.inner {
|
|
19
|
+
max-width: 98vw;
|
|
20
|
+
border-radius: var(--ds-radius-200, 10px);
|
|
21
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export const locales = {
|
|
2
|
+
fr: "fr-FR",
|
|
3
|
+
en: "en-UK",
|
|
4
|
+
nl: "nl-NL"
|
|
5
|
+
};
|
|
6
|
+
export const padStart = (value, count, pad) => {
|
|
7
|
+
let str = String(value);
|
|
8
|
+
|
|
9
|
+
while (str.length < count) {
|
|
10
|
+
str = pad + str;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return str;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const createDate = (...args) => {
|
|
17
|
+
const ref = new Date(...args);
|
|
18
|
+
const yy = ref.getFullYear();
|
|
19
|
+
const mm = padStart(ref.getMonth() + 1, 2, 0);
|
|
20
|
+
const dd = padStart(ref.getDate(), 2, 0);
|
|
21
|
+
const str = `${yy}-${mm}-${dd}`;
|
|
22
|
+
return new Date(str);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const getPrevSaturday = date => {
|
|
26
|
+
const clone = createDate(date);
|
|
27
|
+
const day = 1 + clone.getDay();
|
|
28
|
+
const prevSaturday = clone.getDate() - day % 7;
|
|
29
|
+
clone.setDate(prevSaturday);
|
|
30
|
+
return clone;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const addDays = (date, days) => {
|
|
34
|
+
const clone = createDate(date);
|
|
35
|
+
clone.setDate(clone.getDate() + days);
|
|
36
|
+
return clone;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const christmasWeek = (endWeek, forceSeasonSwitch) => {
|
|
40
|
+
const now = createDate();
|
|
41
|
+
const year = now.getFullYear();
|
|
42
|
+
const month = now.getMonth();
|
|
43
|
+
const date = now.getDate();
|
|
44
|
+
const isAfterChristmas = month === 11 && date >= 25;
|
|
45
|
+
const lastChristmasYear = isAfterChristmas || !isAfterChristmas && forceSeasonSwitch ? year : year - 1;
|
|
46
|
+
const lastChristmas = createDate(lastChristmasYear, 11, 25);
|
|
47
|
+
const nextChristmas = createDate(lastChristmasYear + 1, 11, 25);
|
|
48
|
+
const dateSeasonEnd = addDays(getPrevSaturday(lastChristmas), endWeek * 7);
|
|
49
|
+
return getPrevSaturday(now <= dateSeasonEnd ? lastChristmas : nextChristmas);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const weekToDate = (week, endWeek, forceSeasonSwitch) => addDays(christmasWeek(endWeek, forceSeasonSwitch), week * 7);
|
|
53
|
+
export const formatShort = date => {
|
|
54
|
+
const dd = padStart(date.getDate(), 2, 0);
|
|
55
|
+
return dd;
|
|
56
|
+
};
|
|
57
|
+
export const weekToLongDate = (week, endWeek, forceSeasonSwitch) => {
|
|
58
|
+
const date = weekToDate(week, endWeek, forceSeasonSwitch);
|
|
59
|
+
const dd = padStart(date.getDate(), 2, 0);
|
|
60
|
+
const mm = padStart(date.getMonth() + 1, 2, 0);
|
|
61
|
+
const yy = date.getFullYear();
|
|
62
|
+
return `${dd}/${mm}/${yy}`;
|
|
63
|
+
};
|
|
64
|
+
export const format = date => {
|
|
65
|
+
const dd = padStart(date.getDate(), 2, 0);
|
|
66
|
+
const mm = padStart(date.getMonth() + 1, 2, 0);
|
|
67
|
+
const yy = date.getFullYear();
|
|
68
|
+
return `${yy}-${mm}-${dd}`;
|
|
69
|
+
};
|
|
70
|
+
export const getInterval = (startDate, endDate, pad = {
|
|
71
|
+
before: 0,
|
|
72
|
+
after: 0
|
|
73
|
+
}) => {
|
|
74
|
+
const dates = [];
|
|
75
|
+
|
|
76
|
+
const addDays = function (days) {
|
|
77
|
+
const date = new Date(this.valueOf());
|
|
78
|
+
date.setDate(date.getDate() + days);
|
|
79
|
+
return date;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
let currentDate = addDays.call(startDate, -pad?.before || 0);
|
|
83
|
+
const endDateWithPad = addDays.call(endDate, pad?.after || 0);
|
|
84
|
+
|
|
85
|
+
while (currentDate <= endDateWithPad) {
|
|
86
|
+
dates.push(currentDate);
|
|
87
|
+
currentDate = addDays.call(currentDate, 1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return dates;
|
|
91
|
+
};
|
|
92
|
+
export const buildWeeks = (start, end) => {
|
|
93
|
+
const length = end - start;
|
|
94
|
+
const array = [];
|
|
95
|
+
|
|
96
|
+
for (let i = 0; i < length; i++) {
|
|
97
|
+
array.push(start + i);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return array;
|
|
101
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const transition = {
|
|
2
|
+
duration: 0.64,
|
|
3
|
+
ease: "easeInOut"
|
|
4
|
+
};
|
|
5
|
+
export const scaling = {
|
|
6
|
+
hidden: {
|
|
7
|
+
opacity: 0,
|
|
8
|
+
scale: 1.1,
|
|
9
|
+
transition
|
|
10
|
+
},
|
|
11
|
+
visible: {
|
|
12
|
+
opacity: 1,
|
|
13
|
+
scale: 1,
|
|
14
|
+
transition
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export const fading = {
|
|
18
|
+
hidden: {
|
|
19
|
+
opacity: 0,
|
|
20
|
+
transition
|
|
21
|
+
},
|
|
22
|
+
visible: {
|
|
23
|
+
opacity: 1,
|
|
24
|
+
transition
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
export const character = {
|
|
28
|
+
hidden: {
|
|
29
|
+
opacity: 0,
|
|
30
|
+
y: `0.15em`,
|
|
31
|
+
transition
|
|
32
|
+
},
|
|
33
|
+
visible: {
|
|
34
|
+
opacity: 1,
|
|
35
|
+
y: `0em`,
|
|
36
|
+
transition
|
|
37
|
+
}
|
|
38
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const getFiltrableSections = () => Array.from(document.querySelectorAll("section[data-weeks]"));
|
|
2
|
+
|
|
3
|
+
export const removeFilter = () => {
|
|
4
|
+
const filtrables = getFiltrableSections();
|
|
5
|
+
filtrables.forEach(section => {
|
|
6
|
+
if (section.originalDisplayStyle !== undefined) {
|
|
7
|
+
section.style.display = section.originalDisplayStyle;
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
export const filter = week => {
|
|
12
|
+
const search = String(week);
|
|
13
|
+
const filtrables = getFiltrableSections();
|
|
14
|
+
filtrables.forEach(section => {
|
|
15
|
+
const weeks = section.dataset.weeks.split(",").filter(week => week !== "");
|
|
16
|
+
const visible = weeks.length === 0 || weeks.indexOf(search) !== -1;
|
|
17
|
+
|
|
18
|
+
if (section.originalDisplayStyle === undefined) {
|
|
19
|
+
section.originalDisplayStyle = section.style.display;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
section.style.display = visible ? section.originalDisplayStyle : "none";
|
|
23
|
+
});
|
|
24
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as Events from "./events";
|
|
2
|
+
import * as Dates from "./dates";
|
|
3
|
+
import * as Messages from "../messages";
|
|
4
|
+
export const update = stay => {
|
|
5
|
+
window.sessionStorage.setItem("stay", JSON.stringify(stay));
|
|
6
|
+
Events.fire(window, "msem-stay-changed", stay);
|
|
7
|
+
};
|
|
8
|
+
export const formatStay = (lang, stay) => {
|
|
9
|
+
const locale = Dates.locales[lang] || Dates.locales.en;
|
|
10
|
+
const from = new Date(stay.from);
|
|
11
|
+
const to = new Date(stay.to);
|
|
12
|
+
const fromDay = from.getDate();
|
|
13
|
+
const toDay = to.getDate();
|
|
14
|
+
const isOneDayStay = from.getTime() === to.getTime();
|
|
15
|
+
const fromMonth = from.getMonth();
|
|
16
|
+
const toMonth = to.getMonth();
|
|
17
|
+
const hasMonthChanged = fromMonth !== toMonth;
|
|
18
|
+
const fromMonthLabel = hasMonthChanged ? `${from.toLocaleDateString(locale, {
|
|
19
|
+
month: "long"
|
|
20
|
+
})} ` : "";
|
|
21
|
+
const toMonthLabel = to.toLocaleDateString(locale, {
|
|
22
|
+
month: "long"
|
|
23
|
+
});
|
|
24
|
+
if (isOneDayStay) return `${toDay} ${toMonthLabel}`;
|
|
25
|
+
const dates = `${fromDay} ${fromMonthLabel}${Messages.get(lang, "to")} ${toDay} ${toMonthLabel}`;
|
|
26
|
+
return dates;
|
|
27
|
+
};
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { useUbloContext } from "ublo/with-ublo";
|
|
3
|
+
import * as Messages from "./messages";
|
|
4
|
+
import * as Stay from "./services/stay";
|
|
5
|
+
import css from "./title.module.css";
|
|
6
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
+
|
|
8
|
+
const Title = ({
|
|
9
|
+
stay
|
|
10
|
+
}) => {
|
|
11
|
+
const {
|
|
12
|
+
lang
|
|
13
|
+
} = useUbloContext();
|
|
14
|
+
|
|
15
|
+
if (!stay) {
|
|
16
|
+
return _jsx("div", {
|
|
17
|
+
className: css.title,
|
|
18
|
+
dangerouslySetInnerHTML: {
|
|
19
|
+
__html: Messages.get(lang, "title")
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const formatedStay = Stay.formatStay(lang, stay);
|
|
25
|
+
return _jsx("div", {
|
|
26
|
+
className: css.title,
|
|
27
|
+
dangerouslySetInnerHTML: {
|
|
28
|
+
__html: `${Messages.get(lang, "selected-title")} ${formatedStay}`
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default Title;
|