Skip to content

Commit 2fc6a78

Browse files
authored
feat: show events spanning midnight on both days (#270)
Adds a new feature which shows events which span midnight to be shown on both of the day columns in "week" mode.
2 parents 377fe19 + e02a6cf commit 2fc6a78

File tree

5 files changed

+153
-141
lines changed

5 files changed

+153
-141
lines changed

dev/App.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ const events = ref<CalendarEvent[]>(
110110
endDate,
111111
description: randomText(),
112112
color: randomColor(),
113-
readonly: true,
113+
readonly: false,
114114
};
115115
})
116116
);

src/components/Day.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
:intervalHeight="intervalHeight"
3030
:intervalMinutes="intervalMinutes"
3131
:concurrencyMode="concurrencyMode"
32+
:column-date="date"
3233
@event-mousedown="(h: 'top' | 'bottom' | 'body') => emits('event-mousedown', event, h)"
3334
@event-mouseup="emits('event-mouseup')"
3435
@event-clicked="emits('event-clicked', event)"
@@ -89,7 +90,7 @@ onUnmounted(() => {
8990
const isDateToday = computed(() => isSameDay(now.value, props.date));
9091
9192
const filteredEvents = computed(() => {
92-
let filtered = props.events.filter((e) => isSameDay(e.startDate, props.date));
93+
let filtered = props.events.filter((e) => isSameDay(e.startDate, props.date) || isSameDay(e.endDate, props.date));
9394
return props.concurrencyMode == "stack"
9495
? processConcurrency(filtered)
9596
: calculatePositions(filtered);

src/components/DayEvent.vue

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
</div>
5555

5656
<div
57-
v-if="!event.readonly"
57+
v-if="!event.readonly && !restrictStart"
5858
style="
5959
top: 0px;
6060
position: absolute;
@@ -67,7 +67,7 @@
6767
@mousedown.stop="onMouseDown('top')"
6868
/>
6969
<div
70-
v-if="!event.readonly"
70+
v-if="!event.readonly && !restrictEnd"
7171
style="
7272
bottom: 0px;
7373
position: absolute;
@@ -118,7 +118,14 @@
118118
</template>
119119

120120
<script setup lang="ts">
121-
import { format, differenceInMinutes } from "date-fns";
121+
import {
122+
format,
123+
differenceInMinutes,
124+
isSameDay,
125+
endOfDay,
126+
startOfDay,
127+
addMinutes,
128+
} from "date-fns";
122129
import { $CalendarEvent } from "../types/interfaces";
123130
import {
124131
computed,
@@ -154,6 +161,7 @@ const emits = defineEmits<{
154161
155162
const props = defineProps<{
156163
event: $CalendarEvent;
164+
columnDate: Date;
157165
}>();
158166
159167
watch(hovering, (v) => {
@@ -176,19 +184,47 @@ onUnmounted(() => {
176184
removeEventListener("wheel", onMouseWheel);
177185
});
178186
187+
const minutesPastMidnight = computed(() =>
188+
differenceInMinutes(props.event.endDate, endOfDay(props.columnDate))
189+
);
190+
191+
const spansMidnight = computed(
192+
() => !isSameDay(props.event.startDate, props.event.endDate)
193+
);
194+
195+
const restrictStart = computed(
196+
() => spansMidnight.value && isSameDay(props.event.endDate, props.columnDate)
197+
);
198+
199+
const restrictEnd = computed(
200+
() => minutesPastMidnight.value > config.value.hoursPastMidnight * 60
201+
);
202+
179203
const zIndex = computed(() => (bringToFront.value ? 99 : props.event.zIndex));
180204
181205
const top = computed(() => {
182206
return Math.round(
183-
(props.event.startDate.getHours() * 60 +
184-
props.event.startDate.getMinutes()) *
185-
(config.value.intervalHeight / config.value.intervalMinutes)
207+
restrictStart.value
208+
? 0
209+
: (props.event.startDate.getHours() * 60 +
210+
props.event.startDate.getMinutes()) *
211+
(config.value.intervalHeight / config.value.intervalMinutes)
186212
);
187213
});
188214
189215
const height = computed(() => {
190-
let h =
191-
differenceInMinutes(props.event.endDate, props.event.startDate) *
216+
const start = restrictStart.value
217+
? startOfDay(props.event.endDate)
218+
: props.event.startDate;
219+
const end = restrictEnd.value
220+
? addMinutes(
221+
endOfDay(props.event.startDate),
222+
Math.min(minutesPastMidnight.value, config.value.hoursPastMidnight * 60)
223+
)
224+
: props.event.endDate;
225+
226+
const h =
227+
differenceInMinutes(end, start) *
192228
(config.value.intervalHeight / config.value.intervalMinutes);
193229
return Math.max(h, config.value.intervalHeight * 0.5);
194230
});
@@ -234,9 +270,6 @@ function onMouseMove(e: MouseEvent) {
234270
235271
function onMouseDown(handle: "top" | "bottom" | "body") {
236272
showTooltip.value = false;
237-
if (props.event.readonly === true) {
238-
return;
239-
}
240273
document.addEventListener("mouseup", onMouseUp);
241274
emits("event-mousedown", handle);
242275
}
@@ -303,6 +336,7 @@ const tooltipOffset = ref(0);
303336
.event-card:hover {
304337
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15), 0 8px 16px rgba(0, 0, 0, 0.15);
305338
}
339+
306340
.event-card-root > * {
307341
box-sizing: border-box;
308342
width: 100%;

0 commit comments

Comments
 (0)