pimelon-ui 0.1.64 → 0.1.66
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/package.json +1 -1
- package/src/components/Autocomplete.vue +4 -2
- package/src/components/Calendar/Calendar.vue +432 -0
- package/src/components/Calendar/CalendarDaily.vue +113 -0
- package/src/components/Calendar/CalendarEvent.vue +512 -0
- package/src/components/Calendar/CalendarMonthly.vue +143 -0
- package/src/components/Calendar/CalendarTimeMarker.vue +49 -0
- package/src/components/Calendar/CalendarWeekly.vue +252 -0
- package/src/components/Calendar/EventModalContent.vue +63 -0
- package/src/components/Calendar/FloatingPopover.vue +46 -0
- package/src/components/Calendar/NewEventModal.vue +210 -0
- package/src/components/Calendar/ShowMoreCalendarEvent.vue +37 -0
- package/src/components/Calendar/calendarUtils.js +277 -0
- package/src/components/Calendar/composables/useCalendarData.js +54 -0
- package/src/components/Calendar/composables/useEventModal.js +41 -0
- package/src/components/Calendar.story.md +247 -0
- package/src/components/Calendar.story.vue +138 -0
- package/src/index.js +1 -0
- package/src/resources/listResource.js +1 -1
package/package.json
CHANGED
|
@@ -274,8 +274,10 @@ export default {
|
|
|
274
274
|
if (!this.query) return options
|
|
275
275
|
return options.filter((option) => {
|
|
276
276
|
return (
|
|
277
|
-
option.label
|
|
278
|
-
|
|
277
|
+
option.label
|
|
278
|
+
.toLowerCase()
|
|
279
|
+
.includes(this.query.trim().toLowerCase()) ||
|
|
280
|
+
option.value.toLowerCase().includes(this.query.trim().toLowerCase())
|
|
279
281
|
)
|
|
280
282
|
})
|
|
281
283
|
},
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex h-full flex-col overflow-hidden">
|
|
3
|
+
<slot
|
|
4
|
+
name="header"
|
|
5
|
+
v-bind="{
|
|
6
|
+
currentMonthYear,
|
|
7
|
+
enabledModes,
|
|
8
|
+
activeView,
|
|
9
|
+
decrement,
|
|
10
|
+
increment,
|
|
11
|
+
updateActiveView,
|
|
12
|
+
}"
|
|
13
|
+
>
|
|
14
|
+
<div class="mb-2 flex justify-between">
|
|
15
|
+
<!-- left side -->
|
|
16
|
+
<!-- Year, Month -->
|
|
17
|
+
<span class="text-xl font-medium"> {{ currentMonthYear }}</span>
|
|
18
|
+
<!-- right side -->
|
|
19
|
+
<!-- actions buttons for calendar -->
|
|
20
|
+
<div class="flex gap-x-1">
|
|
21
|
+
<!-- Increment and Decrement Button-->
|
|
22
|
+
|
|
23
|
+
<Button
|
|
24
|
+
@click="decrement()"
|
|
25
|
+
variant="ghost"
|
|
26
|
+
class="h-4 w-4"
|
|
27
|
+
icon="chevron-left"
|
|
28
|
+
/>
|
|
29
|
+
<Button
|
|
30
|
+
@click="increment()"
|
|
31
|
+
variant="ghost"
|
|
32
|
+
class="h-4 w-4"
|
|
33
|
+
icon="chevron-right"
|
|
34
|
+
/>
|
|
35
|
+
|
|
36
|
+
<!-- View change button, default is months or can be set via props! -->
|
|
37
|
+
<TabButtons
|
|
38
|
+
:buttons="enabledModes"
|
|
39
|
+
class="ml-2"
|
|
40
|
+
v-model="activeView"
|
|
41
|
+
/>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</slot>
|
|
45
|
+
|
|
46
|
+
<CalendarMonthly
|
|
47
|
+
v-if="activeView === 'Month'"
|
|
48
|
+
:events="events"
|
|
49
|
+
:currentMonth="currentMonth"
|
|
50
|
+
:currentMonthDates="currentMonthDates"
|
|
51
|
+
:config="overrideConfig"
|
|
52
|
+
@setCurrentDate="(d) => updateCurrentDate(d)"
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<CalendarWeekly
|
|
56
|
+
v-else-if="activeView === 'Week'"
|
|
57
|
+
:events="events"
|
|
58
|
+
:weeklyDates="datesInWeeks[week]"
|
|
59
|
+
:config="overrideConfig"
|
|
60
|
+
/>
|
|
61
|
+
|
|
62
|
+
<CalendarDaily
|
|
63
|
+
v-else-if="activeView === 'Day'"
|
|
64
|
+
:events="events"
|
|
65
|
+
:current-date="selectedDay"
|
|
66
|
+
:config="overrideConfig"
|
|
67
|
+
/>
|
|
68
|
+
|
|
69
|
+
<NewEventModal
|
|
70
|
+
v-if="showEventModal"
|
|
71
|
+
v-model="showEventModal"
|
|
72
|
+
:event="newEvent"
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
</template>
|
|
76
|
+
<script setup>
|
|
77
|
+
import { computed, onMounted, onUnmounted, provide, ref, watch } from 'vue'
|
|
78
|
+
import Button from '../Button.vue'
|
|
79
|
+
import TabButtons from '../TabButtons.vue'
|
|
80
|
+
import {
|
|
81
|
+
getCalendarDates,
|
|
82
|
+
monthList,
|
|
83
|
+
handleSeconds,
|
|
84
|
+
parseDate,
|
|
85
|
+
} from './calendarUtils'
|
|
86
|
+
import CalendarMonthly from './CalendarMonthly.vue'
|
|
87
|
+
import CalendarWeekly from './CalendarWeekly.vue'
|
|
88
|
+
import CalendarDaily from './CalendarDaily.vue'
|
|
89
|
+
import NewEventModal from './NewEventModal.vue'
|
|
90
|
+
import useEventModal from './composables/useEventModal'
|
|
91
|
+
|
|
92
|
+
const props = defineProps({
|
|
93
|
+
events: {
|
|
94
|
+
type: Object,
|
|
95
|
+
required: false,
|
|
96
|
+
default: [],
|
|
97
|
+
},
|
|
98
|
+
config: {
|
|
99
|
+
type: Object,
|
|
100
|
+
},
|
|
101
|
+
create: {
|
|
102
|
+
type: Function,
|
|
103
|
+
required: false,
|
|
104
|
+
},
|
|
105
|
+
update: {
|
|
106
|
+
type: Function,
|
|
107
|
+
required: false,
|
|
108
|
+
},
|
|
109
|
+
delete: {
|
|
110
|
+
type: Function,
|
|
111
|
+
required: false,
|
|
112
|
+
},
|
|
113
|
+
onClick: {
|
|
114
|
+
type: Function,
|
|
115
|
+
required: false,
|
|
116
|
+
},
|
|
117
|
+
onDblClick: {
|
|
118
|
+
type: Function,
|
|
119
|
+
required: false,
|
|
120
|
+
},
|
|
121
|
+
onCellDblClick: {
|
|
122
|
+
type: Function,
|
|
123
|
+
required: false,
|
|
124
|
+
},
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
const defaultConfig = {
|
|
128
|
+
scrollToHour: 15,
|
|
129
|
+
disableModes: [],
|
|
130
|
+
defaultMode: 'Month',
|
|
131
|
+
isEditMode: false,
|
|
132
|
+
eventIcons: {},
|
|
133
|
+
redundantCellHeight: 50,
|
|
134
|
+
hourHeight: 50,
|
|
135
|
+
enableShortcuts: true,
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const overrideConfig = { ...defaultConfig, ...props.config }
|
|
139
|
+
let activeView = ref(overrideConfig.defaultMode)
|
|
140
|
+
|
|
141
|
+
function updateActiveView(value) {
|
|
142
|
+
console.log(value)
|
|
143
|
+
activeView.value = value
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// shortcuts for changing the active view and navigating through the calendar
|
|
147
|
+
onMounted(() => {
|
|
148
|
+
if (!overrideConfig.enableShortcuts) return
|
|
149
|
+
window.addEventListener('keydown', handleShortcuts)
|
|
150
|
+
})
|
|
151
|
+
onUnmounted(() => {
|
|
152
|
+
window.removeEventListener('keydown', handleShortcuts)
|
|
153
|
+
})
|
|
154
|
+
function handleShortcuts(e) {
|
|
155
|
+
if (e.key === 'm' || e.key === 'M') {
|
|
156
|
+
activeView.value = 'Month'
|
|
157
|
+
}
|
|
158
|
+
if (e.key === 'w' || e.key === 'W') {
|
|
159
|
+
activeView.value = 'Week'
|
|
160
|
+
}
|
|
161
|
+
if (e.key === 'd' || e.key === 'D') {
|
|
162
|
+
activeView.value = 'Day'
|
|
163
|
+
}
|
|
164
|
+
if (e.key === 'ArrowLeft') {
|
|
165
|
+
decrement()
|
|
166
|
+
}
|
|
167
|
+
if (e.key === 'ArrowRight') {
|
|
168
|
+
increment()
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
provide('activeView', activeView)
|
|
173
|
+
provide('config', overrideConfig)
|
|
174
|
+
|
|
175
|
+
const parseEvents = computed(() => {
|
|
176
|
+
return props.events.map((event) => {
|
|
177
|
+
const { fromDate, toDate, ...rest } = event
|
|
178
|
+
const date = parseDate(fromDate)
|
|
179
|
+
const from_time = new Date(fromDate).toLocaleTimeString()
|
|
180
|
+
const to_time = new Date(toDate).toLocaleTimeString()
|
|
181
|
+
if (event.isFullDay) {
|
|
182
|
+
return { ...rest, date }
|
|
183
|
+
}
|
|
184
|
+
return { ...rest, date, from_time, to_time }
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
const events = ref(parseEvents.value)
|
|
188
|
+
|
|
189
|
+
events.value.forEach((event) => {
|
|
190
|
+
if (!event.from_time || !event.to_time) {
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
event.from_time = handleSeconds(event.from_time)
|
|
194
|
+
event.to_time = handleSeconds(event.to_time)
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
const { showEventModal, newEvent, openNewEventModal } = useEventModal()
|
|
198
|
+
|
|
199
|
+
provide('calendarActions', {
|
|
200
|
+
createNewEvent,
|
|
201
|
+
updateEventState,
|
|
202
|
+
deleteEvent,
|
|
203
|
+
handleCellDblClick,
|
|
204
|
+
props,
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
// CRUD actions on an event
|
|
208
|
+
function createNewEvent(event) {
|
|
209
|
+
events.value.push(event)
|
|
210
|
+
props.create && props.create(event)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function updateEventState(event) {
|
|
214
|
+
const eventID = event.id
|
|
215
|
+
let eventIndex = events.value.findIndex((e) => e.id === eventID)
|
|
216
|
+
events.value[eventIndex] = event
|
|
217
|
+
props.update && props.update(events.value[eventIndex])
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function deleteEvent(eventID) {
|
|
221
|
+
// Delete event
|
|
222
|
+
const eventIndex = events.value.findIndex((event) => event.id === eventID)
|
|
223
|
+
events.value.splice(eventIndex, 1)
|
|
224
|
+
props.delete && props.delete(eventID)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function openModal(data) {
|
|
228
|
+
const { e, view, date, time } = data
|
|
229
|
+
const config = overrideConfig.isEditMode
|
|
230
|
+
openNewEventModal(e, view, date, config, time)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function handleCellDblClick(e, date, time = '') {
|
|
234
|
+
const data = {
|
|
235
|
+
e,
|
|
236
|
+
view: activeView.value,
|
|
237
|
+
date,
|
|
238
|
+
time,
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (props.onCellDblClick) {
|
|
242
|
+
props.onCellDblClick(data)
|
|
243
|
+
return
|
|
244
|
+
}
|
|
245
|
+
openModal(data)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Calendar View Options
|
|
249
|
+
const actionOptions = [
|
|
250
|
+
{ label: 'Day', variant: 'solid' },
|
|
251
|
+
{ label: 'Week', variant: 'solid' },
|
|
252
|
+
{ label: 'Month', variant: 'solid' },
|
|
253
|
+
]
|
|
254
|
+
let enabledModes = actionOptions.filter(
|
|
255
|
+
(mode) => !overrideConfig.disableModes.includes(mode.label),
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
let currentYear = ref(new Date().getFullYear())
|
|
259
|
+
let currentMonth = ref(new Date().getMonth())
|
|
260
|
+
let currentDate = ref(new Date())
|
|
261
|
+
|
|
262
|
+
let currentMonthDates = computed(() => {
|
|
263
|
+
let dates = getCalendarDates(currentMonth.value, currentYear.value)
|
|
264
|
+
return dates
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
let datesInWeeks = computed(() => {
|
|
268
|
+
let dates = [...currentMonthDates.value]
|
|
269
|
+
let datesInWeeks = []
|
|
270
|
+
while (dates.length) {
|
|
271
|
+
let week = dates.splice(0, 7)
|
|
272
|
+
datesInWeeks.push(week)
|
|
273
|
+
}
|
|
274
|
+
return datesInWeeks
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
function findCurrentWeek(date) {
|
|
278
|
+
return datesInWeeks.value.findIndex((week) =>
|
|
279
|
+
week.find(
|
|
280
|
+
(d) =>
|
|
281
|
+
new Date(d).toLocaleDateString().split('T')[0] ===
|
|
282
|
+
new Date(date).toLocaleDateString().split('T')[0],
|
|
283
|
+
),
|
|
284
|
+
)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
let week = ref(findCurrentWeek(currentDate.value))
|
|
288
|
+
|
|
289
|
+
let date = ref(
|
|
290
|
+
currentMonthDates.value.findIndex(
|
|
291
|
+
(d) => new Date(d).toDateString() === currentDate.value.toDateString(),
|
|
292
|
+
),
|
|
293
|
+
)
|
|
294
|
+
let selectedDay = computed(() => currentMonthDates.value[date.value])
|
|
295
|
+
|
|
296
|
+
function updateCurrentDate(d) {
|
|
297
|
+
activeView.value = 'Day'
|
|
298
|
+
date.value = findIndexOfDate(d)
|
|
299
|
+
week.value = findCurrentWeek(d)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const incrementClickEvents = {
|
|
303
|
+
Month: incrementMonth,
|
|
304
|
+
Week: incrementWeek,
|
|
305
|
+
Day: incrementDay,
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const decrementClickEvents = {
|
|
309
|
+
Month: decrementMonth,
|
|
310
|
+
Week: decrementWeek,
|
|
311
|
+
Day: decrementDay,
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function incrementMonth() {
|
|
315
|
+
currentMonth.value++
|
|
316
|
+
date.value = findFirstDateOfMonth(currentMonth.value, currentYear.value)
|
|
317
|
+
week.value = findCurrentWeek(currentMonthDates.value[date.value]) + 1
|
|
318
|
+
if (currentMonth.value > 11) {
|
|
319
|
+
currentMonth.value = 0
|
|
320
|
+
currentYear.value++
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function decrementMonth() {
|
|
325
|
+
currentMonth.value--
|
|
326
|
+
date.value = findLastDateOfMonth(currentMonth.value, currentYear.value)
|
|
327
|
+
week.value = findCurrentWeek(currentMonthDates.value[date.value])
|
|
328
|
+
if (currentMonth.value < 0) {
|
|
329
|
+
currentMonth.value = 11
|
|
330
|
+
currentYear.value--
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function increment() {
|
|
335
|
+
incrementClickEvents[activeView.value]()
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function decrement() {
|
|
339
|
+
decrementClickEvents[activeView.value]()
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function incrementWeek() {
|
|
343
|
+
week.value += 1
|
|
344
|
+
if (week.value < datesInWeeks.value.length) {
|
|
345
|
+
date.value = findIndexOfDate(datesInWeeks.value[week.value][0])
|
|
346
|
+
}
|
|
347
|
+
if (week.value > datesInWeeks.value.length - 1) {
|
|
348
|
+
incrementMonth()
|
|
349
|
+
}
|
|
350
|
+
let nextMonthDates = filterCurrentWeekDates()
|
|
351
|
+
if (nextMonthDates.length > 0) {
|
|
352
|
+
incrementMonth()
|
|
353
|
+
week.value = findCurrentWeek(nextMonthDates[0])
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function decrementWeek() {
|
|
358
|
+
week.value -= 1
|
|
359
|
+
if (week.value < 0) {
|
|
360
|
+
decrementMonth()
|
|
361
|
+
return
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (week.value > 0) {
|
|
365
|
+
date.value = findIndexOfDate(datesInWeeks.value[week.value][0])
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
let previousMonthDates = filterCurrentWeekDates()
|
|
369
|
+
if (previousMonthDates.length > 0) {
|
|
370
|
+
decrementMonth()
|
|
371
|
+
week.value = findCurrentWeek(previousMonthDates[0])
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
function filterCurrentWeekDates() {
|
|
376
|
+
let currentWeekDates = datesInWeeks.value[week.value]
|
|
377
|
+
let differentMonthDates = currentWeekDates.filter(
|
|
378
|
+
(d) => d.getMonth() !== currentMonth.value,
|
|
379
|
+
)
|
|
380
|
+
return differentMonthDates
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function incrementDay() {
|
|
384
|
+
date.value++
|
|
385
|
+
if (
|
|
386
|
+
date.value > currentMonthDates.value.length - 1 ||
|
|
387
|
+
!isCurrentMonthDate(currentMonthDates.value[date.value])
|
|
388
|
+
) {
|
|
389
|
+
incrementMonth()
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function decrementDay() {
|
|
394
|
+
date.value--
|
|
395
|
+
if (
|
|
396
|
+
date.value < 0 ||
|
|
397
|
+
!isCurrentMonthDate(currentMonthDates.value[date.value])
|
|
398
|
+
) {
|
|
399
|
+
decrementMonth()
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function findLastDateOfMonth(month, year) {
|
|
404
|
+
let inputDate = new Date(year, month + 1, 0)
|
|
405
|
+
let lastDateIndex = currentMonthDates.value.findIndex(
|
|
406
|
+
(date) => new Date(date).toDateString() === inputDate.toDateString(),
|
|
407
|
+
)
|
|
408
|
+
return lastDateIndex
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function findFirstDateOfMonth(month, year) {
|
|
412
|
+
let inputDate = new Date(year, month, 1)
|
|
413
|
+
let firstDateIndex = currentMonthDates.value.findIndex(
|
|
414
|
+
(date) => new Date(date).toDateString() === inputDate.toDateString(),
|
|
415
|
+
)
|
|
416
|
+
return firstDateIndex
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function findIndexOfDate(date) {
|
|
420
|
+
return currentMonthDates.value.findIndex(
|
|
421
|
+
(d) => new Date(d).toDateString() === new Date(date).toDateString(),
|
|
422
|
+
)
|
|
423
|
+
}
|
|
424
|
+
const currentMonthYear = computed(() => {
|
|
425
|
+
return monthList[currentMonth.value] + ', ' + currentYear.value
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
function isCurrentMonthDate(date) {
|
|
429
|
+
date = new Date(date)
|
|
430
|
+
return date.getMonth() === currentMonth.value
|
|
431
|
+
}
|
|
432
|
+
</script>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="h-[90%] min-h-[500px] min-w-[600px]">
|
|
3
|
+
<p class="pb-2 text-base font-bold text-gray-800">
|
|
4
|
+
{{ parseDateWithDay(currentDate, (fullDay = true)) }}
|
|
5
|
+
</p>
|
|
6
|
+
<div class="h-full overflow-hidden">
|
|
7
|
+
<div
|
|
8
|
+
class="flex h-full w-full overflow-scroll border-b-[1px] border-l-[1px] border-t-[1px]"
|
|
9
|
+
ref="gridRef"
|
|
10
|
+
>
|
|
11
|
+
<!-- Left column -->
|
|
12
|
+
<div class="grid h-full w-16 grid-cols-1">
|
|
13
|
+
<span
|
|
14
|
+
v-for="time in 24"
|
|
15
|
+
class="flex h-[72px] items-end justify-center text-center text-sm font-normal text-gray-600"
|
|
16
|
+
:style="{ height: `${hourHeight}px` }"
|
|
17
|
+
/>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<!-- Calendar Grid / Right Column -->
|
|
21
|
+
<div class="grid h-full w-full grid-cols-1 pb-2">
|
|
22
|
+
<div class="calendar-column relative border-r-[1px]">
|
|
23
|
+
<!-- Top Redundant Cell before time starts for giving the calendar some space -->
|
|
24
|
+
<div
|
|
25
|
+
class="flex h-[50px] w-full flex-wrap gap-2 overflow-y-scroll border-b-[1px] border-gray-200 transition-all"
|
|
26
|
+
:style="{ height: `${config.redundantCellHeight}px` }"
|
|
27
|
+
>
|
|
28
|
+
<CalendarEvent
|
|
29
|
+
v-for="(calendarEvent, idx) in fullDayEvents[
|
|
30
|
+
parseDate(currentDate)
|
|
31
|
+
]"
|
|
32
|
+
class="mb-1 w-[20%] cursor-pointer"
|
|
33
|
+
:event="{ ...calendarEvent, idx }"
|
|
34
|
+
:key="calendarEvent.id"
|
|
35
|
+
:date="currentDate"
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
<!-- Day Grid -->
|
|
39
|
+
<div
|
|
40
|
+
class="relative flex"
|
|
41
|
+
v-for="time in twentyFourHoursFormat"
|
|
42
|
+
:data-time-attr="time"
|
|
43
|
+
@dblclick="
|
|
44
|
+
calendarActions.handleCellDblClick($event, currentDate, time)
|
|
45
|
+
"
|
|
46
|
+
>
|
|
47
|
+
<div
|
|
48
|
+
class="w-full border-b-[1px] border-gray-200"
|
|
49
|
+
:style="{ height: `${hourHeight}px` }"
|
|
50
|
+
/>
|
|
51
|
+
</div>
|
|
52
|
+
<CalendarEvent
|
|
53
|
+
v-for="(calendarEvent, idx) in timedEvents[
|
|
54
|
+
parseDate(currentDate)
|
|
55
|
+
]"
|
|
56
|
+
class="absolute mb-2 cursor-pointer"
|
|
57
|
+
:event="calendarEvent"
|
|
58
|
+
:key="calendarEvent.id"
|
|
59
|
+
:date="currentDate"
|
|
60
|
+
/>
|
|
61
|
+
<!-- Current time Marker -->
|
|
62
|
+
<CalendarTimeMarker
|
|
63
|
+
:date="currentDate"
|
|
64
|
+
:redundantCellHeight="config.redundantCellHeight"
|
|
65
|
+
/>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</template>
|
|
72
|
+
|
|
73
|
+
<script setup>
|
|
74
|
+
import { computed, inject, onMounted, ref } from 'vue'
|
|
75
|
+
import CalendarEvent from './CalendarEvent.vue'
|
|
76
|
+
import CalendarTimeMarker from './CalendarTimeMarker.vue'
|
|
77
|
+
import {
|
|
78
|
+
parseDate,
|
|
79
|
+
parseDateWithDay,
|
|
80
|
+
twentyFourHoursFormat,
|
|
81
|
+
} from './calendarUtils'
|
|
82
|
+
import useCalendarData from './composables/useCalendarData'
|
|
83
|
+
|
|
84
|
+
const props = defineProps({
|
|
85
|
+
events: {
|
|
86
|
+
type: Object,
|
|
87
|
+
required: false,
|
|
88
|
+
},
|
|
89
|
+
config: {
|
|
90
|
+
type: Object,
|
|
91
|
+
},
|
|
92
|
+
currentDate: {
|
|
93
|
+
type: Object,
|
|
94
|
+
required: true,
|
|
95
|
+
},
|
|
96
|
+
})
|
|
97
|
+
const timedEvents = computed(
|
|
98
|
+
() => useCalendarData(props.events).timedEvents.value,
|
|
99
|
+
)
|
|
100
|
+
const fullDayEvents = computed(
|
|
101
|
+
() => useCalendarData(props.events).fullDayEvents.value,
|
|
102
|
+
)
|
|
103
|
+
const gridRef = ref(null)
|
|
104
|
+
const hourHeight = props.config.hourHeight
|
|
105
|
+
const minuteHeight = hourHeight / 60
|
|
106
|
+
|
|
107
|
+
onMounted(() => {
|
|
108
|
+
const currentHour = new Date().getHours()
|
|
109
|
+
gridRef.value.scrollBy(0, currentHour * 60 * minuteHeight)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
const calendarActions = inject('calendarActions')
|
|
113
|
+
</script>
|