KI-AGENT: Ergänze wiederholende Termine für Kalender und Plantafel
This commit is contained in:
78
frontend/utils/eventRecurrence.ts
Normal file
78
frontend/utils/eventRecurrence.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import dayjs from "dayjs"
|
||||
|
||||
export const EVENT_REPEAT_INTERVALS = [
|
||||
"Keine Wiederholung",
|
||||
"Täglich",
|
||||
"Wöchentlich",
|
||||
"2-wöchentlich",
|
||||
"Monatlich",
|
||||
"Jährlich"
|
||||
] as const
|
||||
|
||||
const DEFAULT_REPEAT_INTERVAL = "Keine Wiederholung"
|
||||
const MAX_OCCURRENCES = 500
|
||||
|
||||
const addInterval = (date: dayjs.Dayjs, repeatInterval: string) => {
|
||||
switch (repeatInterval) {
|
||||
case "Täglich":
|
||||
return date.add(1, "day")
|
||||
case "Wöchentlich":
|
||||
return date.add(1, "week")
|
||||
case "2-wöchentlich":
|
||||
return date.add(2, "week")
|
||||
case "Monatlich":
|
||||
return date.add(1, "month")
|
||||
case "Jährlich":
|
||||
return date.add(1, "year")
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export const normalizeRepeatInterval = (value?: string | null) =>
|
||||
EVENT_REPEAT_INTERVALS.includes(value as typeof EVENT_REPEAT_INTERVALS[number])
|
||||
? value as typeof EVENT_REPEAT_INTERVALS[number]
|
||||
: DEFAULT_REPEAT_INTERVAL
|
||||
|
||||
export const expandRecurringEvent = <T>(
|
||||
event: {
|
||||
startDate: string | Date
|
||||
endDate?: string | Date | null
|
||||
repeatInterval?: string | null
|
||||
},
|
||||
rangeStart: string | Date,
|
||||
rangeEnd: string | Date,
|
||||
buildOccurrence: (occurrenceStart: dayjs.Dayjs, occurrenceEnd: dayjs.Dayjs | null, occurrenceIndex: number) => T
|
||||
) => {
|
||||
const repeatInterval = normalizeRepeatInterval(event.repeatInterval)
|
||||
const baseStart = dayjs(event.startDate)
|
||||
const baseEnd = event.endDate ? dayjs(event.endDate) : null
|
||||
const visibleStart = dayjs(rangeStart)
|
||||
const visibleEnd = dayjs(rangeEnd)
|
||||
const durationMs = baseEnd ? Math.max(baseEnd.diff(baseStart), 0) : 0
|
||||
|
||||
if (repeatInterval === DEFAULT_REPEAT_INTERVAL) {
|
||||
const occurrenceEnd = baseEnd ? baseStart.add(durationMs, "millisecond") : null
|
||||
if (baseStart.isAfter(visibleEnd) || (occurrenceEnd && occurrenceEnd.isBefore(visibleStart))) return []
|
||||
return [buildOccurrence(baseStart, occurrenceEnd, 0)]
|
||||
}
|
||||
|
||||
const occurrences: T[] = []
|
||||
let occurrenceStart = baseStart
|
||||
let occurrenceIndex = 0
|
||||
|
||||
while (occurrenceIndex < MAX_OCCURRENCES && occurrenceStart.isBefore(visibleEnd.add(1, "day"))) {
|
||||
const occurrenceEnd = baseEnd ? occurrenceStart.add(durationMs, "millisecond") : null
|
||||
|
||||
if (!occurrenceStart.isAfter(visibleEnd) && !(occurrenceEnd && occurrenceEnd.isBefore(visibleStart))) {
|
||||
occurrences.push(buildOccurrence(occurrenceStart, occurrenceEnd, occurrenceIndex))
|
||||
}
|
||||
|
||||
const nextStart = addInterval(occurrenceStart, repeatInterval)
|
||||
if (!nextStart || nextStart.isSame(occurrenceStart)) break
|
||||
occurrenceStart = nextStart
|
||||
occurrenceIndex += 1
|
||||
}
|
||||
|
||||
return occurrences
|
||||
}
|
||||
Reference in New Issue
Block a user