A little better but still broken. I need easier tasks for a while.
This commit is contained in:
@@ -13,6 +13,9 @@ import {
|
||||
daysInclusive,
|
||||
addDaysStr,
|
||||
formatDateRange,
|
||||
getMondayOfISOWeek,
|
||||
getOccurrenceIndex,
|
||||
getVirtualOccurrenceEndDate,
|
||||
} from '@/utils/date'
|
||||
import { toLocalString, fromLocalString } from '@/utils/date'
|
||||
|
||||
@@ -153,25 +156,11 @@ function createWeek(virtualWeek) {
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const dateStr = toLocalString(cur)
|
||||
const storedEvents = []
|
||||
const idSet = calendarStore.dates.get(dateStr)
|
||||
if (idSet) {
|
||||
// Support Set or Array; ignore unexpected shapes
|
||||
if (idSet instanceof Set) {
|
||||
idSet.forEach((id) => {
|
||||
const ev = calendarStore.events.get(id)
|
||||
if (ev) storedEvents.push(ev)
|
||||
})
|
||||
} else if (Array.isArray(idSet)) {
|
||||
for (const id of idSet) {
|
||||
const ev = calendarStore.events.get(id)
|
||||
if (ev) storedEvents.push(ev)
|
||||
}
|
||||
} else if (typeof idSet === 'object' && idSet !== null) {
|
||||
// If mistakenly hydrated as plain object {id:true,...}
|
||||
for (const id of Object.keys(idSet)) {
|
||||
const ev = calendarStore.events.get(id)
|
||||
if (ev) storedEvents.push(ev)
|
||||
}
|
||||
|
||||
// Find all non-repeating events that occur on this date
|
||||
for (const ev of calendarStore.events.values()) {
|
||||
if (!ev.isRepeating && dateStr >= ev.startDate && dateStr <= ev.endDate) {
|
||||
storedEvents.push(ev)
|
||||
}
|
||||
}
|
||||
// Build day events starting with stored (base/spanning) then virtual occurrences
|
||||
@@ -179,56 +168,45 @@ function createWeek(virtualWeek) {
|
||||
for (const base of repeatingBases) {
|
||||
// Skip if the base itself already on this date (already in storedEvents)
|
||||
if (dateStr >= base.startDate && dateStr <= base.endDate) continue
|
||||
if (calendarStore.occursOnDate(base, dateStr)) {
|
||||
// Determine sequential occurrence index: base event = 0, first repeat = 1, etc.
|
||||
let recurrenceIndex = 0
|
||||
try {
|
||||
if (base.repeat === 'weeks') {
|
||||
const pattern = base.repeatWeekdays || []
|
||||
const interval = base.repeatInterval || 1
|
||||
const baseStart = new Date(base.startDate + 'T00:00:00')
|
||||
const baseEnd = new Date(base.endDate + 'T00:00:00')
|
||||
const target = new Date(dateStr + 'T00:00:00')
|
||||
const WEEK_MS = 7 * 86400000
|
||||
const baseBlockStart = new Date(baseStart)
|
||||
baseBlockStart.setDate(baseStart.getDate() - baseStart.getDay())
|
||||
function isAligned(d) {
|
||||
const blk = new Date(d)
|
||||
blk.setDate(d.getDate() - d.getDay())
|
||||
const diff = Math.floor((blk - baseBlockStart) / WEEK_MS)
|
||||
return diff % interval === 0
|
||||
|
||||
// Check if any occurrence of this repeating event spans through this date
|
||||
const baseStart = fromLocalString(base.startDate)
|
||||
const baseEnd = fromLocalString(base.endDate)
|
||||
const spanDays = Math.max(0, Math.round((baseEnd - baseStart) / (24 * 60 * 60 * 1000)))
|
||||
const currentDate = fromLocalString(dateStr)
|
||||
|
||||
let occurrenceFound = false
|
||||
|
||||
// Check dates going backwards to find an occurrence that might span to this date
|
||||
for (let offset = 0; offset <= spanDays && !occurrenceFound; offset++) {
|
||||
const candidateStart = new Date(currentDate)
|
||||
candidateStart.setDate(candidateStart.getDate() - offset)
|
||||
const candidateStartStr = toLocalString(candidateStart)
|
||||
|
||||
const occurrenceIndex = getOccurrenceIndex(base, candidateStartStr)
|
||||
if (occurrenceIndex !== null) {
|
||||
// Calculate the end date of this occurrence
|
||||
const virtualEndDate = getVirtualOccurrenceEndDate(base, candidateStartStr)
|
||||
|
||||
// Check if this occurrence spans through the current date
|
||||
if (dateStr >= candidateStartStr && dateStr <= virtualEndDate) {
|
||||
// Create virtual occurrence (if not already created)
|
||||
const virtualId = base.id + '_v_' + candidateStartStr
|
||||
const alreadyExists = dayEvents.some((ev) => ev.id === virtualId)
|
||||
|
||||
if (!alreadyExists) {
|
||||
dayEvents.push({
|
||||
...base,
|
||||
id: virtualId,
|
||||
startDate: candidateStartStr,
|
||||
endDate: virtualEndDate,
|
||||
_recurrenceIndex: occurrenceIndex,
|
||||
_baseId: base.id,
|
||||
})
|
||||
}
|
||||
// Count valid occurrences after base end and before target
|
||||
let count = 0
|
||||
const cursor = new Date(baseEnd)
|
||||
cursor.setDate(cursor.getDate() + 1)
|
||||
while (cursor < target) {
|
||||
if (pattern[cursor.getDay()] && isAligned(cursor)) count++
|
||||
cursor.setDate(cursor.getDate() + 1)
|
||||
}
|
||||
// Target itself is guaranteed valid (occursOnDate passed), so its index is count+1
|
||||
recurrenceIndex = count + 1
|
||||
} else if (base.repeat === 'months') {
|
||||
const baseStart = new Date(base.startDate + 'T00:00:00')
|
||||
const target = new Date(dateStr + 'T00:00:00')
|
||||
const interval = base.repeatInterval || 1
|
||||
const diffMonths =
|
||||
(target.getFullYear() - baseStart.getFullYear()) * 12 +
|
||||
(target.getMonth() - baseStart.getMonth())
|
||||
// diffMonths should be multiple of interval; sequential index = diffMonths/interval
|
||||
recurrenceIndex = diffMonths / interval
|
||||
occurrenceFound = true
|
||||
}
|
||||
} catch {
|
||||
recurrenceIndex = 0
|
||||
}
|
||||
dayEvents.push({
|
||||
...base,
|
||||
id: base.id + '_v_' + dateStr,
|
||||
startDate: dateStr,
|
||||
endDate: dateStr,
|
||||
_recurrenceIndex: recurrenceIndex,
|
||||
_baseId: base.id,
|
||||
})
|
||||
}
|
||||
}
|
||||
const dow = cur.getDay()
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useCalendarStore } from '@/stores/CalendarStore'
|
||||
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
|
||||
import WeekdaySelector from './WeekdaySelector.vue'
|
||||
import Numeric from './Numeric.vue'
|
||||
import { addDaysStr } from '@/utils/date'
|
||||
import { addDaysStr, getMondayOfISOWeek } from '@/utils/date'
|
||||
|
||||
const props = defineProps({
|
||||
selection: { type: Object, default: () => ({ startDate: null, dayCount: 0 }) },
|
||||
@@ -173,11 +173,9 @@ function openEditDialog(payload) {
|
||||
// Count valid repeat occurrences (pattern + interval alignment) AFTER the base span
|
||||
const interval = event.repeatInterval || 1
|
||||
const WEEK_MS = 7 * 86400000
|
||||
const baseBlockStart = new Date(baseStart)
|
||||
baseBlockStart.setDate(baseStart.getDate() - baseStart.getDay())
|
||||
const baseBlockStart = getMondayOfISOWeek(baseStart)
|
||||
function isAligned(d) {
|
||||
const blk = new Date(d)
|
||||
blk.setDate(d.getDate() - d.getDay())
|
||||
const blk = getMondayOfISOWeek(d)
|
||||
const diff = Math.floor((blk - baseBlockStart) / WEEK_MS)
|
||||
return diff % interval === 0
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user