@bagelink/vue 1.2.15 → 1.2.20
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/dist/components/calendar/CalendarTypes.d.ts +13 -0
- package/dist/components/calendar/CalendarTypes.d.ts.map +1 -0
- package/dist/components/calendar/Index.vue.d.ts +39 -507
- package/dist/components/calendar/Index.vue.d.ts.map +1 -1
- package/dist/components/calendar/utils.d.ts +31 -0
- package/dist/components/calendar/utils.d.ts.map +1 -0
- package/dist/components/calendar/views/AgendaView.vue.d.ts +16 -0
- package/dist/components/calendar/views/AgendaView.vue.d.ts.map +1 -0
- package/dist/components/calendar/views/DayView.vue.d.ts +50 -0
- package/dist/components/calendar/views/DayView.vue.d.ts.map +1 -0
- package/dist/components/calendar/views/MonthView.vue.d.ts +20 -0
- package/dist/components/calendar/views/MonthView.vue.d.ts.map +1 -0
- package/dist/components/calendar/views/WeekView.vue.d.ts +33 -0
- package/dist/components/calendar/views/WeekView.vue.d.ts.map +1 -0
- package/dist/components/form/BglMultiStepForm.vue.d.ts +63 -0
- package/dist/components/form/BglMultiStepForm.vue.d.ts.map +1 -0
- package/dist/components/form/index.d.ts +1 -0
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/inputs/CodeEditor/Index.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/DateInput.vue.d.ts +3 -3
- package/dist/components/form/inputs/DateInput.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/DatePicker.vue.d.ts +3 -3
- package/dist/components/form/inputs/DatePicker.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/SelectInput.vue.d.ts.map +1 -1
- package/dist/index.cjs +2241 -3891
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +2242 -3892
- package/dist/style.css +567 -633
- package/dist/utils/BagelFormUtils.d.ts +4 -2
- package/dist/utils/BagelFormUtils.d.ts.map +1 -1
- package/dist/utils/calendar/EDate.d.ts +2 -0
- package/dist/utils/calendar/EDate.d.ts.map +1 -0
- package/dist/utils/calendar/Helpers.d.ts +19 -0
- package/dist/utils/calendar/Helpers.d.ts.map +1 -0
- package/dist/utils/calendar/constants.d.ts +3 -0
- package/dist/utils/calendar/constants.d.ts.map +1 -0
- package/dist/utils/calendar/dateUtils.d.ts +30 -0
- package/dist/utils/calendar/dateUtils.d.ts.map +1 -0
- package/dist/utils/calendar/event.interface.d.ts +32 -0
- package/dist/utils/calendar/event.interface.d.ts.map +1 -0
- package/dist/utils/calendar/time.d.ts +117 -0
- package/dist/utils/calendar/time.d.ts.map +1 -0
- package/dist/utils/calendar/types.d.ts +27 -0
- package/dist/utils/calendar/types.d.ts.map +1 -0
- package/dist/utils/calendar/typings.d.ts +87 -0
- package/dist/utils/calendar/typings.d.ts.map +1 -0
- package/dist/utils/calendar/week.d.ts +117 -0
- package/dist/utils/calendar/week.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/components/calendar/CalendarTypes.ts +13 -0
- package/src/components/calendar/Index.vue +124 -389
- package/src/components/calendar/utils.ts +70 -0
- package/src/components/calendar/views/AgendaView.vue +263 -0
- package/src/components/calendar/views/DayView.vue +373 -0
- package/src/components/calendar/views/MonthView.vue +313 -0
- package/src/components/calendar/views/WeekView.vue +431 -0
- package/src/components/form/BglMultiStepForm.vue +383 -69
- package/src/components/form/index.ts +1 -0
- package/src/components/form/inputs/CodeEditor/Index.vue +11 -0
- package/src/components/form/inputs/DateInput.vue +3 -3
- package/src/components/form/inputs/DatePicker.vue +35 -30
- package/src/components/form/inputs/SelectInput.vue +2 -0
- package/src/components/form/inputs/Upload/upload.types.d.ts +0 -1
- package/src/index.ts +2 -2
- package/src/styles/inputs.css +138 -137
- package/src/styles/layout.css +3 -2
- package/src/styles/mobilLayout.css +4 -2
- package/src/utils/BagelFormUtils.ts +6 -2
- package/src/utils/calendar/EDate.ts +0 -0
- package/src/{components/calendar/helpers → utils/calendar}/Helpers.ts +6 -6
- package/src/utils/calendar/constants.ts +2 -0
- package/src/utils/{timeAgo.ts → calendar/dateUtils.ts} +38 -1
- package/src/utils/calendar/event.interface.ts +33 -0
- package/src/{components/calendar/helpers/Time.ts → utils/calendar/time.ts} +15 -15
- package/src/utils/calendar/types.ts +27 -0
- package/src/{components/calendar/typings/config.interface.ts → utils/calendar/typings.ts} +13 -6
- package/src/utils/calendar/week.ts +588 -0
- package/src/components/calendar/assets/base.css +0 -60
- package/src/components/calendar/components/header/Header.vue +0 -153
- package/src/components/calendar/components/month/AgendaEventTile.vue +0 -135
- package/src/components/calendar/components/month/AgendaEvents.vue +0 -72
- package/src/components/calendar/components/month/Day.vue +0 -256
- package/src/components/calendar/components/month/Event.vue +0 -164
- package/src/components/calendar/components/month/Month.vue +0 -241
- package/src/components/calendar/components/month/WeekDay.vue +0 -15
- package/src/components/calendar/components/partials/EventFlyout.vue +0 -430
- package/src/components/calendar/components/week/Day.vue +0 -198
- package/src/components/calendar/components/week/DayEvent.vue +0 -584
- package/src/components/calendar/components/week/DayTimeline.vue +0 -80
- package/src/components/calendar/components/week/FullDayEvent.vue +0 -121
- package/src/components/calendar/components/week/Week.vue +0 -414
- package/src/components/calendar/components/week/WeekTimeline.vue +0 -101
- package/src/components/calendar/constants.ts +0 -13
- package/src/components/calendar/helpers/DayIntervals.ts +0 -48
- package/src/components/calendar/helpers/EDate.ts +0 -18
- package/src/components/calendar/helpers/Errors.ts +0 -69
- package/src/components/calendar/helpers/EventChange.ts +0 -88
- package/src/components/calendar/helpers/EventConcurrency.ts +0 -69
- package/src/components/calendar/helpers/EventFlyoutPosition.ts +0 -96
- package/src/components/calendar/helpers/EventPosition.ts +0 -154
- package/src/components/calendar/helpers/EventsFilter.ts +0 -50
- package/src/components/calendar/helpers/Week.ts +0 -37
- package/src/components/calendar/language/index.ts +0 -41
- package/src/components/calendar/language/keys.ts +0 -99
- package/src/components/calendar/models/Event.ts +0 -112
- package/src/components/calendar/styles/_mixins.css +0 -21
- package/src/components/calendar/styles/_variables.css +0 -47
- package/src/components/calendar/typings/interfaces/day.interface.ts +0 -10
- package/src/components/calendar/typings/interfaces/event.interface.ts +0 -32
- package/src/components/calendar/typings/interfaces/full-day-events-week.type.ts +0 -8
- package/src/components/calendar/typings/interfaces/period.interface.ts +0 -5
- package/src/components/calendar/typings/interfaces/time-modes.ts +0 -11
- package/src/components/calendar/typings/types.ts +0 -27
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { CalendarEvent, WeekStart } from '../CalendarTypes'
|
|
3
|
+
import type { PopoverState } from '../utils'
|
|
4
|
+
import { Card, formatDate } from '@bagelink/vue'
|
|
5
|
+
import { ref, computed, onMounted, onUnmounted, useSlots } from 'vue'
|
|
6
|
+
import {
|
|
7
|
+
openPopover as openPopoverUtil,
|
|
8
|
+
closePopover as closePopoverUtil,
|
|
9
|
+
} from '../utils'
|
|
10
|
+
|
|
11
|
+
interface WeekViewEvent extends CalendarEvent {
|
|
12
|
+
top: number
|
|
13
|
+
height: number
|
|
14
|
+
left: number
|
|
15
|
+
width: number
|
|
16
|
+
overlappingEvents: number
|
|
17
|
+
position: number
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const props = withDefaults(defineProps<{
|
|
21
|
+
events?: CalendarEvent[]
|
|
22
|
+
startDate?: Date
|
|
23
|
+
weekStart?: WeekStart
|
|
24
|
+
}>(), {
|
|
25
|
+
startDate: () => new Date(),
|
|
26
|
+
weekStart: 'Sunday',
|
|
27
|
+
events: () => []
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const emit = defineEmits<{
|
|
31
|
+
(e: 'eventClick', event: CalendarEvent): void
|
|
32
|
+
(e: 'eventCreate', event: { start_time: Date, end_time: Date }): void
|
|
33
|
+
}>()
|
|
34
|
+
|
|
35
|
+
const slots = useSlots()
|
|
36
|
+
|
|
37
|
+
// Configuration constants
|
|
38
|
+
const slotHeight = 60
|
|
39
|
+
const slotDuration = 60
|
|
40
|
+
const timeRange = { start: 0, end: 24 }
|
|
41
|
+
|
|
42
|
+
// Drag state
|
|
43
|
+
const dragState = ref({
|
|
44
|
+
isDragging: false,
|
|
45
|
+
start: null as { x: number, y: number } | null,
|
|
46
|
+
end: null as { x: number, y: number } | null,
|
|
47
|
+
startTime: null as Date | null,
|
|
48
|
+
endTime: null as Date | null
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
// Popover state
|
|
52
|
+
const activeEvent = ref<CalendarEvent | null>(null)
|
|
53
|
+
const showPopover = ref(false)
|
|
54
|
+
const popoverPosition = ref({ top: 0, left: 0, width: 0, height: 0 })
|
|
55
|
+
const popoverRef = ref<HTMLElement | null>(null)
|
|
56
|
+
|
|
57
|
+
const popoverState: PopoverState = {
|
|
58
|
+
activeEvent,
|
|
59
|
+
showPopover,
|
|
60
|
+
popoverPosition,
|
|
61
|
+
popoverRef
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Time indicators
|
|
65
|
+
const currentTimeTop = ref(0)
|
|
66
|
+
const isToday = ref(false)
|
|
67
|
+
const currentTimeInterval = ref(null as any)
|
|
68
|
+
|
|
69
|
+
// Calculate week days based on start date and week start preference
|
|
70
|
+
const weekDays = computed(() => {
|
|
71
|
+
const days = []
|
|
72
|
+
const start = new Date(props.startDate)
|
|
73
|
+
const weekStartOffset = props.weekStart === 'Sunday' ? 0 : 1
|
|
74
|
+
|
|
75
|
+
// Adjust to start of week
|
|
76
|
+
const dayOfWeek = start.getDay()
|
|
77
|
+
start.setDate(start.getDate() - dayOfWeek + weekStartOffset)
|
|
78
|
+
|
|
79
|
+
// Create array of 7 day dates
|
|
80
|
+
for (let i = 0; i < 7; i++) {
|
|
81
|
+
const date = new Date(start)
|
|
82
|
+
date.setDate(start.getDate() + i)
|
|
83
|
+
days.push(date)
|
|
84
|
+
}
|
|
85
|
+
return days
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
// Generate hourly time slots
|
|
89
|
+
const timeSlots = computed(() => {
|
|
90
|
+
const slots = []
|
|
91
|
+
for (let hour = timeRange.start; hour < timeRange.end; hour++) {
|
|
92
|
+
for (let minute = 0; minute < 60; minute += slotDuration) {
|
|
93
|
+
slots.push({
|
|
94
|
+
hour,
|
|
95
|
+
minute,
|
|
96
|
+
time: `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return slots
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
// Process events for display with positioning calculations
|
|
104
|
+
const processedEvents = computed(() => {
|
|
105
|
+
const events: WeekViewEvent[] = []
|
|
106
|
+
const overlappingGroups: { [key: string]: WeekViewEvent[] } = {}
|
|
107
|
+
|
|
108
|
+
props.events.forEach((event) => {
|
|
109
|
+
const startDate = new Date(event.start_time)
|
|
110
|
+
const endDate = new Date(event.end_time)
|
|
111
|
+
|
|
112
|
+
// Find which day this event belongs to
|
|
113
|
+
const dayIndex = weekDays.value.findIndex(day => day.getDate() === startDate.getDate()
|
|
114
|
+
&& day.getMonth() === startDate.getMonth()
|
|
115
|
+
&& day.getFullYear() === startDate.getFullYear()
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
if (dayIndex === -1) return
|
|
119
|
+
|
|
120
|
+
// Calculate vertical positioning
|
|
121
|
+
const startMinutes = startDate.getHours() * 60 + startDate.getMinutes()
|
|
122
|
+
const endMinutes = endDate.getHours() * 60 + endDate.getMinutes()
|
|
123
|
+
const top = (startMinutes / slotDuration) * (slotHeight / 2)
|
|
124
|
+
const height = Math.max(((endMinutes - startMinutes) / slotDuration) * (slotHeight / 2), 30)
|
|
125
|
+
|
|
126
|
+
const weekEvent: WeekViewEvent = {
|
|
127
|
+
...event,
|
|
128
|
+
top,
|
|
129
|
+
height,
|
|
130
|
+
left: 0,
|
|
131
|
+
width: 95,
|
|
132
|
+
overlappingEvents: 0,
|
|
133
|
+
position: 0
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Group by day and time range for overlapping calculation
|
|
137
|
+
const key = `${dayIndex}-${Math.floor(startMinutes / 30)}`
|
|
138
|
+
if (!overlappingGroups[key]) {
|
|
139
|
+
overlappingGroups[key] = []
|
|
140
|
+
}
|
|
141
|
+
overlappingGroups[key].push(weekEvent)
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
// Adjust overlapping events
|
|
145
|
+
Object.values(overlappingGroups).forEach((group) => {
|
|
146
|
+
if (group.length > 1) {
|
|
147
|
+
const groupWidth = 95 / group.length
|
|
148
|
+
group.forEach((event, index) => {
|
|
149
|
+
event.overlappingEvents = group.length
|
|
150
|
+
event.position = index
|
|
151
|
+
event.width = groupWidth
|
|
152
|
+
event.left = index * groupWidth
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
events.push(...group)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
return events
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
// Mouse event handlers for drag-to-create functionality
|
|
162
|
+
function handleMouseDown(e: MouseEvent) {
|
|
163
|
+
const target = e.target as HTMLElement
|
|
164
|
+
if (!target.closest('.time-slot')) return
|
|
165
|
+
|
|
166
|
+
dragState.value.isDragging = true
|
|
167
|
+
dragState.value.start = { x: e.clientX, y: e.clientY }
|
|
168
|
+
dragState.value.startTime = getTimeFromPosition(e.clientX, e.clientY)
|
|
169
|
+
|
|
170
|
+
document.addEventListener('mousemove', handleMouseMove)
|
|
171
|
+
document.addEventListener('mouseup', handleMouseUp)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function handleMouseMove(e: MouseEvent) {
|
|
175
|
+
if (!dragState.value.isDragging) return
|
|
176
|
+
|
|
177
|
+
dragState.value.end = { x: e.clientX, y: e.clientY }
|
|
178
|
+
dragState.value.endTime = getTimeFromPosition(e.clientX, e.clientY)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function handleMouseUp() {
|
|
182
|
+
if (!dragState.value.isDragging || !dragState.value.startTime || !dragState.value.endTime) return
|
|
183
|
+
|
|
184
|
+
let start = new Date(dragState.value.startTime)
|
|
185
|
+
let end = new Date(dragState.value.endTime)
|
|
186
|
+
|
|
187
|
+
// Ensure end time is after start time
|
|
188
|
+
if (end < start) [start, end] = [end, start]
|
|
189
|
+
|
|
190
|
+
emit('eventCreate', { start_time: start, end_time: end })
|
|
191
|
+
|
|
192
|
+
// Reset drag state
|
|
193
|
+
dragState.value = {
|
|
194
|
+
isDragging: false,
|
|
195
|
+
start: null,
|
|
196
|
+
end: null,
|
|
197
|
+
startTime: null,
|
|
198
|
+
endTime: null
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
document.removeEventListener('mousemove', handleMouseMove)
|
|
202
|
+
document.removeEventListener('mouseup', handleMouseUp)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function getTimeFromPosition(x: number, y: number): Date {
|
|
206
|
+
const rect = document.querySelector('.time-slots')?.getBoundingClientRect()
|
|
207
|
+
if (!rect) return new Date()
|
|
208
|
+
|
|
209
|
+
const dayIndex = Math.floor((x - rect.left) / (rect.width / 7))
|
|
210
|
+
const minutes = Math.floor((y - rect.top) / (slotHeight / 2)) * slotDuration
|
|
211
|
+
|
|
212
|
+
const date = new Date(weekDays.value[dayIndex])
|
|
213
|
+
date.setHours(Math.floor(minutes / 60))
|
|
214
|
+
date.setMinutes(minutes % 60)
|
|
215
|
+
|
|
216
|
+
return date
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Update the current time indicator position
|
|
220
|
+
function updateCurrentTimeIndicator() {
|
|
221
|
+
const now = new Date()
|
|
222
|
+
|
|
223
|
+
// Check if today is in our current week view
|
|
224
|
+
isToday.value = weekDays.value.some(day => day.getDate() === now.getDate()
|
|
225
|
+
&& day.getMonth() === now.getMonth()
|
|
226
|
+
&& day.getFullYear() === now.getFullYear()
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
// Calculate position for the current time line
|
|
230
|
+
const minutes = now.getHours() * 60 + now.getMinutes()
|
|
231
|
+
currentTimeTop.value = (minutes / slotDuration) * (slotHeight / 2)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Wrapper functions for popover utilities
|
|
235
|
+
function openPopover(event: CalendarEvent, e: MouseEvent) {
|
|
236
|
+
openPopoverUtil(
|
|
237
|
+
event,
|
|
238
|
+
e,
|
|
239
|
+
popoverState,
|
|
240
|
+
!!slots.eventContent,
|
|
241
|
+
(evt) => { emit('eventClick', evt) }
|
|
242
|
+
)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function closePopover() {
|
|
246
|
+
closePopoverUtil(popoverState)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Lifecycle hooks
|
|
250
|
+
onMounted(() => {
|
|
251
|
+
document.addEventListener('mousedown', handleMouseDown)
|
|
252
|
+
|
|
253
|
+
// Initialize current time indicator and set up interval to update it
|
|
254
|
+
updateCurrentTimeIndicator()
|
|
255
|
+
currentTimeInterval.value = setInterval(updateCurrentTimeIndicator, 60000)
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
onUnmounted(() => {
|
|
259
|
+
document.removeEventListener('mousedown', handleMouseDown)
|
|
260
|
+
document.removeEventListener('mousemove', handleMouseMove)
|
|
261
|
+
document.removeEventListener('mouseup', handleMouseUp)
|
|
262
|
+
|
|
263
|
+
if (currentTimeInterval.value) {
|
|
264
|
+
clearInterval(currentTimeInterval.value)
|
|
265
|
+
}
|
|
266
|
+
})
|
|
267
|
+
</script>
|
|
268
|
+
|
|
269
|
+
<template>
|
|
270
|
+
<div class="w-100p overflow-hidden m_overflow h-100p grid">
|
|
271
|
+
<div class="weekGrid border-bottom me-1">
|
|
272
|
+
<div />
|
|
273
|
+
<div
|
|
274
|
+
v-for="day in weekDays" :key="day.toISOString()"
|
|
275
|
+
class="day-header p-05 txt-center"
|
|
276
|
+
>
|
|
277
|
+
{{ formatDate(day, 'DDD') }}
|
|
278
|
+
<span
|
|
279
|
+
class="txt-12 round p-025"
|
|
280
|
+
:class="{
|
|
281
|
+
'color-gray': day.toDateString() !== new Date().toDateString(),
|
|
282
|
+
'bg-primary color-white': day.toDateString() === new Date().toDateString(),
|
|
283
|
+
}"
|
|
284
|
+
>
|
|
285
|
+
{{ formatDate(day, 'DD') }}
|
|
286
|
+
</span>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
<div class="overflow h-100p pe-05">
|
|
290
|
+
<div class="weekGrid border-end relative" @mousedown="handleMouseDown">
|
|
291
|
+
<div>
|
|
292
|
+
<div v-for="slot in timeSlots" :key="slot.time" class="txt-light txt-12 color-gray flex justify-content-center bg-gray-light border-start" :style="{ height: `${slotHeight}px` }">
|
|
293
|
+
{{ slot.time }}
|
|
294
|
+
</div>
|
|
295
|
+
</div>
|
|
296
|
+
|
|
297
|
+
<div v-if="isToday" class=" absolute end w-100p z-2 flex pointer-events-none ps-4-5" :style="{ top: `${currentTimeTop}px` }">
|
|
298
|
+
<div class="current-time-dot h-10px aspect-ratio-1 round bg-primary" />
|
|
299
|
+
<div class="current-time-line w-100p bg-primary" />
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
<div v-for="day in weekDays" :key="day.toISOString()" class="day-column top bottom border-start relative">
|
|
303
|
+
<template
|
|
304
|
+
v-for="event in processedEvents.filter(e =>
|
|
305
|
+
new Date(e.start_time).toDateString() === day.toDateString())"
|
|
306
|
+
:key="event.id"
|
|
307
|
+
>
|
|
308
|
+
<div
|
|
309
|
+
class="event absolute radius-05 overflow-hidden pointer transition z-1"
|
|
310
|
+
:style="{
|
|
311
|
+
top: `${event.top}px`,
|
|
312
|
+
height: `${event.height}px`,
|
|
313
|
+
left: `${event.left}%`,
|
|
314
|
+
width: `${event.width}%`,
|
|
315
|
+
backgroundColor: event.color || 'var(--bgl-primary)',
|
|
316
|
+
}"
|
|
317
|
+
@click.stop="slots.eventContent ? openPopover(event, $event) : emit('eventClick', event)"
|
|
318
|
+
>
|
|
319
|
+
<div class="overflow-hidden color-text-light p-025 txt12 h-100p">
|
|
320
|
+
<div class="white-space ellipsis-1">
|
|
321
|
+
{{ event.title }}
|
|
322
|
+
</div>
|
|
323
|
+
<div class="txt10 opacity-8">
|
|
324
|
+
{{ formatDate(event.start_time, 'HH:mm') }}
|
|
325
|
+
</div>
|
|
326
|
+
</div>
|
|
327
|
+
</div>
|
|
328
|
+
</template>
|
|
329
|
+
</div>
|
|
330
|
+
|
|
331
|
+
<!-- Drag selection preview -->
|
|
332
|
+
<div
|
|
333
|
+
v-if="dragState.isDragging && dragState.start && dragState.end"
|
|
334
|
+
class="drag-preview absolute bg-primary pointer-events-none"
|
|
335
|
+
:style="{
|
|
336
|
+
left: `${Math.min(dragState.start.x, dragState.end.x)}px`,
|
|
337
|
+
top: `${Math.min(dragState.start.y, dragState.end.y)}px`,
|
|
338
|
+
width: `${Math.abs(dragState.end.x - dragState.start.x)}px`,
|
|
339
|
+
height: `${Math.abs(dragState.end.y - dragState.start.y)}px`,
|
|
340
|
+
}"
|
|
341
|
+
/>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
|
|
345
|
+
<!-- Custom Popover -->
|
|
346
|
+
<Card
|
|
347
|
+
v-if="showPopover && activeEvent"
|
|
348
|
+
ref="popoverRef"
|
|
349
|
+
v-click-outside="closePopover"
|
|
350
|
+
thin
|
|
351
|
+
class="custom-popover fixed z-999 radius-05 bg-white w350"
|
|
352
|
+
:style="{
|
|
353
|
+
top: `${popoverPosition.top}px`,
|
|
354
|
+
left: `${popoverPosition.left}px`,
|
|
355
|
+
maxWidth: `${popoverPosition.width}px`,
|
|
356
|
+
}"
|
|
357
|
+
>
|
|
358
|
+
<slot name="eventContent" :event="activeEvent" />
|
|
359
|
+
</Card>
|
|
360
|
+
<div class="border-bottom me-1" />
|
|
361
|
+
</div>
|
|
362
|
+
</template>
|
|
363
|
+
|
|
364
|
+
<style scoped>
|
|
365
|
+
.weekGrid{
|
|
366
|
+
display: grid;
|
|
367
|
+
grid-template-columns: 5rem repeat(7, 1fr);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.days-column {
|
|
371
|
+
flex-grow: 1;
|
|
372
|
+
display: flex;
|
|
373
|
+
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.time-slot {
|
|
377
|
+
height: 30px;
|
|
378
|
+
display: flex;
|
|
379
|
+
align-items: center;
|
|
380
|
+
justify-content: center;
|
|
381
|
+
color: var(--text-muted);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.time-slots {
|
|
385
|
+
flex-grow: 1;
|
|
386
|
+
display: flex;
|
|
387
|
+
overflow: auto;
|
|
388
|
+
position: relative;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.day-column {
|
|
392
|
+
flex: 1;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.event {
|
|
396
|
+
margin-right: 2px;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.event:hover {
|
|
400
|
+
z-index: 1;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.drag-preview {
|
|
404
|
+
border: 2px solid var(--bgl-primary);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.current-time-line {
|
|
408
|
+
height: 2px;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
.custom-popover {
|
|
412
|
+
min-width: 250px;
|
|
413
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
414
|
+
animation: fadeIn 0.2s ease;
|
|
415
|
+
transform-origin: center left;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
@keyframes fadeIn {
|
|
419
|
+
from {
|
|
420
|
+
opacity: 0;
|
|
421
|
+
transform: scale(0.95);
|
|
422
|
+
}
|
|
423
|
+
to {
|
|
424
|
+
opacity: 1;
|
|
425
|
+
transform: scale(1);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
@media screen and (max-width: 910px) {
|
|
429
|
+
|
|
430
|
+
}
|
|
431
|
+
</style>
|