willba-component-library 0.2.55 → 0.2.56
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/assets/IconsSvg.d.ts +9 -0
- package/lib/components/FilterBar/FilterBar.stories.d.ts +1 -1
- package/lib/components/FilterCalendar/FilterCalendar.d.ts +1 -1
- package/lib/components/FilterCalendar/FilterCalendar.stories.d.ts +2 -1
- package/lib/components/FilterCalendar/hooks/useFilterCalendar.d.ts +3 -3
- package/lib/core/components/calendar/CalendarTypes.d.ts +8 -6
- package/lib/core/components/calendar/hooks/index.d.ts +3 -0
- package/lib/core/components/calendar/hooks/useCalendarLoadingSpinner.d.ts +7 -0
- package/lib/core/components/calendar/hooks/useCalendarTooltips.d.ts +10 -0
- package/lib/core/components/calendar/hooks/useUpdateDisabledDates.d.ts +13 -0
- package/lib/core/components/calendar/utils/calendarSelectionRules.d.ts +15 -0
- package/lib/core/components/calendar/utils/checkForContinuousSelection.d.ts +10 -0
- package/lib/core/components/calendar/utils/disabledDatesByPage.d.ts +9 -0
- package/lib/core/components/calendar/utils/handleCalendarModifiers.d.ts +46 -0
- package/lib/core/components/calendar/utils/handleRangeContextDisabledDates.d.ts +27 -0
- package/lib/core/components/calendar/utils/index.d.ts +8 -0
- package/lib/core/components/calendar/utils/nightsCount.d.ts +6 -0
- package/lib/core/components/calendar/utils/parseDate.d.ts +7 -0
- package/lib/core/components/calendar/utils/parseDates.d.ts +6 -0
- package/lib/index.d.ts +10 -7
- package/lib/index.esm.js +646 -273
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +646 -273
- package/lib/index.js.map +1 -1
- package/lib/index.umd.js +646 -273
- package/lib/index.umd.js.map +1 -1
- package/lib/themes/useTheme.d.ts +2 -0
- package/package.json +1 -1
- package/src/assets/IconsSvg.tsx +66 -0
- package/src/components/FilterBar/FilterBar.stories.tsx +2 -1
- package/src/components/FilterBar/FilterBar.tsx +1 -1
- package/src/components/FilterCalendar/FilterCalendar.css +8 -9
- package/src/components/FilterCalendar/FilterCalendar.stories.tsx +345 -158
- package/src/components/FilterCalendar/FilterCalendar.tsx +69 -52
- package/src/components/FilterCalendar/FilterCalendarTypes.ts +0 -1
- package/src/components/FilterCalendar/hooks/useFilterCalendar.ts +44 -4
- package/src/core/components/buttons/submit-button/SubmitButton.tsx +1 -4
- package/src/core/components/calendar/Calendar.css +24 -6
- package/src/core/components/calendar/Calendar.tsx +127 -382
- package/src/core/components/calendar/CalendarTypes.ts +9 -4
- package/src/core/components/calendar/hooks/index.ts +3 -0
- package/src/core/components/calendar/hooks/useCalendarLoadingSpinner.tsx +25 -0
- package/src/core/components/calendar/hooks/useCalendarTooltips.tsx +139 -0
- package/src/core/components/calendar/hooks/useUpdateDisabledDates.tsx +94 -0
- package/src/core/components/calendar/utils/calendarSelectionRules.tsx +163 -0
- package/src/core/components/calendar/utils/checkForContinuousSelection.tsx +50 -0
- package/src/core/components/calendar/utils/disabledDatesByPage.tsx +36 -0
- package/src/core/components/calendar/utils/handleCalendarModifiers.tsx +151 -0
- package/src/core/components/calendar/utils/handleRangeContextDisabledDates.tsx +70 -0
- package/src/core/components/calendar/utils/index.ts +8 -0
- package/src/themes/Default.css +6 -0
- package/src/themes/useTheme.tsx +3 -0
- package/src/assets/SpinnerSvg.tsx +0 -40
- package/src/core/utils/handleOverlappingDates.tsx +0 -3
- package/src/core/utils/index.ts +0 -3
- /package/src/core/{utils → components/calendar/utils}/nightsCount.tsx +0 -0
- /package/src/core/{utils → components/calendar/utils}/parseDate.tsx +0 -0
- /package/src/core/{utils → components/calendar/utils}/parseDates.tsx +0 -0
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import React, { forwardRef
|
|
2
|
-
import {
|
|
3
|
-
addDays,
|
|
4
|
-
startOfDay,
|
|
5
|
-
format,
|
|
6
|
-
isAfter,
|
|
7
|
-
isEqual,
|
|
8
|
-
isBefore,
|
|
9
|
-
} from 'date-fns'
|
|
1
|
+
import React, { forwardRef } from 'react'
|
|
2
|
+
import { startOfDay, isBefore, endOfDay, isEqual, isAfter } from 'date-fns'
|
|
10
3
|
import { fi, enUS } from 'date-fns/locale'
|
|
11
4
|
import { useTranslation } from 'react-i18next'
|
|
12
|
-
import { DateRange, DayPicker
|
|
5
|
+
import { DateRange, DayPicker } from 'react-day-picker'
|
|
13
6
|
import { useMediaQuery } from 'react-responsive'
|
|
14
7
|
|
|
15
|
-
import { CalendarTypes
|
|
16
|
-
import {
|
|
8
|
+
import { CalendarTypes } from './CalendarTypes'
|
|
9
|
+
import { IconsSvg } from '../../../assets/IconsSvg'
|
|
10
|
+
import {
|
|
11
|
+
calendarSelectionRules,
|
|
12
|
+
checkForContinuousSelection,
|
|
13
|
+
handleCalendarModifiers,
|
|
14
|
+
disabledDatesByPage as handleDisabledDatesByPage,
|
|
15
|
+
handleRangeContextDisabledDates,
|
|
16
|
+
} from './utils'
|
|
17
|
+
import {
|
|
18
|
+
useCalendarLoadingSpinner,
|
|
19
|
+
useCalendarTooltips,
|
|
20
|
+
useUpdateDisabledDates,
|
|
21
|
+
} from './hooks'
|
|
17
22
|
|
|
18
23
|
import 'react-day-picker/dist/style.css'
|
|
19
24
|
import './Calendar.css'
|
|
@@ -33,10 +38,12 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
33
38
|
setUpdateCalendarMonthNavigation,
|
|
34
39
|
updateCalendarDefaultMoth,
|
|
35
40
|
loadingData,
|
|
36
|
-
initialCalendarRange,
|
|
37
41
|
showFeedback,
|
|
38
42
|
palette,
|
|
39
|
-
|
|
43
|
+
setCalendarHasError,
|
|
44
|
+
setUpdatedForSubmit,
|
|
45
|
+
rangeContext,
|
|
46
|
+
calendarHasError,
|
|
40
47
|
}: CalendarTypes,
|
|
41
48
|
ref
|
|
42
49
|
) => {
|
|
@@ -46,81 +53,17 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
46
53
|
const isTablet = useMediaQuery({ maxWidth: 960 })
|
|
47
54
|
const today = startOfDay(new Date())
|
|
48
55
|
const selectedStartDate = calendarRange?.from
|
|
56
|
+
const rangeContextStartDate = rangeContext?.from
|
|
49
57
|
|
|
50
58
|
// Handle overlapping availableDates.lastCheckOut and disabledDates.start
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const dateFormat = 'dd-MM-yyyy'
|
|
58
|
-
|
|
59
|
-
const { disabledDates } = disableCalendarDates
|
|
60
|
-
|
|
61
|
-
const { updatedDisabledDates, newOverlappingDates } = (
|
|
62
|
-
disabledDates || []
|
|
63
|
-
).reduce(
|
|
64
|
-
(
|
|
65
|
-
acc: {
|
|
66
|
-
updatedDisabledDates: { to: Date; from: Date }[]
|
|
67
|
-
newOverlappingDates: { to: Date; from: Date }[]
|
|
68
|
-
},
|
|
69
|
-
dateRange
|
|
70
|
-
) => {
|
|
71
|
-
const formattedFromDate = format(dateRange.from, dateFormat)
|
|
72
|
-
const formattedToDate = format(dateRange.to, dateFormat)
|
|
73
|
-
|
|
74
|
-
const hasTwoOverlappingDates =
|
|
75
|
-
disableCalendarDates.availableDates?.some(
|
|
76
|
-
(item) =>
|
|
77
|
-
format(item.lastCheckOut, dateFormat) === formattedFromDate &&
|
|
78
|
-
format(item.lastCheckOut, dateFormat) === formattedToDate
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
const hasOneOverlappingDate =
|
|
82
|
-
disableCalendarDates.availableDates?.some(
|
|
83
|
-
(item) =>
|
|
84
|
-
format(item.lastCheckOut, dateFormat) === formattedFromDate &&
|
|
85
|
-
format(item.lastCheckOut, dateFormat) !== formattedToDate
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
-
if (hasTwoOverlappingDates) {
|
|
89
|
-
acc.newOverlappingDates.push(dateRange)
|
|
90
|
-
} else if (hasOneOverlappingDate) {
|
|
91
|
-
acc.newOverlappingDates.push(dateRange)
|
|
92
|
-
acc.updatedDisabledDates.push({
|
|
93
|
-
...dateRange,
|
|
94
|
-
from: addDays(dateRange.from, 1),
|
|
95
|
-
})
|
|
96
|
-
} else {
|
|
97
|
-
acc.updatedDisabledDates.push(dateRange)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return acc
|
|
101
|
-
},
|
|
102
|
-
{ updatedDisabledDates: [], newOverlappingDates: [] }
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
if (newOverlappingDates.length) {
|
|
106
|
-
setOverlappingDate((prev = []) => [...prev, ...newOverlappingDates])
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const newDisableCalendarDates = {
|
|
110
|
-
...disableCalendarDates,
|
|
111
|
-
disabledDates: updatedDisabledDates,
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return newDisableCalendarDates
|
|
59
|
+
const { newDisableCalendarDates, overlappingDate } = useUpdateDisabledDates(
|
|
60
|
+
{
|
|
61
|
+
disableCalendarDates,
|
|
62
|
+
calendarRange,
|
|
63
|
+
updateCalendarMonthNavigation,
|
|
64
|
+
updateCalendarDefaultMoth,
|
|
115
65
|
}
|
|
116
|
-
|
|
117
|
-
}, [
|
|
118
|
-
disableCalendarDates,
|
|
119
|
-
calendarRange,
|
|
120
|
-
updateCalendarMonthNavigation,
|
|
121
|
-
initialCalendarRange,
|
|
122
|
-
updateCalendarDefaultMoth,
|
|
123
|
-
])
|
|
66
|
+
)
|
|
124
67
|
|
|
125
68
|
// Handle disable dates by page
|
|
126
69
|
const disabledDatesByPage = handleDisabledDatesByPage({
|
|
@@ -130,106 +73,59 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
130
73
|
})
|
|
131
74
|
|
|
132
75
|
// Handle tooltip
|
|
133
|
-
|
|
134
|
-
if (typeof document === 'undefined' || !showFeedback) return
|
|
135
|
-
|
|
136
|
-
// Children
|
|
137
|
-
const calendarTooltip = document.querySelector('.will-calendar-tooltip')
|
|
138
|
-
const calendarTooltipCheckOut = document.querySelector(
|
|
139
|
-
'.will-calendar-tooltip-check-out'
|
|
140
|
-
)
|
|
141
|
-
|
|
142
|
-
const calendarTooltipOverlappingDate = document.querySelector(
|
|
143
|
-
'.will-calendar-tooltip-overlapping-date'
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
const loadingSpinner = document.querySelector(
|
|
147
|
-
'.will-filter-bar-calendar .will-calendar-spinner'
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
// Parents
|
|
151
|
-
const calendarButtons = document.querySelectorAll(
|
|
152
|
-
'.will-filter-bar-calendar .rdp-cell:has(.booked):not(:has(.disabled-after-check-in))'
|
|
153
|
-
)
|
|
154
|
-
const calendarButtonsCheckOut = document.querySelectorAll(
|
|
155
|
-
'.will-filter-bar-calendar .rdp-cell:has(.booked.disabled-after-check-in)'
|
|
156
|
-
)
|
|
157
|
-
const calendarMonthContainer = document.querySelector(
|
|
158
|
-
'.will-filter-bar-calendar .rdp-months'
|
|
159
|
-
)
|
|
160
|
-
const calendarOverlappingDate = document.querySelectorAll(
|
|
161
|
-
'.will-filter-bar-calendar .rdp-cell:has(.overlapping-date)'
|
|
162
|
-
)
|
|
163
|
-
|
|
164
|
-
const tooltipClonesCheckIn: Element[] = []
|
|
165
|
-
const tooltipClonesCheckOut: Element[] = []
|
|
166
|
-
const tooltipClonesSpinner: Element[] = []
|
|
167
|
-
const tooltipClonesOverlappingDates: Element[] = []
|
|
168
|
-
|
|
169
|
-
if (calendarTooltip && calendarButtons.length > 0) {
|
|
170
|
-
calendarButtons.forEach((element) => {
|
|
171
|
-
const tooltipClone: Element = calendarTooltip.cloneNode(
|
|
172
|
-
true
|
|
173
|
-
) as Element
|
|
174
|
-
element.appendChild(tooltipClone)
|
|
175
|
-
tooltipClonesCheckIn.push(tooltipClone)
|
|
176
|
-
})
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (calendarTooltipCheckOut && calendarButtonsCheckOut.length > 0) {
|
|
180
|
-
calendarButtonsCheckOut.forEach((element) => {
|
|
181
|
-
const tooltipClone: Element = calendarTooltipCheckOut.cloneNode(
|
|
182
|
-
true
|
|
183
|
-
) as Element
|
|
184
|
-
element.appendChild(tooltipClone)
|
|
185
|
-
tooltipClonesCheckOut.push(tooltipClone)
|
|
186
|
-
})
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (loadingSpinner && calendarMonthContainer) {
|
|
190
|
-
const tooltipClone: Element = loadingSpinner.cloneNode(true) as Element
|
|
191
|
-
calendarMonthContainer.appendChild(tooltipClone)
|
|
192
|
-
tooltipClonesSpinner.push(tooltipClone)
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
if (
|
|
196
|
-
calendarTooltipOverlappingDate &&
|
|
197
|
-
calendarOverlappingDate.length > 0
|
|
198
|
-
) {
|
|
199
|
-
calendarOverlappingDate.forEach((element) => {
|
|
200
|
-
const tooltipClone: Element =
|
|
201
|
-
calendarTooltipOverlappingDate.cloneNode(true) as Element
|
|
202
|
-
element.appendChild(tooltipClone)
|
|
203
|
-
tooltipClonesOverlappingDates.push(tooltipClone)
|
|
204
|
-
})
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
return () => {
|
|
208
|
-
tooltipClonesCheckIn.forEach((clone) => clone.remove())
|
|
209
|
-
tooltipClonesCheckOut.forEach((clone) => clone.remove())
|
|
210
|
-
tooltipClonesSpinner.forEach((clone) => clone.remove())
|
|
211
|
-
tooltipClonesOverlappingDates.forEach((clone) => clone.remove())
|
|
212
|
-
}
|
|
213
|
-
}, [
|
|
76
|
+
useCalendarTooltips({
|
|
214
77
|
calendarRange,
|
|
215
78
|
updateCalendarMonthNavigation,
|
|
216
79
|
overlappingDate,
|
|
217
|
-
initialCalendarRange,
|
|
218
80
|
updateCalendarDefaultMoth,
|
|
219
|
-
|
|
81
|
+
showFeedback,
|
|
82
|
+
})
|
|
220
83
|
|
|
221
84
|
// Handle loading spinner
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
85
|
+
useCalendarLoadingSpinner({
|
|
86
|
+
loadingData,
|
|
87
|
+
updateCalendarMonthNavigation,
|
|
88
|
+
updateCalendarDefaultMoth,
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
// Handle the date selection and availability for selection logic.
|
|
92
|
+
const handleOnSelect = (range?: DateRange) => {
|
|
93
|
+
setCalendarHasError && calendarHasError && setCalendarHasError(false)
|
|
94
|
+
|
|
95
|
+
calendarSelectionRules({
|
|
96
|
+
range,
|
|
97
|
+
newDisableCalendarDates,
|
|
98
|
+
setCalendarRange,
|
|
99
|
+
setDisabledDates,
|
|
100
|
+
calendarRange,
|
|
101
|
+
overlappingDate,
|
|
102
|
+
setCalendarHasError,
|
|
103
|
+
rangeContext,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
setUpdatedForSubmit && setUpdatedForSubmit(true)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Handle disabled dates for range context
|
|
110
|
+
const {
|
|
111
|
+
findFirstPossibleRangeContextCheckIn,
|
|
112
|
+
findLastPossibleRangeContextCheckOut,
|
|
113
|
+
firstPossibleRangeContextCheckIn,
|
|
114
|
+
lastPossibleRangeContextCheckOut,
|
|
115
|
+
currentSelectionLastCheckoutDate,
|
|
116
|
+
} = handleRangeContextDisabledDates({
|
|
117
|
+
rangeContext,
|
|
118
|
+
availableDates: newDisableCalendarDates?.availableDates,
|
|
119
|
+
calendarRange,
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
// Handle check for continuous selection in the range context
|
|
123
|
+
checkForContinuousSelection({
|
|
124
|
+
setCalendarHasError,
|
|
125
|
+
rangeContext,
|
|
126
|
+
calendarRange,
|
|
127
|
+
calendarHasError,
|
|
128
|
+
})
|
|
233
129
|
|
|
234
130
|
return (
|
|
235
131
|
<div className="will-filter-bar-calendar" ref={ref}>
|
|
@@ -242,21 +138,12 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
242
138
|
numberOfMonths={!isTablet ? 2 : 1}
|
|
243
139
|
weekStartsOn={1}
|
|
244
140
|
selected={calendarRange}
|
|
245
|
-
onSelect={(range) =>
|
|
246
|
-
handleSelectedCheckIn({
|
|
247
|
-
range,
|
|
248
|
-
newDisableCalendarDates,
|
|
249
|
-
setCalendarRange,
|
|
250
|
-
setDisabledDates,
|
|
251
|
-
calendarRange,
|
|
252
|
-
overlappingDate,
|
|
253
|
-
setOverlappingDates,
|
|
254
|
-
})
|
|
255
|
-
}
|
|
141
|
+
onSelect={(range) => handleOnSelect(range)}
|
|
256
142
|
captionLayout="dropdown-buttons"
|
|
257
143
|
defaultMonth={
|
|
258
|
-
|
|
144
|
+
calendarRange?.from ||
|
|
259
145
|
selectedStartDate ||
|
|
146
|
+
rangeContextStartDate ||
|
|
260
147
|
(newDisableCalendarDates?.disabledDates?.length
|
|
261
148
|
? newDisableCalendarDates.disabledDates[0].from
|
|
262
149
|
: today)
|
|
@@ -265,8 +152,18 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
265
152
|
disabledDatesByPage.length
|
|
266
153
|
? disabledDatesByPage
|
|
267
154
|
: disabledDates?.length
|
|
268
|
-
?
|
|
269
|
-
|
|
155
|
+
? [
|
|
156
|
+
...disabledDates,
|
|
157
|
+
...firstPossibleRangeContextCheckIn,
|
|
158
|
+
...lastPossibleRangeContextCheckOut,
|
|
159
|
+
]
|
|
160
|
+
: newDisableCalendarDates?.disabledDates?.length
|
|
161
|
+
? [
|
|
162
|
+
...newDisableCalendarDates.disabledDates,
|
|
163
|
+
...firstPossibleRangeContextCheckIn,
|
|
164
|
+
...lastPossibleRangeContextCheckOut,
|
|
165
|
+
]
|
|
166
|
+
: []
|
|
270
167
|
}
|
|
271
168
|
fromMonth={today}
|
|
272
169
|
onMonthChange={(val) => {
|
|
@@ -275,55 +172,43 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
275
172
|
setUpdateCalendarMonthNavigation((prev) => !prev))
|
|
276
173
|
: null
|
|
277
174
|
}}
|
|
175
|
+
classNames={{
|
|
176
|
+
day_range_start: calendarRange?.from ? 'rdp-day_range_start' : '',
|
|
177
|
+
day_range_end: calendarRange?.to ? 'rdp-day_range_end' : '',
|
|
178
|
+
}}
|
|
278
179
|
modifiersClassNames={{
|
|
279
180
|
today: 'my-today',
|
|
280
181
|
booked: 'booked',
|
|
281
182
|
disabledAfterCheckIn: 'disabled-after-check-in',
|
|
282
183
|
overlappingDate: 'overlapping-date',
|
|
283
|
-
|
|
284
184
|
noActiveSelectionStart:
|
|
285
|
-
'rdp-day_selected rdp-day_range_start no-active-selection
|
|
185
|
+
'rdp-day_selected rdp-day_range_start no-active-selection',
|
|
286
186
|
noActiveSelectionMid:
|
|
287
187
|
'rdp-day_selected rdp-day_range_middle no-active-selection',
|
|
288
188
|
noActiveSelectionEnd:
|
|
289
189
|
'rdp-day_selected rdp-day_range_end no-active-selection',
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
booked: disabledDatesByPage.length
|
|
293
|
-
? disabledDatesByPage
|
|
294
|
-
: disabledDates?.length
|
|
295
|
-
? disabledDates
|
|
296
|
-
: newDisableCalendarDates?.disabledDates || [],
|
|
297
|
-
|
|
298
|
-
disabledAfterCheckIn: calendarRange?.from
|
|
299
|
-
? [{ after: calendarRange.from }]
|
|
300
|
-
: [],
|
|
190
|
+
checkoutOptionsMid:
|
|
191
|
+
'rdp-day_selected rdp-day_range_middle checkout-option',
|
|
301
192
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
: [],
|
|
305
|
-
noActiveSelectionMid:
|
|
306
|
-
!calendarRange &&
|
|
307
|
-
initialCalendarRange?.from &&
|
|
308
|
-
initialCalendarRange?.to
|
|
309
|
-
? [
|
|
310
|
-
{
|
|
311
|
-
after: initialCalendarRange?.from,
|
|
312
|
-
before: initialCalendarRange?.to,
|
|
313
|
-
},
|
|
314
|
-
]
|
|
315
|
-
: [],
|
|
316
|
-
noActiveSelectionEnd: !calendarRange
|
|
317
|
-
? initialCalendarRange?.to || []
|
|
318
|
-
: [],
|
|
319
|
-
|
|
320
|
-
overlappingDate:
|
|
321
|
-
(!calendarRange?.from &&
|
|
322
|
-
overlappingDate?.map((item) => ({
|
|
323
|
-
from: item.from,
|
|
324
|
-
}))) ||
|
|
325
|
-
[],
|
|
193
|
+
checkInOnly: 'check-in-only',
|
|
194
|
+
checkOutOnly: 'check-out-only',
|
|
326
195
|
}}
|
|
196
|
+
modifiers={
|
|
197
|
+
// This function handles conditions for applying the modifiersClassNames
|
|
198
|
+
handleCalendarModifiers({
|
|
199
|
+
newDisableCalendarDates,
|
|
200
|
+
calendarRange,
|
|
201
|
+
disabledDatesByPage,
|
|
202
|
+
disabledDates,
|
|
203
|
+
overlappingDate,
|
|
204
|
+
rangeContext,
|
|
205
|
+
findFirstPossibleRangeContextCheckIn,
|
|
206
|
+
findLastPossibleRangeContextCheckOut,
|
|
207
|
+
firstPossibleRangeContextCheckIn,
|
|
208
|
+
lastPossibleRangeContextCheckOut,
|
|
209
|
+
currentSelectionLastCheckoutDate,
|
|
210
|
+
})
|
|
211
|
+
}
|
|
327
212
|
/>
|
|
328
213
|
|
|
329
214
|
<div className={'will-calendar-tooltip'}>
|
|
@@ -335,161 +220,21 @@ export const Calendar = forwardRef<HTMLDivElement, CalendarTypes>(
|
|
|
335
220
|
<div className={'will-calendar-tooltip-overlapping-date'}>
|
|
336
221
|
<div>{t('checkOutOnly')}</div>
|
|
337
222
|
</div>
|
|
223
|
+
<div className={'will-calendar-tooltip-check-in-only'}>
|
|
224
|
+
<div>Check-in Only</div>
|
|
225
|
+
</div>
|
|
226
|
+
<div className={'will-calendar-tooltip-check-out-only'}>
|
|
227
|
+
<div>Checkout Only</div>
|
|
228
|
+
</div>
|
|
338
229
|
<div className={'will-calendar-spinner'}>
|
|
339
|
-
<
|
|
230
|
+
<IconsSvg
|
|
231
|
+
fill={palette?.primary || 'inherit'}
|
|
232
|
+
size={50}
|
|
233
|
+
icon="spinner"
|
|
234
|
+
/>
|
|
340
235
|
</div>
|
|
341
236
|
</div>
|
|
342
237
|
</div>
|
|
343
238
|
)
|
|
344
239
|
}
|
|
345
240
|
)
|
|
346
|
-
|
|
347
|
-
/////////
|
|
348
|
-
|
|
349
|
-
const handleSelectedCheckIn = ({
|
|
350
|
-
range,
|
|
351
|
-
newDisableCalendarDates,
|
|
352
|
-
setCalendarRange,
|
|
353
|
-
setDisabledDates,
|
|
354
|
-
calendarRange,
|
|
355
|
-
overlappingDate,
|
|
356
|
-
setOverlappingDates,
|
|
357
|
-
}: {
|
|
358
|
-
range: DateRange | undefined
|
|
359
|
-
newDisableCalendarDates?: DisableCalendarDates
|
|
360
|
-
setCalendarRange: (range: DateRange | undefined) => void
|
|
361
|
-
setDisabledDates: ((arg: Matcher[]) => void) | undefined
|
|
362
|
-
setOverlappingDates: (arg: boolean) => void
|
|
363
|
-
calendarRange?: DateRange
|
|
364
|
-
overlappingDate?: DateRange[]
|
|
365
|
-
}) => {
|
|
366
|
-
// Calendar dates select logic
|
|
367
|
-
const dateFormat = 'dd-MM-yyyy'
|
|
368
|
-
const rangeFrom = range?.from ? format(range.from, dateFormat) : null
|
|
369
|
-
const rangeTo = range?.to ? format(range.to, dateFormat) : null
|
|
370
|
-
const calendarFrom = calendarRange?.from
|
|
371
|
-
? format(calendarRange?.from, dateFormat)
|
|
372
|
-
: null
|
|
373
|
-
|
|
374
|
-
const overlappingDateFrom = overlappingDate?.length
|
|
375
|
-
? overlappingDate.find(
|
|
376
|
-
(date) => format(date.from || 1, dateFormat) === rangeFrom
|
|
377
|
-
)
|
|
378
|
-
: null
|
|
379
|
-
|
|
380
|
-
const checkOutRange = newDisableCalendarDates?.availableDates?.length
|
|
381
|
-
? newDisableCalendarDates.availableDates.find(
|
|
382
|
-
(checkInDate) =>
|
|
383
|
-
format(checkInDate.checkIn || 1, dateFormat) ===
|
|
384
|
-
format(range?.from || 1, dateFormat)
|
|
385
|
-
)
|
|
386
|
-
: null
|
|
387
|
-
|
|
388
|
-
// Case: Set the calendar range only if it overlaps with the previously selected dates.
|
|
389
|
-
// The selection must remain continuous, meaning no gaps between days are allowed.
|
|
390
|
-
// Whether selecting forwards or backwards from the initially chosen dates,
|
|
391
|
-
// the new range must be directly adjacent to or overlap with the current selection.
|
|
392
|
-
const selectedDates = newDisableCalendarDates?.selectedDates || null
|
|
393
|
-
const rowRangeFrom = range?.from
|
|
394
|
-
const rowRangeTo = range?.to
|
|
395
|
-
const selectedDatesFrom = newDisableCalendarDates?.selectedDates?.from || null
|
|
396
|
-
const selectedDatesTo = newDisableCalendarDates?.selectedDates?.to || null
|
|
397
|
-
|
|
398
|
-
// Checking if rowRangeFrom is equal to or before selectedDatesTo
|
|
399
|
-
const startIsEqualOrBeforeSelectedEnd =
|
|
400
|
-
rowRangeFrom && selectedDatesFrom && selectedDatesTo
|
|
401
|
-
? isBefore(startOfDay(rowRangeFrom), startOfDay(selectedDatesTo)) ||
|
|
402
|
-
isEqual(startOfDay(rowRangeFrom), startOfDay(selectedDatesTo))
|
|
403
|
-
: null
|
|
404
|
-
|
|
405
|
-
// Checking if rowRangeTo is equal to or after selectedDatesFrom
|
|
406
|
-
const endIsEqualOrAfterSelectedStart =
|
|
407
|
-
rowRangeTo && selectedDatesFrom && selectedDatesTo
|
|
408
|
-
? isAfter(startOfDay(rowRangeTo), startOfDay(selectedDatesFrom)) ||
|
|
409
|
-
isEqual(startOfDay(rowRangeTo), startOfDay(selectedDatesFrom))
|
|
410
|
-
: null
|
|
411
|
-
|
|
412
|
-
if (rangeFrom && checkOutRange && setDisabledDates) {
|
|
413
|
-
const checkIn = addDays(checkOutRange.checkIn, 1)
|
|
414
|
-
const firstCheckOut = addDays(checkOutRange.firstCheckOut, -1)
|
|
415
|
-
const noDatesRange =
|
|
416
|
-
format(checkIn, dateFormat) ===
|
|
417
|
-
format(checkOutRange.firstCheckOut, dateFormat)
|
|
418
|
-
|
|
419
|
-
setDisabledDates([
|
|
420
|
-
// { before: findCheckOutRange?.checkIn },
|
|
421
|
-
|
|
422
|
-
...(newDisableCalendarDates?.disabledDates || []),
|
|
423
|
-
|
|
424
|
-
{
|
|
425
|
-
from: noDatesRange ? undefined : checkIn,
|
|
426
|
-
to: noDatesRange ? undefined : firstCheckOut,
|
|
427
|
-
},
|
|
428
|
-
|
|
429
|
-
{ after: checkOutRange?.lastCheckOut },
|
|
430
|
-
])
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
console.log(
|
|
434
|
-
selectedDates,
|
|
435
|
-
startIsEqualOrBeforeSelectedEnd,
|
|
436
|
-
endIsEqualOrAfterSelectedStart
|
|
437
|
-
)
|
|
438
|
-
|
|
439
|
-
setOverlappingDates && setOverlappingDates(false)
|
|
440
|
-
|
|
441
|
-
if (
|
|
442
|
-
(selectedDates && !startIsEqualOrBeforeSelectedEnd) ||
|
|
443
|
-
(selectedDates && range?.to && !endIsEqualOrAfterSelectedStart)
|
|
444
|
-
) {
|
|
445
|
-
setCalendarRange(undefined)
|
|
446
|
-
setOverlappingDates && setOverlappingDates(true)
|
|
447
|
-
} else if (
|
|
448
|
-
(rangeTo && rangeFrom && rangeFrom === rangeTo) ||
|
|
449
|
-
(!rangeTo && !rangeFrom) ||
|
|
450
|
-
overlappingDateFrom
|
|
451
|
-
) {
|
|
452
|
-
setCalendarRange(undefined)
|
|
453
|
-
setDisabledDates && setDisabledDates([])
|
|
454
|
-
} else if (calendarFrom && rangeFrom && rangeFrom !== calendarFrom) {
|
|
455
|
-
setCalendarRange({
|
|
456
|
-
from: range?.from,
|
|
457
|
-
to: undefined,
|
|
458
|
-
})
|
|
459
|
-
} else {
|
|
460
|
-
setCalendarRange(range)
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
const handleDisabledDatesByPage = ({
|
|
465
|
-
newDisableCalendarDates,
|
|
466
|
-
selectedPath,
|
|
467
|
-
today,
|
|
468
|
-
}: {
|
|
469
|
-
newDisableCalendarDates?: DisableCalendarDates
|
|
470
|
-
selectedPath?: string
|
|
471
|
-
today: Date
|
|
472
|
-
}) => {
|
|
473
|
-
const daysToOffsetCalendar =
|
|
474
|
-
newDisableCalendarDates?.disabledDatesByPage && selectedPath
|
|
475
|
-
? [
|
|
476
|
-
newDisableCalendarDates?.disabledDatesByPage?.find(
|
|
477
|
-
(item) => selectedPath === item.page
|
|
478
|
-
),
|
|
479
|
-
]
|
|
480
|
-
: []
|
|
481
|
-
|
|
482
|
-
return daysToOffsetCalendar.length
|
|
483
|
-
? [
|
|
484
|
-
{
|
|
485
|
-
from: addDays(
|
|
486
|
-
today,
|
|
487
|
-
daysToOffsetCalendar.length && daysToOffsetCalendar[0]?.offset
|
|
488
|
-
? daysToOffsetCalendar[0]?.offset
|
|
489
|
-
: -2
|
|
490
|
-
),
|
|
491
|
-
to: addDays(today, -100),
|
|
492
|
-
},
|
|
493
|
-
]
|
|
494
|
-
: []
|
|
495
|
-
}
|
|
@@ -16,7 +16,11 @@ export type DisableCalendarDates = {
|
|
|
16
16
|
page: string
|
|
17
17
|
offset: number
|
|
18
18
|
}[]
|
|
19
|
-
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type RangeContext = {
|
|
22
|
+
from: Date
|
|
23
|
+
to: Date
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
export type CalendarTypes = {
|
|
@@ -30,13 +34,14 @@ export type CalendarTypes = {
|
|
|
30
34
|
disabledDates?: Matcher[]
|
|
31
35
|
setDisabledDates?: (arg: Matcher[]) => void
|
|
32
36
|
loadingData?: boolean
|
|
33
|
-
initialCalendarRange?: DateRange | undefined
|
|
34
37
|
showFeedback?: boolean
|
|
35
38
|
noActiveSelection?: boolean
|
|
36
39
|
palette?: Palette
|
|
37
|
-
|
|
38
40
|
updateCalendarMonthNavigation?: boolean
|
|
39
41
|
setUpdateCalendarMonthNavigation?: (arg: (prev: boolean) => boolean) => void
|
|
40
42
|
updateCalendarDefaultMoth?: number
|
|
41
|
-
|
|
43
|
+
setCalendarHasError?: (arg: boolean) => void
|
|
44
|
+
setUpdatedForSubmit?: (arg: boolean) => void
|
|
45
|
+
rangeContext?: RangeContext
|
|
46
|
+
calendarHasError?: boolean
|
|
42
47
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useEffect } from 'react'
|
|
2
|
+
|
|
3
|
+
type Props = {
|
|
4
|
+
loadingData?: boolean
|
|
5
|
+
updateCalendarMonthNavigation?: boolean
|
|
6
|
+
updateCalendarDefaultMoth?: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const useCalendarLoadingSpinner = ({
|
|
10
|
+
loadingData,
|
|
11
|
+
updateCalendarMonthNavigation,
|
|
12
|
+
updateCalendarDefaultMoth,
|
|
13
|
+
}: Props) =>
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
if (typeof document === 'undefined') return
|
|
16
|
+
|
|
17
|
+
const loadingSpinner: HTMLElement | null = document.querySelector(
|
|
18
|
+
'.will-filter-bar-calendar .rdp-months .will-calendar-spinner'
|
|
19
|
+
)
|
|
20
|
+
if (loadingData) {
|
|
21
|
+
if (loadingSpinner) loadingSpinner.style.display = 'flex'
|
|
22
|
+
} else {
|
|
23
|
+
if (loadingSpinner) loadingSpinner.style.display = 'none'
|
|
24
|
+
}
|
|
25
|
+
}, [loadingData, updateCalendarMonthNavigation, updateCalendarDefaultMoth])
|