Event resize/move bugs and UX.

This commit is contained in:
Leo Vasanko 2025-08-27 09:42:23 -06:00
parent cfb1b2ce5a
commit 8f092b5653

View File

@ -26,10 +26,12 @@
> >
<span class="event-title">{{ span.title }}</span> <span class="event-title">{{ span.title }}</span>
<div <div
v-if="!span.hasPrevWeek"
class="resize-handle left" class="resize-handle left"
@pointerdown="handleResizePointerDown(span, 'resize-left', $event)" @pointerdown="handleResizePointerDown(span, 'resize-left', $event)"
></div> ></div>
<div <div
v-if="!span.hasNextWeek"
class="resize-handle right" class="resize-handle right"
@pointerdown="handleResizePointerDown(span, 'resize-right', $event)" @pointerdown="handleResizePointerDown(span, 'resize-right', $event)"
></div> ></div>
@ -92,6 +94,17 @@ const eventSegments = computed(() => {
} else { } else {
sp.hasNextWeek = false sp.hasNextWeek = false
} }
// Compute full occurrence start/end (may extend beyond visible week)
if (sp.minNDay != null) {
sp.occurrenceStartDate = addDaysStr(sp.startDate, -sp.minNDay)
if (sp.days != null) {
sp.occurrenceEndDate = addDaysStr(sp.occurrenceStartDate, sp.days - 1)
} else {
// Fallback: approximate using maxNDay if days unknown
const total = (sp.maxNDay || 0) + 1
sp.occurrenceEndDate = addDaysStr(sp.occurrenceStartDate, total - 1)
}
}
}) })
// Sort so longer multi-day first, then earlier, then id for stability // Sort so longer multi-day first, then earlier, then id for stability
spans.sort((a, b) => { spans.sort((a, b) => {
@ -206,7 +219,10 @@ function handleEventPointerDown(span, event) {
if (event.target.classList.contains('resize-handle')) return if (event.target.classList.contains('resize-handle')) return
event.stopPropagation() event.stopPropagation()
const baseId = span.id const baseId = span.id
let anchorDate = span.startDate // Use full occurrence boundaries for drag logic (not clipped week portion)
const fullStart = span.occurrenceStartDate || span.startDate
const fullEnd = span.occurrenceEndDate || span.endDate
let anchorDate = fullStart
try { try {
const spanDays = daysInclusive(span.startDate, span.endDate) const spanDays = daysInclusive(span.startDate, span.endDate)
const targetEl = event.currentTarget const targetEl = event.currentTarget
@ -218,7 +234,8 @@ function handleEventPointerDown(span, event) {
if (!isFinite(dayIndex)) dayIndex = 0 if (!isFinite(dayIndex)) dayIndex = 0
if (dayIndex < 0) dayIndex = 0 if (dayIndex < 0) dayIndex = 0
if (dayIndex >= spanDays) dayIndex = spanDays - 1 if (dayIndex >= spanDays) dayIndex = spanDays - 1
anchorDate = addDaysStr(span.startDate, dayIndex) const absoluteOffset = (span.minNDay || 0) + dayIndex
anchorDate = addDaysStr(fullStart, absoluteOffset)
} }
} catch (e) {} } catch (e) {}
startLocalDrag( startLocalDrag(
@ -229,8 +246,8 @@ function handleEventPointerDown(span, event) {
pointerStartX: event.clientX, pointerStartX: event.clientX,
pointerStartY: event.clientY, pointerStartY: event.clientY,
anchorDate, anchorDate,
startDate: span.startDate, startDate: fullStart,
endDate: span.endDate, endDate: fullEnd,
n: span.n, n: span.n,
}, },
event, event,
@ -240,6 +257,8 @@ function handleEventPointerDown(span, event) {
function handleResizePointerDown(span, mode, event) { function handleResizePointerDown(span, mode, event) {
event.stopPropagation() event.stopPropagation()
const baseId = span.id const baseId = span.id
const fullStart = span.occurrenceStartDate || span.startDate
const fullEnd = span.occurrenceEndDate || span.endDate
startLocalDrag( startLocalDrag(
{ {
id: baseId, id: baseId,
@ -248,8 +267,8 @@ function handleResizePointerDown(span, mode, event) {
pointerStartX: event.clientX, pointerStartX: event.clientX,
pointerStartY: event.clientY, pointerStartY: event.clientY,
anchorDate: null, anchorDate: null,
startDate: span.startDate, startDate: fullStart,
endDate: span.endDate, endDate: fullEnd,
n: span.n, n: span.n,
}, },
event, event,
@ -437,28 +456,21 @@ function onDragPointerUp(e) {
store.$history?.endCompound() store.$history?.endCompound()
} }
function computeTentativeRangeFromPointer(st, dropDateStr) { const min = (a, b) => (a < b ? a : b)
const max = (a, b) => (a > b ? a : b)
function computeTentativeRangeFromPointer(st, current) {
const anchorOffset = st.anchorOffset || 0 const anchorOffset = st.anchorOffset || 0
const spanDays = st.originSpanDays || daysInclusive(st.startDate, st.endDate) const spanDays = st.originSpanDays || daysInclusive(st.startDate, st.endDate)
let startStr = st.startDate
let endStr = st.endDate
if (st.mode === 'move') { if (st.mode === 'move') {
startStr = addDaysStr(dropDateStr, -anchorOffset) const ns = addDaysStr(current, -anchorOffset)
endStr = addDaysStr(startStr, spanDays - 1) const ne = addDaysStr(ns, spanDays - 1)
} else if (st.mode === 'resize-left') { return [ns, ne]
startStr = dropDateStr
endStr = st.endDate
} else if (st.mode === 'resize-right') {
startStr = st.startDate
endStr = dropDateStr
}
return normalizeDateOrder(startStr, endStr)
} }
if (st.mode === 'resize-left') return [min(st.endDate, current), st.endDate]
if (st.mode === 'resize-right') return [st.startDate, max(st.startDate, current)]
function normalizeDateOrder(aStr, bStr) { return [st.startDate, st.endDate]
if (!aStr) return [bStr, bStr]
if (!bStr) return [aStr, aStr]
return aStr <= bStr ? [aStr, bStr] : [bStr, aStr]
} }
function applyRangeDuringDrag(st, startDate, endDate) { function applyRangeDuringDrag(st, startDate, endDate) {