Fix week view cross-month event fetching bug

When viewing a week that spans two months, events from the second month
were not appearing in the week view. The issue was that the calendar
component only fetched events for the month of the current date, but
week view needs events from all months that appear in the visible week.

- Modified event fetching logic to detect when week view spans multiple months
- Added cross-month support by fetching events from all relevant months
- Added get_start_of_week helper function to calculate week boundaries
- Enhanced ViewMode handling to distinguish between month and week fetching strategies

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Connor Johnstone
2025-09-21 14:17:33 -04:00
parent 037b733d48
commit 7ce7d4c9d9

View File

@@ -3,7 +3,7 @@ use crate::components::{
};
use crate::models::ical::VEvent;
use crate::services::{calendar_service::{UserInfo, ExternalCalendar}, CalendarService};
use chrono::{Datelike, Duration, Local, NaiveDate};
use chrono::{Datelike, Duration, Local, NaiveDate, Weekday};
use gloo_storage::{LocalStorage, Storage};
use std::collections::HashMap;
use web_sys::MouseEvent;
@@ -111,6 +111,7 @@ pub fn Calendar(props: &CalendarProps) -> Html {
use_effect_with((*current_date, view.clone(), external_events.len(), props.user_info.clone()), move |(date, _view, _external_len, user_info)| {
let auth_token: Option<String> = LocalStorage::get("auth_token").ok();
let date = *date; // Clone the date to avoid lifetime issues
let view_mode = _view.clone(); // Clone the view mode to avoid lifetime issues
let external_events = external_events.clone(); // Clone external events to avoid lifetime issues
let user_info = user_info.clone(); // Clone user_info to avoid lifetime issues
@@ -136,17 +137,53 @@ pub fn Calendar(props: &CalendarProps) -> Html {
String::new()
};
let current_year = date.year();
let current_month = date.month();
// Determine which months to fetch based on view mode
let months_to_fetch = match view_mode {
ViewMode::Month => {
// For month view, just fetch the current month
vec![(date.year(), date.month())]
}
ViewMode::Week => {
// For week view, calculate the week bounds and fetch all months that intersect
let start_of_week = get_start_of_week(date);
let end_of_week = start_of_week + Duration::days(6);
let mut months = vec![(start_of_week.year(), start_of_week.month())];
// If the week spans into a different month, add that month too
if end_of_week.month() != start_of_week.month() || end_of_week.year() != start_of_week.year() {
months.push((end_of_week.year(), end_of_week.month()));
}
months
}
};
match calendar_service
.fetch_events_for_month_vevent(
&token,
&password,
current_year,
current_month,
)
.await
// Fetch events for all required months
let mut all_events = Vec::new();
for (year, month) in months_to_fetch {
match calendar_service
.fetch_events_for_month_vevent(
&token,
&password,
year,
month,
)
.await
{
Ok(mut month_events) => {
all_events.append(&mut month_events);
}
Err(err) => {
error.set(Some(format!("Failed to load events for {}-{}: {}", year, month, err)));
loading.set(false);
return;
}
}
}
// Process the combined events
match Ok(all_events) as Result<Vec<VEvent>, String>
{
Ok(vevents) => {
// Filter CalDAV events based on calendar visibility
@@ -602,3 +639,18 @@ pub fn Calendar(props: &CalendarProps) -> Html {
</div>
}
}
// Helper function to calculate the start of the week (Sunday) for a given date
fn get_start_of_week(date: NaiveDate) -> NaiveDate {
let weekday = date.weekday();
let days_from_sunday = match weekday {
Weekday::Sun => 0,
Weekday::Mon => 1,
Weekday::Tue => 2,
Weekday::Wed => 3,
Weekday::Thu => 4,
Weekday::Fri => 5,
Weekday::Sat => 6,
};
date - Duration::days(days_from_sunday)
}