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