Major new version #2
@ -244,10 +244,16 @@ function openCreateDialog(selectionData = null) {
|
||||
recurrenceWeekdays.value[startingDay] = true
|
||||
initialWeekday.value = startingDay
|
||||
|
||||
let days = 1
|
||||
if (start && end && start <= end) {
|
||||
const s = fromLocalString(start, DEFAULT_TZ)
|
||||
const e = fromLocalString(end, DEFAULT_TZ)
|
||||
days = Math.max(1, (e - s) / 86400000 + 1)
|
||||
}
|
||||
editingEventId.value = calendarStore.createEvent({
|
||||
title: '',
|
||||
startDate: start,
|
||||
endDate: end,
|
||||
days,
|
||||
colorId: colorId.value,
|
||||
recur:
|
||||
recurrenceEnabled.value && repeat.value !== 'none'
|
||||
@ -306,7 +312,8 @@ function openEditDialog(payload) {
|
||||
if (event.recur.freq === 'weeks' && occurrenceIndex >= 0) {
|
||||
const pattern = event.recur.weekdays || []
|
||||
const baseStart = fromLocalString(event.startDate, DEFAULT_TZ)
|
||||
const baseEnd = fromLocalString(event.endDate, DEFAULT_TZ)
|
||||
const baseEnd = new Date(fromLocalString(event.startDate, DEFAULT_TZ))
|
||||
baseEnd.setDate(baseEnd.getDate() + (event.days || 1) - 1)
|
||||
if (occurrenceIndex === 0) {
|
||||
occurrenceDate = baseStart
|
||||
weekday = baseStart.getDay()
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ref } from 'vue'
|
||||
import { addDays, differenceInWeeks, differenceInCalendarDays } from 'date-fns'
|
||||
import { addDays, differenceInWeeks } from 'date-fns'
|
||||
import {
|
||||
toLocalString,
|
||||
fromLocalString,
|
||||
@ -72,19 +72,27 @@ export function createVirtualWeekManager({
|
||||
const collectEventsForDate = (dateStr, curDateObj) => {
|
||||
const storedEvents = []
|
||||
for (const ev of calendarStore.events.values()) {
|
||||
if (!ev.recur && dateStr >= ev.startDate && dateStr <= ev.endDate) {
|
||||
storedEvents.push(ev)
|
||||
if (!ev.recur) {
|
||||
const evEnd = toLocalString(
|
||||
addDays(fromLocalString(ev.startDate, DEFAULT_TZ), (ev.days || 1) - 1),
|
||||
DEFAULT_TZ,
|
||||
)
|
||||
if (dateStr >= ev.startDate && dateStr <= evEnd) {
|
||||
storedEvents.push({ ...ev, endDate: evEnd })
|
||||
}
|
||||
}
|
||||
}
|
||||
const dayEvents = [...storedEvents]
|
||||
for (const base of repeatingBases) {
|
||||
if (dateStr >= base.startDate && dateStr <= base.endDate) {
|
||||
dayEvents.push({ ...base, _recurrenceIndex: 0, _baseId: base.id })
|
||||
const baseEnd = toLocalString(
|
||||
addDays(fromLocalString(base.startDate, DEFAULT_TZ), (base.days || 1) - 1),
|
||||
DEFAULT_TZ,
|
||||
)
|
||||
if (dateStr >= base.startDate && dateStr <= baseEnd) {
|
||||
dayEvents.push({ ...base, endDate: baseEnd, _recurrenceIndex: 0, _baseId: base.id })
|
||||
continue
|
||||
}
|
||||
const baseStart = fromLocalString(base.startDate, DEFAULT_TZ)
|
||||
const baseEnd = fromLocalString(base.endDate, DEFAULT_TZ)
|
||||
const spanDays = Math.max(0, differenceInCalendarDays(baseEnd, baseStart))
|
||||
const spanDays = (base.days || 1) - 1
|
||||
const currentDate = curDateObj
|
||||
let occurrenceFound = false
|
||||
for (let offset = 0; offset <= spanDays && !occurrenceFound; offset++) {
|
||||
@ -303,19 +311,27 @@ export function createVirtualWeekManager({
|
||||
// Rebuild events list for this day
|
||||
const storedEvents = []
|
||||
for (const ev of calendarStore.events.values()) {
|
||||
if (!ev.recur && dateStr >= ev.startDate && dateStr <= ev.endDate) {
|
||||
storedEvents.push(ev)
|
||||
if (!ev.recur) {
|
||||
const evEnd = toLocalString(
|
||||
addDays(fromLocalString(ev.startDate, DEFAULT_TZ), (ev.days || 1) - 1),
|
||||
DEFAULT_TZ,
|
||||
)
|
||||
if (dateStr >= ev.startDate && dateStr <= evEnd) {
|
||||
storedEvents.push({ ...ev, endDate: evEnd })
|
||||
}
|
||||
}
|
||||
}
|
||||
const dayEvents = [...storedEvents]
|
||||
for (const base of repeatingBases) {
|
||||
if (dateStr >= base.startDate && dateStr <= base.endDate) {
|
||||
dayEvents.push({ ...base, _recurrenceIndex: 0, _baseId: base.id })
|
||||
const baseEndStr = toLocalString(
|
||||
addDays(fromLocalString(base.startDate, DEFAULT_TZ), (base.days || 1) - 1),
|
||||
DEFAULT_TZ,
|
||||
)
|
||||
if (dateStr >= base.startDate && dateStr <= baseEndStr) {
|
||||
dayEvents.push({ ...base, endDate: baseEndStr, _recurrenceIndex: 0, _baseId: base.id })
|
||||
continue
|
||||
}
|
||||
const baseStart = fromLocalString(base.startDate, DEFAULT_TZ)
|
||||
const baseEnd = fromLocalString(base.endDate, DEFAULT_TZ)
|
||||
const spanDays = Math.max(0, differenceInCalendarDays(baseEnd, baseStart))
|
||||
const spanDays = (base.days || 1) - 1
|
||||
const currentDate = fromLocalString(dateStr, DEFAULT_TZ)
|
||||
let occurrenceFound = false
|
||||
for (let offset = 0; offset <= spanDays && !occurrenceFound; offset++) {
|
||||
|
@ -127,14 +127,18 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
},
|
||||
|
||||
createEvent(eventData) {
|
||||
const singleDay = eventData.startDate === eventData.endDate
|
||||
let days = 1
|
||||
if (typeof eventData.days === 'number') {
|
||||
days = Math.max(1, Math.floor(eventData.days))
|
||||
}
|
||||
const singleDay = days === 1
|
||||
const event = {
|
||||
id: this.generateId(),
|
||||
title: eventData.title,
|
||||
startDate: eventData.startDate,
|
||||
endDate: eventData.endDate,
|
||||
days,
|
||||
colorId:
|
||||
eventData.colorId ?? this.selectEventColorId(eventData.startDate, eventData.endDate),
|
||||
eventData.colorId ?? this.selectEventColorId(eventData.startDate, eventData.startDate),
|
||||
startTime: singleDay ? eventData.startTime || '09:00' : null,
|
||||
durationMinutes: singleDay ? eventData.durationMinutes || 60 : null,
|
||||
recur:
|
||||
@ -149,7 +153,7 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
}
|
||||
: null,
|
||||
}
|
||||
this.events.set(event.id, { ...event, isSpanning: event.startDate < event.endDate })
|
||||
this.events.set(event.id, { ...event, isSpanning: event.days > 1 })
|
||||
this.notifyEventsChanged()
|
||||
return event.id
|
||||
},
|
||||
@ -164,7 +168,7 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
const endDate = fromLocalString(endDateStr, DEFAULT_TZ)
|
||||
for (const ev of this.events.values()) {
|
||||
const evStart = fromLocalString(ev.startDate)
|
||||
const evEnd = fromLocalString(ev.endDate)
|
||||
const evEnd = addDays(evStart, (ev.days || 1) - 1)
|
||||
if (evEnd < startDate || evStart > endDate) continue
|
||||
if (ev.colorId >= 0 && ev.colorId < 8) colorCounts[ev.colorId]++
|
||||
}
|
||||
@ -202,17 +206,10 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
this.deleteEvent(baseId)
|
||||
return
|
||||
}
|
||||
const oldStart = fromLocalString(base.startDate, DEFAULT_TZ)
|
||||
const oldEnd = fromLocalString(base.endDate, DEFAULT_TZ)
|
||||
const durationDays = Math.max(0, differenceInCalendarDays(oldEnd, oldStart))
|
||||
const newEndStr = toLocalString(
|
||||
addDays(fromLocalString(nextStartStr, DEFAULT_TZ), durationDays),
|
||||
DEFAULT_TZ,
|
||||
)
|
||||
base.startDate = nextStartStr
|
||||
base.endDate = newEndStr
|
||||
// keep same days length
|
||||
if (numericCount !== Infinity) base.recur.count = String(Math.max(1, numericCount - 1))
|
||||
this.events.set(baseId, { ...base, isSpanning: base.startDate < base.endDate })
|
||||
this.events.set(baseId, { ...base, isSpanning: base.days > 1 })
|
||||
this.notifyEventsChanged()
|
||||
},
|
||||
|
||||
@ -234,14 +231,6 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
base.recur.count = occurrenceIndex
|
||||
const nextStartStr = getOccurrenceDate(snapshot, occurrenceIndex + 1, DEFAULT_TZ)
|
||||
if (!nextStartStr) return
|
||||
const durationDays = Math.max(
|
||||
0,
|
||||
differenceInCalendarDays(
|
||||
fromLocalString(snapshot.endDate),
|
||||
fromLocalString(snapshot.startDate),
|
||||
),
|
||||
)
|
||||
const newEndStr = toLocalString(addDays(fromLocalString(nextStartStr), durationDays))
|
||||
const originalNumeric =
|
||||
snapshot.recur.count === 'unlimited' ? Infinity : parseInt(snapshot.recur.count, 10)
|
||||
let remainingCount = 'unlimited'
|
||||
@ -253,7 +242,7 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
this.createEvent({
|
||||
title: snapshot.title,
|
||||
startDate: nextStartStr,
|
||||
endDate: newEndStr,
|
||||
days: snapshot.days,
|
||||
colorId: snapshot.colorId,
|
||||
recur: snapshot.recur
|
||||
? {
|
||||
@ -283,8 +272,7 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
const snapshot = this.events.get(eventId)
|
||||
if (!snapshot) return
|
||||
const prevStart = fromLocalString(snapshot.startDate, DEFAULT_TZ)
|
||||
const prevEnd = fromLocalString(snapshot.endDate, DEFAULT_TZ)
|
||||
const prevDurationDays = Math.max(0, differenceInCalendarDays(prevEnd, prevStart))
|
||||
const prevDurationDays = (snapshot.days || 1) - 1
|
||||
const newStart = fromLocalString(newStartStr, DEFAULT_TZ)
|
||||
const newEnd = fromLocalString(newEndStr, DEFAULT_TZ)
|
||||
const proposedDurationDays = Math.max(0, differenceInCalendarDays(newEnd, newStart))
|
||||
@ -292,10 +280,7 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
if (mode === 'resize-left' || mode === 'resize-right')
|
||||
finalDurationDays = proposedDurationDays
|
||||
snapshot.startDate = newStartStr
|
||||
snapshot.endDate = toLocalString(
|
||||
addDays(fromLocalString(newStartStr, DEFAULT_TZ), finalDurationDays),
|
||||
DEFAULT_TZ,
|
||||
)
|
||||
snapshot.days = finalDurationDays + 1
|
||||
if (
|
||||
rotatePattern &&
|
||||
(mode === 'move' || mode === 'resize-left') &&
|
||||
@ -310,7 +295,7 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
snapshot.recur.weekdays = this._rotateWeekdayPattern(snapshot.recur.weekdays, shift)
|
||||
}
|
||||
}
|
||||
this.events.set(eventId, { ...snapshot, isSpanning: snapshot.startDate < snapshot.endDate })
|
||||
this.events.set(eventId, { ...snapshot, isSpanning: snapshot.days > 1 })
|
||||
this.notifyEventsChanged()
|
||||
},
|
||||
|
||||
@ -398,7 +383,7 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
const newId = this.createEvent({
|
||||
title: base.title,
|
||||
startDate: newStartStr,
|
||||
endDate: newEndStr,
|
||||
days: base.days,
|
||||
colorId: base.colorId,
|
||||
recur: {
|
||||
freq: base.recur.freq,
|
||||
@ -430,7 +415,7 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
return newId
|
||||
},
|
||||
|
||||
splitRepeatSeries(baseId, occurrenceIndex, newStartStr, newEndStr) {
|
||||
splitRepeatSeries(baseId, occurrenceIndex, newStartStr, _newEndStr) {
|
||||
const base = this.events.get(baseId)
|
||||
if (!base || !base.recur) return null
|
||||
const originalCountRaw = base.recur.count
|
||||
@ -446,7 +431,7 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
return this.createEvent({
|
||||
title: base.title,
|
||||
startDate: newStartStr,
|
||||
endDate: newEndStr,
|
||||
days: base.days,
|
||||
colorId: base.colorId,
|
||||
recur: base.recur
|
||||
? {
|
||||
@ -484,11 +469,12 @@ export const useCalendarStore = defineStore('calendar', {
|
||||
})
|
||||
},
|
||||
deserialize(value) {
|
||||
return JSON.parse(value, (_k, v) => {
|
||||
const revived = JSON.parse(value, (_k, v) => {
|
||||
if (v && v.__map) return new Map(v.data)
|
||||
if (v && v.__set) return new Set(v.data)
|
||||
return v
|
||||
})
|
||||
return revived
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -23,9 +23,8 @@ const monthAbbr = [
|
||||
'nov',
|
||||
'dec',
|
||||
]
|
||||
// Calendar year bounds (used instead of config.min_year / config.max_year)
|
||||
const MIN_YEAR = 1901
|
||||
const MAX_YEAR = 2100
|
||||
const MIN_YEAR = 100 // less than 100 is interpreted as 19xx
|
||||
const MAX_YEAR = 9999
|
||||
|
||||
// Core helpers ------------------------------------------------------------
|
||||
/**
|
||||
@ -230,9 +229,7 @@ function getOccurrenceDate(event, occurrenceIndex, timeZone = DEFAULT_TZ) {
|
||||
}
|
||||
|
||||
function getVirtualOccurrenceEndDate(event, occurrenceStartDate, timeZone = DEFAULT_TZ) {
|
||||
const baseStart = fromLocalString(event.startDate, timeZone)
|
||||
const baseEnd = fromLocalString(event.endDate, timeZone)
|
||||
const spanDays = Math.max(0, dateFns.differenceInCalendarDays(baseEnd, baseStart))
|
||||
const spanDays = Math.max(0, (event.days || 1) - 1)
|
||||
const occurrenceStart = fromLocalString(occurrenceStartDate, timeZone)
|
||||
return toLocalString(dateFns.addDays(occurrenceStart, spanDays), timeZone)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user