Event moving fixed again, splitting correctly for recurrent events.
This commit is contained in:
parent
4529d0c412
commit
d794758b54
@ -161,6 +161,25 @@ function startLocalDrag(init, evt) {
|
||||
window.addEventListener('pointercancel', onDragPointerUp, { passive: false })
|
||||
}
|
||||
|
||||
// Determine date under pointer: traverse DOM to find day cell carrying data-date attribute
|
||||
function getDateUnderPointer(x, y, el) {
|
||||
let cur = el
|
||||
while (cur) {
|
||||
if (cur.dataset && cur.dataset.date) {
|
||||
return { date: cur.dataset.date }
|
||||
}
|
||||
cur = cur.parentElement
|
||||
}
|
||||
// Fallback: elementFromPoint scan
|
||||
const probe = document.elementFromPoint(x, y)
|
||||
let p = probe
|
||||
while (p) {
|
||||
if (p.dataset && p.dataset.date) return { date: p.dataset.date }
|
||||
p = p.parentElement
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function onDragPointerMove(e) {
|
||||
const st = dragState.value
|
||||
if (!st) return
|
||||
@ -234,9 +253,12 @@ function normalizeDateOrder(aStr, bStr) {
|
||||
}
|
||||
|
||||
function applyRangeDuringDrag(st, startDate, endDate) {
|
||||
// If dragging a virtual occurrence, map to base move without changing recurrence pattern mid-series.
|
||||
// We disallow resizing individual virtual occurrences; treat as move of whole series anchor.
|
||||
if (st.isVirtual && st.mode !== 'move') return
|
||||
if (st.isVirtual) {
|
||||
if (st.mode !== 'move') return // no resize for virtual occurrence
|
||||
// Split-move: occurrence being dragged treated as first of new series
|
||||
store.splitMoveVirtualOccurrence(st.id, st.startDate, startDate, endDate)
|
||||
return
|
||||
}
|
||||
store.setEventRange(st.id, startDate, endDate, { mode: st.mode })
|
||||
}
|
||||
|
||||
|
@ -586,6 +586,98 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
// no expansion
|
||||
},
|
||||
|
||||
// Split a repeating series at a specific occurrence date and move that occurrence (and future) to new range
|
||||
splitMoveVirtualOccurrence(baseId, occurrenceDateStr, newStartStr, newEndStr) {
|
||||
const base = this._findEventInAnyList(baseId)
|
||||
if (!base || !base.isRepeating) return
|
||||
const originalCountRaw = base.repeatCount
|
||||
const spanDays = Math.max(
|
||||
0,
|
||||
Math.round(
|
||||
(fromLocalString(base.endDate) - fromLocalString(base.startDate)) / (24 * 60 * 60 * 1000),
|
||||
),
|
||||
)
|
||||
const occurrenceDate = fromLocalString(occurrenceDateStr)
|
||||
const baseStart = fromLocalString(base.startDate)
|
||||
if (occurrenceDate <= baseStart) {
|
||||
// Moving the base itself: just move entire series
|
||||
this.setEventRange(baseId, newStartStr, newEndStr, { mode: 'move' })
|
||||
return
|
||||
}
|
||||
let keptOccurrences = 0 // number of occurrences BEFORE the moved one
|
||||
if (base.repeat === 'weeks') {
|
||||
const interval = base.repeatInterval || 1
|
||||
const pattern = base.repeatWeekdays || []
|
||||
if (!pattern.some(Boolean)) return
|
||||
const WEEK_MS = 7 * 86400000
|
||||
const blockStartBase = new Date(baseStart)
|
||||
blockStartBase.setDate(blockStartBase.getDate() - blockStartBase.getDay())
|
||||
function isAligned(d) {
|
||||
const blk = new Date(d)
|
||||
blk.setDate(d.getDate() - d.getDay())
|
||||
const diff = Math.floor((blk - blockStartBase) / WEEK_MS)
|
||||
return diff % interval === 0
|
||||
}
|
||||
const cursor = new Date(baseStart)
|
||||
while (cursor < occurrenceDate) {
|
||||
if (pattern[cursor.getDay()] && isAligned(cursor)) keptOccurrences++
|
||||
cursor.setDate(cursor.getDate() + 1)
|
||||
}
|
||||
} else if (base.repeat === 'months') {
|
||||
const diffMonths =
|
||||
(occurrenceDate.getFullYear() - baseStart.getFullYear()) * 12 +
|
||||
(occurrenceDate.getMonth() - baseStart.getMonth())
|
||||
const interval = base.repeatInterval || 1
|
||||
if (diffMonths <= 0 || diffMonths % interval !== 0) return // invalid occurrence
|
||||
keptOccurrences = diffMonths // base is occurrence 0; we keep all before diffMonths
|
||||
} else {
|
||||
// Unsupported repeat type
|
||||
return
|
||||
}
|
||||
// Truncate original series to keptOccurrences
|
||||
this._terminateRepeatSeriesAtIndex(baseId, keptOccurrences)
|
||||
// Compute remaining occurrences count
|
||||
let remainingCount = 'unlimited'
|
||||
if (originalCountRaw !== 'unlimited') {
|
||||
const total = parseInt(originalCountRaw, 10)
|
||||
if (!isNaN(total)) {
|
||||
const rem = total - keptOccurrences
|
||||
if (rem <= 0) return
|
||||
remainingCount = String(rem)
|
||||
}
|
||||
}
|
||||
// Determine repeat-specific adjustments
|
||||
let repeatWeekdays = base.repeatWeekdays
|
||||
if (base.repeat === 'weeks' && Array.isArray(base.repeatWeekdays)) {
|
||||
// Rotate pattern so that the moved occurrence weekday stays active relative to new anchor
|
||||
const origWeekday = occurrenceDate.getDay()
|
||||
const newWeekday = fromLocalString(newStartStr).getDay()
|
||||
const shift = newWeekday - origWeekday
|
||||
if (shift !== 0) {
|
||||
const rotated = [false, false, false, false, false, false, false]
|
||||
for (let i = 0; i < 7; i++) {
|
||||
if (base.repeatWeekdays[i]) {
|
||||
let ni = (i + shift) % 7
|
||||
if (ni < 0) ni += 7
|
||||
rotated[ni] = true
|
||||
}
|
||||
}
|
||||
repeatWeekdays = rotated
|
||||
}
|
||||
}
|
||||
// Create continuation series starting at newStartStr
|
||||
this.createEvent({
|
||||
title: base.title,
|
||||
startDate: newStartStr,
|
||||
endDate: newEndStr,
|
||||
colorId: base.colorId,
|
||||
repeat: base.repeat,
|
||||
repeatInterval: base.repeatInterval,
|
||||
repeatCount: remainingCount,
|
||||
repeatWeekdays,
|
||||
})
|
||||
},
|
||||
|
||||
// Split a repeating series at a given occurrence index; returns new series id
|
||||
splitRepeatSeries(baseId, occurrenceIndex, newStartStr, newEndStr, _grabbedWeekday) {
|
||||
const base = this._findEventInAnyList(baseId)
|
||||
|
Loading…
x
Reference in New Issue
Block a user