willba-component-library 0.2.71 → 0.2.73
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/lib/components/FilterCalendar/components/Footer.d.ts +10 -0
- package/lib/core/components/calendar/utils/checkForContinuousSelection.d.ts +3 -2
- package/lib/index.esm.js +190 -76
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +190 -76
- package/lib/index.js.map +1 -1
- package/lib/index.umd.js +190 -76
- package/lib/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/assets/IconsSvg.tsx +2 -0
- package/src/components/FilterBar/components/buttons/tab-button/TabButton.css +1 -1
- package/src/components/FilterCalendar/FilterCalendar.css +14 -10
- package/src/components/FilterCalendar/FilterCalendar.stories.tsx +177 -426
- package/src/components/FilterCalendar/FilterCalendar.tsx +10 -91
- package/src/components/FilterCalendar/components/Footer.tsx +114 -0
- package/src/core/components/buttons/submit-button/SubmitButton.css +2 -0
- package/src/core/components/calendar/Calendar.css +18 -11
- package/src/core/components/calendar/Calendar.tsx +2 -1
- package/src/core/components/calendar/hooks/useCalendarTooltips.tsx +2 -0
- package/src/core/components/calendar/hooks/useUpdateDisabledDates.tsx +3 -1
- package/src/core/components/calendar/utils/checkForContinuousSelection.tsx +45 -12
- package/src/core/components/calendar/utils/handleCalendarModifiers.tsx +26 -6
- package/src/locales/en/common.json +2 -2
- package/src/locales/fi/common.json +3 -3
- package/src/themes/Default.css +7 -5
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { useTranslation } from 'react-i18next'
|
|
3
|
-
import { useMediaQuery } from 'react-responsive'
|
|
4
3
|
|
|
5
|
-
import useTheme
|
|
4
|
+
import useTheme from '../../themes/useTheme'
|
|
6
5
|
import '../../themes/Default.css'
|
|
7
|
-
import { Calendar,
|
|
6
|
+
import { Calendar, CloseButton } from '../../core/components'
|
|
8
7
|
import {
|
|
9
8
|
useAwaitRender,
|
|
10
9
|
useCloseFilterSection,
|
|
11
10
|
useUpdateTranslations,
|
|
12
11
|
} from '../../core/hooks'
|
|
13
|
-
import { nightsCount, parseDate } from '../../core/components/calendar/utils'
|
|
14
|
-
import { IconsSvg } from '../../assets/IconsSvg'
|
|
15
12
|
|
|
16
13
|
import { FilterCalendarTypes } from './FilterCalendarTypes'
|
|
17
14
|
import { useFilterCalendar } from './hooks/useFilterCalendar'
|
|
15
|
+
import { Footer } from './components/Footer'
|
|
18
16
|
|
|
19
17
|
import './FilterCalendar.css'
|
|
20
18
|
|
|
@@ -37,7 +35,6 @@ export default function FilterCalendar({
|
|
|
37
35
|
// Translations
|
|
38
36
|
useUpdateTranslations({ language })
|
|
39
37
|
const { t } = useTranslation()
|
|
40
|
-
const isMobile = useMediaQuery({ maxWidth: 690 })
|
|
41
38
|
|
|
42
39
|
const {
|
|
43
40
|
setCalendarRange,
|
|
@@ -70,10 +67,6 @@ export default function FilterCalendar({
|
|
|
70
67
|
handleSelectedFilter: setToggleCalendar,
|
|
71
68
|
})
|
|
72
69
|
|
|
73
|
-
const nights = nightsCount({
|
|
74
|
-
calendarRange: calendarRange,
|
|
75
|
-
})
|
|
76
|
-
|
|
77
70
|
return (
|
|
78
71
|
<div className={`will-root`} style={themePalette}>
|
|
79
72
|
{toggleCalendar && (
|
|
@@ -109,90 +102,16 @@ export default function FilterCalendar({
|
|
|
109
102
|
/>
|
|
110
103
|
</div>
|
|
111
104
|
<div className="will-calendar-footer">
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
<div>
|
|
120
|
-
<span>
|
|
121
|
-
{parseDate({
|
|
122
|
-
date: calendarRange?.from,
|
|
123
|
-
dateFormat: 'EEEEEE d.M.yyyy',
|
|
124
|
-
language,
|
|
125
|
-
}) || t('common:checkIn')}
|
|
126
|
-
</span>
|
|
127
|
-
<span className="will-calendar-footer-dates-separator">
|
|
128
|
-
-
|
|
129
|
-
</span>
|
|
130
|
-
<span>
|
|
131
|
-
{parseDate({
|
|
132
|
-
date: calendarRange?.to,
|
|
133
|
-
dateFormat: 'EEEEEE d.M.yyyy',
|
|
134
|
-
language,
|
|
135
|
-
}) || t('common:checkOut')}
|
|
136
|
-
</span>
|
|
137
|
-
</div>
|
|
138
|
-
)}
|
|
139
|
-
|
|
140
|
-
<span className="will-calendar-footer-booked">
|
|
141
|
-
{calendarHasError
|
|
142
|
-
? t(`filterBar:calendar.minNights`)
|
|
143
|
-
: nights
|
|
144
|
-
? `${nights} ${t(
|
|
145
|
-
`common:${nights === 1 ? 'night' : 'nights'}`
|
|
146
|
-
)}`
|
|
147
|
-
: ''}
|
|
148
|
-
</span>
|
|
149
|
-
</div>
|
|
150
|
-
|
|
151
|
-
{calendarHasError &&
|
|
152
|
-
isMobile &&
|
|
153
|
-
renderCalendarErrorMessage({
|
|
154
|
-
palette,
|
|
155
|
-
message: t(
|
|
156
|
-
`common:errors.calendarErrors.checkInAvailabilityError`
|
|
157
|
-
),
|
|
158
|
-
})}
|
|
159
|
-
|
|
160
|
-
<div className="will-calendar-footer-actions">
|
|
161
|
-
<SubmitButton
|
|
162
|
-
onClick={handleClearDates}
|
|
163
|
-
disabled={!calendarRange?.from}
|
|
164
|
-
label={t(`common:clearDates`)}
|
|
165
|
-
variant="text"
|
|
166
|
-
/>
|
|
167
|
-
</div>
|
|
168
|
-
</div>
|
|
169
|
-
|
|
170
|
-
{calendarHasError &&
|
|
171
|
-
!isMobile &&
|
|
172
|
-
renderCalendarErrorMessage({
|
|
173
|
-
palette,
|
|
174
|
-
message: t(
|
|
175
|
-
`common:errors.calendarErrors.checkInAvailabilityError`
|
|
176
|
-
),
|
|
177
|
-
})}
|
|
105
|
+
<Footer
|
|
106
|
+
calendarHasError={calendarHasError}
|
|
107
|
+
calendarRange={calendarRange}
|
|
108
|
+
handleClearDates={handleClearDates}
|
|
109
|
+
language={language}
|
|
110
|
+
palette={palette}
|
|
111
|
+
/>
|
|
178
112
|
</div>
|
|
179
113
|
</div>
|
|
180
114
|
)}
|
|
181
115
|
</div>
|
|
182
116
|
)
|
|
183
117
|
}
|
|
184
|
-
|
|
185
|
-
/////////
|
|
186
|
-
|
|
187
|
-
const renderCalendarErrorMessage = ({
|
|
188
|
-
message,
|
|
189
|
-
palette,
|
|
190
|
-
}: {
|
|
191
|
-
message?: string
|
|
192
|
-
palette: Palette
|
|
193
|
-
}) => (
|
|
194
|
-
<div className="will-calendar-footer-error">
|
|
195
|
-
<IconsSvg fill={palette?.error || 'inherit'} size={25} icon="warning" />
|
|
196
|
-
<span style={{ marginLeft: '10px' }}>{message || ''}</span>
|
|
197
|
-
</div>
|
|
198
|
-
)
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { useTranslation } from 'react-i18next'
|
|
3
|
+
import { useMediaQuery } from 'react-responsive'
|
|
4
|
+
import { DateRange } from 'react-day-picker'
|
|
5
|
+
|
|
6
|
+
import { Palette } from '../../../themes/useTheme'
|
|
7
|
+
import { nightsCount, parseDate } from '../../../core/components/calendar/utils'
|
|
8
|
+
import { IconsSvg } from '../../../assets/IconsSvg'
|
|
9
|
+
import { SubmitButton } from '../../../core/components'
|
|
10
|
+
|
|
11
|
+
export const Footer = ({
|
|
12
|
+
calendarHasError,
|
|
13
|
+
calendarRange,
|
|
14
|
+
handleClearDates,
|
|
15
|
+
language,
|
|
16
|
+
palette,
|
|
17
|
+
}: {
|
|
18
|
+
calendarHasError: boolean
|
|
19
|
+
calendarRange?: DateRange
|
|
20
|
+
handleClearDates: () => void
|
|
21
|
+
language?: string
|
|
22
|
+
palette: Palette
|
|
23
|
+
}) => {
|
|
24
|
+
const { t } = useTranslation()
|
|
25
|
+
const isMobile = useMediaQuery({ maxWidth: 600 })
|
|
26
|
+
|
|
27
|
+
const nights = nightsCount({
|
|
28
|
+
calendarRange: calendarRange,
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<>
|
|
33
|
+
<div className="will-calendar-footer-actions-wrapper">
|
|
34
|
+
<div className="will-calendar-footer-dates">
|
|
35
|
+
{calendarHasError ? (
|
|
36
|
+
<span>
|
|
37
|
+
{t(`common:errors.calendarErrors.checkInAvailabilityGuide`)}
|
|
38
|
+
</span>
|
|
39
|
+
) : (
|
|
40
|
+
<div>
|
|
41
|
+
<span>
|
|
42
|
+
{parseDate({
|
|
43
|
+
date: calendarRange?.from,
|
|
44
|
+
dateFormat: 'EEEEEE d.M.yyyy',
|
|
45
|
+
language,
|
|
46
|
+
}) || t('common:checkIn')}
|
|
47
|
+
</span>
|
|
48
|
+
<span className="will-calendar-footer-dates-separator">-</span>
|
|
49
|
+
<span>
|
|
50
|
+
{parseDate({
|
|
51
|
+
date: calendarRange?.to,
|
|
52
|
+
dateFormat: 'EEEEEE d.M.yyyy',
|
|
53
|
+
language,
|
|
54
|
+
}) || t('common:checkOut')}
|
|
55
|
+
</span>
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
|
|
59
|
+
<span className="will-calendar-footer-booked">
|
|
60
|
+
{calendarHasError
|
|
61
|
+
? `${1} ${t(`common:night`)} min`
|
|
62
|
+
: nights
|
|
63
|
+
? `${nights} ${t(`common:${nights === 1 ? 'night' : 'nights'}`)}`
|
|
64
|
+
: ''}
|
|
65
|
+
</span>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<div className="will-calendar-footer-error">
|
|
69
|
+
{calendarHasError &&
|
|
70
|
+
isMobile &&
|
|
71
|
+
renderCalendarErrorMessage({
|
|
72
|
+
palette,
|
|
73
|
+
message: t(
|
|
74
|
+
`common:errors.calendarErrors.checkInAvailabilityError`
|
|
75
|
+
),
|
|
76
|
+
})}
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div className="will-calendar-footer-actions">
|
|
80
|
+
<SubmitButton
|
|
81
|
+
onClick={handleClearDates}
|
|
82
|
+
disabled={!calendarRange?.from}
|
|
83
|
+
label={t(`common:clearDates`)}
|
|
84
|
+
variant="text"
|
|
85
|
+
/>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div className="will-calendar-footer-error">
|
|
90
|
+
{calendarHasError &&
|
|
91
|
+
!isMobile &&
|
|
92
|
+
renderCalendarErrorMessage({
|
|
93
|
+
palette,
|
|
94
|
+
message: t(`common:errors.calendarErrors.checkInAvailabilityError`),
|
|
95
|
+
})}
|
|
96
|
+
</div>
|
|
97
|
+
</>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/////////
|
|
102
|
+
|
|
103
|
+
const renderCalendarErrorMessage = ({
|
|
104
|
+
message,
|
|
105
|
+
palette,
|
|
106
|
+
}: {
|
|
107
|
+
message?: string
|
|
108
|
+
palette: Palette
|
|
109
|
+
}) => (
|
|
110
|
+
<>
|
|
111
|
+
<IconsSvg fill={palette?.error || 'inherit'} size={25} icon="warning" />
|
|
112
|
+
<span>{message || ''}</span>
|
|
113
|
+
</>
|
|
114
|
+
)
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
/* Calendar overrides */
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
.will-calendar-filter-container .DayPicker {
|
|
11
|
-
font-size: 25px;
|
|
10
|
+
font-size: 25px;
|
|
12
11
|
}
|
|
13
12
|
|
|
14
13
|
.will-calendar-filter-container .rdp-month {
|
|
@@ -67,7 +66,8 @@
|
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
.will-calendar-filter-container .rdp-cell .rdp-button[disabled] {
|
|
70
|
-
|
|
69
|
+
color: var(--will-transparent-black);
|
|
70
|
+
opacity: 1
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
@media (max-width: 960px) {
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
/*
|
|
88
|
+
/* Tooltips */
|
|
89
89
|
.will-root .will-calendar-filter-container .will-calendar-tooltip,
|
|
90
90
|
.will-root .will-calendar-filter-container .will-calendar-tooltip-check-out,
|
|
91
91
|
.will-root .will-calendar-filter-container .will-calendar-tooltip-overlapping-date,
|
|
@@ -158,15 +158,11 @@
|
|
|
158
158
|
|
|
159
159
|
/* No active selection */
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
/* ---- */
|
|
165
|
-
|
|
166
161
|
.will-root .will-calendar-filter-container .no-active-selection-start,
|
|
167
162
|
.will-root .will-calendar-filter-container .no-active-selection-mid,
|
|
168
163
|
.will-root .will-calendar-filter-container .no-active-selection-end {
|
|
169
164
|
position: initial;
|
|
165
|
+
|
|
170
166
|
}
|
|
171
167
|
|
|
172
168
|
.will-root .will-calendar-filter-container .no-active-selection-start::before,
|
|
@@ -179,7 +175,6 @@
|
|
|
179
175
|
border: 3px dashed var(--will-grey);
|
|
180
176
|
}
|
|
181
177
|
|
|
182
|
-
|
|
183
178
|
.will-root .will-calendar-filter-container .no-active-selection-start::before {
|
|
184
179
|
border-right: none;
|
|
185
180
|
border-top-left-radius: 50%;
|
|
@@ -202,7 +197,6 @@
|
|
|
202
197
|
color: inherit;
|
|
203
198
|
}
|
|
204
199
|
|
|
205
|
-
|
|
206
200
|
/* Overlapping date */
|
|
207
201
|
|
|
208
202
|
.will-root .will-calendar-filter-container .overlapping-date {
|
|
@@ -214,4 +208,17 @@
|
|
|
214
208
|
cursor: not-allowed;
|
|
215
209
|
}
|
|
216
210
|
|
|
211
|
+
@media (max-width: 600px) {
|
|
212
|
+
/* Tooltips */
|
|
213
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip,
|
|
214
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip-check-out,
|
|
215
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip-overlapping-date,
|
|
216
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip-check-out-only,
|
|
217
|
+
.will-root .will-calendar-filter-container .will-calendar-tooltip-check-in-only {
|
|
218
|
+
top: -70px;
|
|
219
|
+
white-space: wrap;
|
|
220
|
+
max-width: 120px;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
217
224
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { forwardRef
|
|
1
|
+
import React, { forwardRef } from 'react'
|
|
2
2
|
import { startOfDay } from 'date-fns'
|
|
3
3
|
import { fi, enUS } from 'date-fns/locale'
|
|
4
4
|
import { useTranslation } from 'react-i18next'
|
|
@@ -118,6 +118,7 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
118
118
|
rangeContext,
|
|
119
119
|
calendarRange,
|
|
120
120
|
calendarHasError,
|
|
121
|
+
disabledDates: newDisableCalendarDates?.disabledDates,
|
|
121
122
|
})
|
|
122
123
|
|
|
123
124
|
return (
|
|
@@ -119,5 +119,7 @@ export const useCalendarTooltips = ({ showFeedback }: Props) =>
|
|
|
119
119
|
tooltipClonesCheckOut.forEach((clone) => clone.remove())
|
|
120
120
|
tooltipClonesSpinner.forEach((clone) => clone.remove())
|
|
121
121
|
tooltipClonesOverlappingDates.forEach((clone) => clone.remove())
|
|
122
|
+
tooltipClonesCheckInOnly.forEach((clone) => clone.remove())
|
|
123
|
+
tooltipClonesCheckOutOnly.forEach((clone) => clone.remove())
|
|
122
124
|
}
|
|
123
125
|
})
|
|
@@ -85,7 +85,7 @@ export const useUpdateDisabledDates = ({
|
|
|
85
85
|
|
|
86
86
|
// Extract overlapping dates ( dates that are only available for checkout )
|
|
87
87
|
if (newOverlappingDates.length) {
|
|
88
|
-
setOverlappingDate(
|
|
88
|
+
setOverlappingDate([...newOverlappingDates])
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
const newDisableCalendarDates = {
|
|
@@ -103,5 +103,7 @@ export const useUpdateDisabledDates = ({
|
|
|
103
103
|
updateCalendarDefaultMonth,
|
|
104
104
|
])
|
|
105
105
|
|
|
106
|
+
console.log('1111', overlappingDate)
|
|
107
|
+
|
|
106
108
|
return { newDisableCalendarDates, overlappingDate, lastPossibleCheckout }
|
|
107
109
|
}
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { useEffect } from 'react'
|
|
2
2
|
import { DateRange } from 'react-day-picker'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
isAfter,
|
|
5
|
+
isEqual,
|
|
6
|
+
isBefore,
|
|
7
|
+
endOfDay,
|
|
8
|
+
isWithinInterval,
|
|
9
|
+
areIntervalsOverlapping,
|
|
10
|
+
} from 'date-fns'
|
|
4
11
|
|
|
5
|
-
import { RangeContext } from '../CalendarTypes'
|
|
12
|
+
import { DisableCalendarDates, RangeContext } from '../CalendarTypes'
|
|
6
13
|
|
|
7
14
|
type Props = {
|
|
8
15
|
setCalendarHasError?: (arg: boolean) => void
|
|
9
16
|
rangeContext?: RangeContext
|
|
10
17
|
calendarRange?: DateRange
|
|
11
18
|
calendarHasError?: boolean
|
|
19
|
+
disabledDates?: DisableCalendarDates['disabledDates']
|
|
12
20
|
}
|
|
13
21
|
|
|
14
22
|
// Case: If the selected dates do not overlap with the rangeContext during continuous selection,
|
|
@@ -20,34 +28,59 @@ export const checkForContinuousSelection = ({
|
|
|
20
28
|
rangeContext,
|
|
21
29
|
calendarRange,
|
|
22
30
|
calendarHasError,
|
|
31
|
+
disabledDates,
|
|
23
32
|
}: Props) => {
|
|
24
|
-
const calendarRangeFrom = calendarRange?.from
|
|
25
|
-
const calendarRangeTo = calendarRange?.to
|
|
26
|
-
const rangeContextFrom = rangeContext?.from
|
|
27
|
-
const rangeContextTo = rangeContext?.to
|
|
33
|
+
const calendarRangeFrom = calendarRange?.from && endOfDay(calendarRange.from)
|
|
34
|
+
const calendarRangeTo = calendarRange?.to && endOfDay(calendarRange.to)
|
|
35
|
+
const rangeContextFrom = rangeContext?.from && endOfDay(rangeContext.from)
|
|
36
|
+
const rangeContextTo = rangeContext?.to && endOfDay(rangeContext.to)
|
|
28
37
|
|
|
29
38
|
// Checking if rangeFrom is equal to or before rangeContextTo
|
|
30
39
|
const startIsEqualOrBeforeRangeContextEnd =
|
|
31
40
|
calendarRangeFrom && rangeContextTo
|
|
32
|
-
? isBefore(
|
|
33
|
-
isEqual(
|
|
41
|
+
? isBefore(calendarRangeFrom, rangeContextTo) ||
|
|
42
|
+
isEqual(calendarRangeFrom, rangeContextTo)
|
|
34
43
|
: null
|
|
35
44
|
|
|
36
45
|
// Checking if rangeTo is equal to or after rangeContextFrom
|
|
37
46
|
const endIsEqualOrAfterRangeContextStart =
|
|
38
47
|
calendarRangeTo && rangeContextFrom && rangeContextTo
|
|
39
|
-
? isAfter(
|
|
40
|
-
isEqual(
|
|
48
|
+
? isAfter(calendarRangeTo, rangeContextFrom) ||
|
|
49
|
+
isEqual(calendarRangeTo, rangeContextFrom)
|
|
41
50
|
: null
|
|
42
51
|
|
|
52
|
+
// Check if selection overlapping unavailable dates
|
|
53
|
+
const selectionOverlappingUnavailableDate = disabledDates?.find((range) => {
|
|
54
|
+
const rangeFrom = endOfDay(range.from)
|
|
55
|
+
const rangeTo = endOfDay(range.to)
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
rangeContextFrom &&
|
|
59
|
+
rangeContextTo &&
|
|
60
|
+
areIntervalsOverlapping(
|
|
61
|
+
{ start: rangeContextFrom, end: rangeContextTo },
|
|
62
|
+
{ start: rangeFrom, end: rangeTo }
|
|
63
|
+
) &&
|
|
64
|
+
calendarRangeFrom &&
|
|
65
|
+
calendarRangeTo &&
|
|
66
|
+
areIntervalsOverlapping(
|
|
67
|
+
{ start: calendarRangeFrom, end: calendarRangeTo },
|
|
68
|
+
{ start: rangeFrom, end: rangeTo }
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
})
|
|
72
|
+
|
|
43
73
|
useEffect(() => {
|
|
44
74
|
if (
|
|
45
75
|
(rangeContext &&
|
|
46
76
|
calendarRangeFrom &&
|
|
47
77
|
!startIsEqualOrBeforeRangeContextEnd) ||
|
|
48
|
-
(rangeContext &&
|
|
78
|
+
(rangeContext &&
|
|
79
|
+
calendarRangeTo &&
|
|
80
|
+
!endIsEqualOrAfterRangeContextStart) ||
|
|
81
|
+
selectionOverlappingUnavailableDate
|
|
49
82
|
) {
|
|
50
|
-
setCalendarHasError && !calendarHasError && setCalendarHasError(true)
|
|
83
|
+
!!(setCalendarHasError && !calendarHasError) && setCalendarHasError(true)
|
|
51
84
|
}
|
|
52
85
|
})
|
|
53
86
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { addDays, endOfDay } from 'date-fns'
|
|
1
|
+
import { addDays, endOfDay, isAfter, isBefore } from 'date-fns'
|
|
2
2
|
import { DateRange, Matcher } from 'react-day-picker'
|
|
3
3
|
|
|
4
4
|
import { DisableCalendarDates, RangeContext } from '../CalendarTypes'
|
|
@@ -47,6 +47,27 @@ export const handleCalendarModifiers = ({
|
|
|
47
47
|
const rangeContextFrom = rangeContext?.from && endOfDay(rangeContext.from)
|
|
48
48
|
const rangeContextTo = rangeContext?.to && endOfDay(rangeContext.to)
|
|
49
49
|
|
|
50
|
+
const filteredOverlappingDates = overlappingDate
|
|
51
|
+
? overlappingDate
|
|
52
|
+
.filter((date) => {
|
|
53
|
+
const dateFrom = date.from ? endOfDay(date.from) : null
|
|
54
|
+
const isBeforeRange =
|
|
55
|
+
dateFrom &&
|
|
56
|
+
findFirstPossibleRangeContextCheckIn?.checkIn &&
|
|
57
|
+
isBefore(dateFrom, findFirstPossibleRangeContextCheckIn?.checkIn)
|
|
58
|
+
const isAfterRange =
|
|
59
|
+
dateFrom &&
|
|
60
|
+
findLastPossibleRangeContextCheckOut?.lastCheckOut &&
|
|
61
|
+
isAfter(
|
|
62
|
+
dateFrom,
|
|
63
|
+
endOfDay(findLastPossibleRangeContextCheckOut?.lastCheckOut)
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return !(isBeforeRange || isAfterRange)
|
|
67
|
+
})
|
|
68
|
+
.map((date) => ({ from: date.from }))
|
|
69
|
+
: []
|
|
70
|
+
|
|
50
71
|
return {
|
|
51
72
|
booked: disabledDatesByPage.length
|
|
52
73
|
? disabledDatesByPage
|
|
@@ -70,11 +91,10 @@ export const handleCalendarModifiers = ({
|
|
|
70
91
|
? [{ after: calendarRangeFrom }]
|
|
71
92
|
: [],
|
|
72
93
|
|
|
73
|
-
overlappingDate:
|
|
74
|
-
|
|
75
|
-
?
|
|
76
|
-
: []
|
|
77
|
-
],
|
|
94
|
+
overlappingDate:
|
|
95
|
+
!calendarRangeFrom && !!filteredOverlappingDates.length
|
|
96
|
+
? filteredOverlappingDates.map((date) => ({ from: date.from }))
|
|
97
|
+
: [],
|
|
78
98
|
|
|
79
99
|
noActiveSelectionStart: rangeContextFrom || [],
|
|
80
100
|
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"checkInOnly": "Check-in only",
|
|
13
13
|
"errors": {
|
|
14
14
|
"calendarErrors": {
|
|
15
|
-
"checkInAvailabilityError": "
|
|
16
|
-
"checkInAvailabilityGuide": "
|
|
15
|
+
"checkInAvailabilityError": "All room reservations in a single purchase must be for the same dates.",
|
|
16
|
+
"checkInAvailabilityGuide": "If you need reservations for different dates, please make a separate purchase."
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"noCheckIn": "Huone ei saatavilla",
|
|
10
10
|
"noCheckOut": "Uloskirjaus ei saatavilla",
|
|
11
11
|
"checkOutOnly": "Vain uloskirjaus",
|
|
12
|
-
"checkInOnly": "
|
|
12
|
+
"checkInOnly": "Vain sisäänkirjautuminen",
|
|
13
13
|
"errors": {
|
|
14
14
|
"calendarErrors": {
|
|
15
|
-
"checkInAvailabilityError": "
|
|
16
|
-
"checkInAvailabilityGuide": "
|
|
15
|
+
"checkInAvailabilityError": "Yhdellä ostolla tehdyt huonevaraukset tulee olla samalle ajankohdalle.",
|
|
16
|
+
"checkInAvailabilityGuide": "Jos tarvitset huonevarauksia eri ajankohdille, ole hyvä ja tee uusi osto."
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
}
|
package/src/themes/Default.css
CHANGED
|
@@ -21,21 +21,23 @@
|
|
|
21
21
|
--will-onahau: #CDEEFF;
|
|
22
22
|
--will-text: #5A5959;
|
|
23
23
|
--will-charcoal-blue: #384265;
|
|
24
|
-
--will-transparent-white: rgba(255, 255, 255, 0.30);
|
|
25
|
-
--will-transparent-black: rgba(171, 167, 175, 0.30);
|
|
26
24
|
--will-error: #d32f2f;
|
|
27
25
|
|
|
28
|
-
/*
|
|
26
|
+
/* Transparent */
|
|
27
|
+
--will-transparent-black: rgba(0, 0, 0, 0.5);
|
|
28
|
+
--will-transparent-white: rgba(255, 255, 255, 0.30);
|
|
29
|
+
--will-transparent-lavender: rgba(171, 167, 175, 0.30);
|
|
30
|
+
|
|
31
|
+
/* Color mix */
|
|
29
32
|
--will-primary-lighter: color-mix(in srgb, var(--will-primary), white 50%);
|
|
30
33
|
--will-primary-lightest: color-mix(in srgb, var(--will-primary), white 80%);
|
|
31
34
|
|
|
32
35
|
|
|
33
|
-
/*
|
|
36
|
+
/* Shadows */
|
|
34
37
|
--will-box-shadow-dark: 0px 2px 12px 2px #a1a1a180;
|
|
35
38
|
--will-box-shadow-light: 0px 2px 12px 2px #bcb9b980;
|
|
36
39
|
|
|
37
40
|
/* Breakpoints */
|
|
38
|
-
|
|
39
41
|
--will-lg: 1140px;
|
|
40
42
|
--will-md: 960px;
|
|
41
43
|
--will-sm: 600px;
|