Implement event/date search bar

This commit is contained in:
LeoVasanko committed 2025-08-27 23:15:27 +00:00
1 parent 367072a8a2
commit 825e3e2b73
5 files changed
+616 -312

No files matched your search

+62
View File
@@ -139,6 +139,68 @@ export function getDate(event, n, timeZone = DEFAULT_TZ) {
return null
}
/**
* Return nearest occurrence (past or future) relative to a reference date (date-string yyyy-MM-dd).
* Falls back to first/last when reference lies before first or after last (bounded by cap).
* Returns { n, dateStr } or null if no recurrence / invalid.
*/
export function getNearestOccurrence(event, referenceDateStr, timeZone = DEFAULT_TZ, cap = 5000) {
if (!event) return null
if (!event.recur) return { n: 0, dateStr: event.startDate }
const { recur } = event
if (!recur || !['weeks', 'months'].includes(recur.freq)) return { n: 0, dateStr: event.startDate }
const refDate = fromLocalString(referenceDateStr, timeZone)
const baseDate = fromLocalString(event.startDate, timeZone)
if (refDate <= baseDate) return { n: 0, dateStr: event.startDate }
const maxCount = recur.count === 'unlimited' ? cap : Math.min(parseInt(recur.count, 10) || 0, cap)
if (maxCount <= 0) return null
let low = 0
let high = maxCount - 1
let candidateGE = null
while (low <= high) {
const mid = (low + high) >> 1
const midStr = getDate(event, mid, timeZone)
if (!midStr) {
// invalid mid (should rarely happen) shrink high
high = mid - 1
continue
}
const midDate = fromLocalString(midStr, timeZone)
if (midDate >= refDate) {
candidateGE = { n: mid, dateStr: midStr, date: midDate }
high = mid - 1
} else {
low = mid + 1
}
}
let candidateLT = null
if (candidateGE) {
const prevN = candidateGE.n - 1
if (prevN >= 0) {
const prevStr = getDate(event, prevN, timeZone)
if (prevStr) {
candidateLT = { n: prevN, dateStr: prevStr, date: fromLocalString(prevStr, timeZone) }
}
}
} else {
// All occurrences earlier than ref
const lastN = maxCount - 1
const lastStr = getDate(event, lastN, timeZone)
if (lastStr)
candidateLT = { n: lastN, dateStr: lastStr, date: fromLocalString(lastStr, timeZone) }
}
if (candidateGE && candidateLT) {
const diffGE = candidateGE.date - refDate
const diffLT = refDate - candidateLT.date
return diffLT <= diffGE
? { n: candidateLT.n, dateStr: candidateLT.dateStr }
: { n: candidateGE.n, dateStr: candidateGE.dateStr }
}
if (candidateGE) return { n: candidateGE.n, dateStr: candidateGE.dateStr }
if (candidateLT) return { n: candidateLT.n, dateStr: candidateLT.dateStr }
return null
}
export function buildDayEvents(events, dateStr, timeZone = DEFAULT_TZ) {
const date = fromLocalString(dateStr, timeZone)
const out = []