Fix display of repeated multi day events

This commit is contained in:
Leo Vasanko 2025-08-22 12:10:33 -06:00
parent 07b22fa885
commit 1b1a95da1d

View File

@ -62,41 +62,51 @@ function generateRepeatOccurrencesForDate(targetDateStr) {
if (baseEvent.repeat === 'weeks') {
const repeatWeekdays = baseEvent.repeatWeekdays
const targetWeekday = targetDate.getDay()
if (!repeatWeekdays[targetWeekday]) continue
if (targetDate < baseStartDate) continue
const maxOccurrences =
baseEvent.repeatCount === 'unlimited' ? Infinity : parseInt(baseEvent.repeatCount, 10)
const interval = baseEvent.repeatInterval || 1
const maxOccurrences = baseEvent.repeatCount === 'unlimited' ? Infinity : parseInt(baseEvent.repeatCount, 10)
if (maxOccurrences === 0) continue
// Count occurrences from start up to (and including) target
const interval = baseEvent.repeatInterval || 1
const msPerDay = 24*60*60*1000
// Determine if targetDate lies within some occurrence span. We look backwards up to spanDays to find a start day.
let occStart = null
for (let back=0; back<=spanDays; back++) {
const cand = new Date(targetDate)
cand.setDate(cand.getDate() - back)
if (cand < baseStartDate) break
const daysDiff = Math.floor((cand - baseStartDate)/msPerDay)
const weeksDiff = Math.floor(daysDiff / 7)
if (weeksDiff % interval !== 0) continue
if (repeatWeekdays[cand.getDay()]) {
// candidate start must produce span covering targetDate
const candEnd = new Date(cand)
candEnd.setDate(candEnd.getDate() + spanDays)
if (targetDate <= candEnd) {
occStart = cand
break
}
}
}
if (!occStart) continue
// Skip base occurrence if this is within its span (base already physically stored)
if (occStart.getTime() === baseStartDate.getTime()) continue
// Compute occurrence index (number of previous start days)
let occIdx = 0
// Determine the week distance from baseStartDate to targetDate
const msPerDay = 24 * 60 * 60 * 1000
const daysDiff = Math.floor((targetDate - baseStartDate) / msPerDay)
const weeksDiff = Math.floor(daysDiff / 7)
if (weeksDiff % interval !== 0) continue
// Count occurrences only among valid weeks and selected weekdays
const cursor = new Date(baseStartDate)
while (cursor < targetDate && occIdx < maxOccurrences) {
const cDaysDiff = Math.floor((cursor - baseStartDate) / msPerDay)
while (cursor < occStart && occIdx < maxOccurrences) {
const cDaysDiff = Math.floor((cursor - baseStartDate)/msPerDay)
const cWeeksDiff = Math.floor(cDaysDiff / 7)
if (cWeeksDiff % interval === 0 && repeatWeekdays[cursor.getDay()]) occIdx++
cursor.setDate(cursor.getDate() + 1)
}
if (targetDate.getTime() === baseStartDate.getTime()) {
// skip base occurrence
continue
cursor.setDate(cursor.getDate()+1)
}
if (occIdx >= maxOccurrences) continue
const occStart = new Date(targetDate)
const occEnd = new Date(occStart)
occEnd.setDate(occStart.getDate() + spanDays)
const occStartStr = toLocalString(occStart)
const occEndStr = toLocalString(occEnd)
occurrences.push({
...baseEvent,
id: `${baseEvent.id}_repeat_${occIdx}_${targetWeekday}`,
id: `${baseEvent.id}_repeat_${occIdx}_${occStart.getDay()}`,
startDate: occStartStr,
endDate: occEndStr,
isRepeatOccurrence: true,
@ -123,12 +133,15 @@ function generateRepeatOccurrencesForDate(targetDateStr) {
if (maxOccurrences === 0) continue
const i = intervalsPassed
if (i >= maxOccurrences) continue
// Skip base occurrence
if (i === 0) continue
const currentStart = new Date(baseStartDate)
currentStart.setMonth(baseStartDate.getMonth() + i)
const currentEnd = new Date(currentStart)
currentEnd.setDate(currentStart.getDate() + spanDays)
// If target day lies within base (i===0) we skip because base is stored already
if (i === 0) {
// only skip if targetDate within base span
if (targetDate >= baseStartDate && targetDate <= baseEndDate) continue
}
const currentStartStr = toLocalString(currentStart)
const currentEndStr = toLocalString(currentEnd)
if (currentStartStr <= targetDateStr && targetDateStr <= currentEndStr) {