From 53c4a9969745db3332d117629a2d35c1b1ccbf00 Mon Sep 17 00:00:00 2001 From: Connor Johnstone Date: Wed, 3 Sep 2025 16:31:25 -0400 Subject: [PATCH] Fix multi-day all-day events to display across all days they span MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All-day events spanning multiple days were only showing on their start date. For example, a "Vacation (Dec 20-25)" event would only appear on Dec 20th. Root cause: Logic only checked events stored in each day's HashMap entry, missing events that span into other days. Solution: - Modified all-day event collection to search all events across all days - Added event_spans_date() helper function to check if event spans given date - Properly handles iCalendar dtend convention (day after event ends) - Added deduplication to prevent duplicate events from multiple day buckets - Removed unused day_events variable Result: Multi-day all-day events now correctly appear on every day they span, while single-day events continue to work as before. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- frontend/src/components/week_view.rs | 31 +++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/week_view.rs b/frontend/src/components/week_view.rs index d027236..89c3d4a 100644 --- a/frontend/src/components/week_view.rs +++ b/frontend/src/components/week_view.rs @@ -316,10 +316,19 @@ pub fn week_view(props: &WeekViewProps) -> Html { week_days.iter().map(|date| { let is_today = *date == props.today; let weekday_name = get_weekday_name(date.weekday()); - let day_events = props.events.get(date).cloned().unwrap_or_default(); - // Filter for all-day events only - let all_day_events: Vec<_> = day_events.iter().filter(|event| event.all_day).collect(); + // Collect all-day events that span this date (from any day in the week) + let mut all_day_events: Vec<&VEvent> = Vec::new(); + for events_list in props.events.values() { + for event in events_list { + if event.all_day && event_spans_date(event, *date) { + all_day_events.push(event); + } + } + } + // Remove duplicates (same event might appear in multiple day buckets) + all_day_events.sort_by_key(|e| &e.uid); + all_day_events.dedup_by_key(|e| &e.uid); html! {
@@ -1308,3 +1317,19 @@ fn calculate_event_layout(events: &[VEvent], date: NaiveDate, time_increment: u3 event_columns } + +// Check if an all-day event spans the given date +fn event_spans_date(event: &VEvent, date: NaiveDate) -> bool { + let start_date = event.dtstart.with_timezone(&Local).date_naive(); + let end_date = if let Some(dtend) = event.dtend { + // For all-day events, dtend is often set to the day after the last day + // So we need to subtract a day to get the actual last day of the event + dtend.with_timezone(&Local).date_naive() - chrono::Duration::days(1) + } else { + // Single day event + start_date + }; + + // Check if the given date falls within the event's date range + date >= start_date && date <= end_date +}