diff --git a/frontend/src/components/week_view.rs b/frontend/src/components/week_view.rs index cd9c139..bbcedc0 100644 --- a/frontend/src/components/week_view.rs +++ b/frontend/src/components/week_view.rs @@ -1169,59 +1169,88 @@ fn events_overlap(event1: &VEvent, event2: &VEvent) -> bool { // Calculate layout columns for overlapping events fn calculate_event_layout(events: &[VEvent], date: NaiveDate) -> Vec<(usize, usize)> { - // Filter events that should appear on this date and sort by start time + + // Filter and sort events that should appear on this date let mut day_events: Vec<_> = events.iter() - .filter(|event| { + .enumerate() + .filter_map(|(idx, event)| { let (_, _, _) = calculate_event_position(event, date); - // Only include events that would be positioned (non-zero dimensions or all-day) let local_start = event.dtstart.with_timezone(&Local); let event_date = local_start.date_naive(); - event_date == date || - (event_date == date - chrono::Duration::days(1) && local_start.hour() >= 20) + if event_date == date || + (event_date == date - chrono::Duration::days(1) && local_start.hour() >= 20) { + Some((idx, event)) + } else { + None + } }) .collect(); // Sort by start time - day_events.sort_by_key(|event| event.dtstart.with_timezone(&Local).naive_local()); + day_events.sort_by_key(|(_, event)| event.dtstart.with_timezone(&Local).naive_local()); - // Calculate layout: (column_index, total_columns) - let mut layout = Vec::with_capacity(day_events.len()); - let mut columns: Vec> = Vec::new(); + // For each event, find all events it overlaps with + let mut event_columns = vec![(0, 1); events.len()]; // (column_idx, total_columns) - for event in &day_events { - // Find the first column where this event doesn't overlap with any existing event - let mut placed = false; - for (col_idx, column) in columns.iter_mut().enumerate() { - if !column.iter().any(|existing_event| events_overlap(event, existing_event)) { - column.push(event); - layout.push((col_idx, 0)); // total_columns will be set later - placed = true; - break; + for i in 0..day_events.len() { + let (orig_idx_i, event_i) = day_events[i]; + + // Find all events that overlap with this event + let mut overlapping_events = vec![i]; + for j in 0..day_events.len() { + if i != j { + let (_, event_j) = day_events[j]; + if events_overlap(event_i, event_j) { + overlapping_events.push(j); + } } } - if !placed { - // Create new column - columns.push(vec![event]); - layout.push((columns.len() - 1, 0)); // total_columns will be set later - } - } - - // Update total_columns for all events - let total_columns = columns.len(); - for (_, total_cols) in layout.iter_mut() { - *total_cols = total_columns; - } - - // Create result mapping original events to their layout - let mut result = Vec::with_capacity(events.len()); - for event in events { - if let Some(pos) = day_events.iter().position(|e| e.uid == event.uid) { - result.push(layout[pos]); + // If this event doesn't overlap with anything, it gets full width + if overlapping_events.len() == 1 { + event_columns[orig_idx_i] = (0, 1); } else { - result.push((0, 1)); // Default: single column + // This event overlaps - we need to calculate column layout + // Sort the overlapping group by start time + overlapping_events.sort_by_key(|&idx| day_events[idx].1.dtstart.with_timezone(&Local).naive_local()); + + // Assign columns using a greedy algorithm + let mut columns: Vec> = Vec::new(); + + for &event_idx in &overlapping_events { + let (orig_idx, event) = day_events[event_idx]; + + // Find the first column where this event doesn't overlap with existing events + let mut placed = false; + for (col_idx, column) in columns.iter_mut().enumerate() { + let can_place = column.iter().all(|&existing_idx| { + let (_, existing_event) = day_events[existing_idx]; + !events_overlap(event, existing_event) + }); + + if can_place { + column.push(event_idx); + event_columns[orig_idx] = (col_idx, columns.len()); + placed = true; + break; + } + } + + if !placed { + // Create new column + columns.push(vec![event_idx]); + event_columns[orig_idx] = (columns.len() - 1, columns.len()); + } + } + + // Update total_columns for all events in this overlapping group + let total_columns = columns.len(); + for &event_idx in &overlapping_events { + let (orig_idx, _) = day_events[event_idx]; + event_columns[orig_idx].1 = total_columns; + } } } - result + event_columns }