diff --git a/frontend/src/app.rs b/frontend/src/app.rs index b7afe13..82f3cd5 100644 --- a/frontend/src/app.rs +++ b/frontend/src/app.rs @@ -412,6 +412,132 @@ pub fn App() -> Html { let create_event_modal_open = create_event_modal_open.clone(); let auth_token = auth_token.clone(); Callback::from(move |event_data: EventCreationData| { + // Check if this is an update operation (has original_uid) or a create operation + if let Some(original_uid) = event_data.original_uid.clone() { + web_sys::console::log_1(&format!("Updating event via modal: {:?}", event_data).into()); + + create_event_modal_open.set(false); + + // Handle the update operation using the existing backend update logic + if let Some(token) = (*auth_token).clone() { + let event_data_for_update = event_data.clone(); + wasm_bindgen_futures::spawn_local(async move { + let calendar_service = CalendarService::new(); + + // Get CalDAV password from storage + let password = if let Ok(credentials_str) = + LocalStorage::get::("caldav_credentials") + { + if let Ok(credentials) = + serde_json::from_str::(&credentials_str) + { + credentials["password"].as_str().unwrap_or("").to_string() + } else { + String::new() + } + } else { + String::new() + }; + + // Convert EventCreationData to update parameters + let params = event_data_for_update.to_create_event_params(); + + // Determine if this is a recurring event update + let is_recurring = matches!(event_data_for_update.recurrence, crate::components::event_form::RecurrenceType::Daily | + crate::components::event_form::RecurrenceType::Weekly | + crate::components::event_form::RecurrenceType::Monthly | + crate::components::event_form::RecurrenceType::Yearly); + + let update_result = if is_recurring && event_data_for_update.edit_scope.is_some() { + // Use series update endpoint for recurring events + let edit_action = event_data_for_update.edit_scope.unwrap(); + let scope = match edit_action { + crate::components::EditAction::EditAll => "all_in_series".to_string(), + crate::components::EditAction::EditFuture => "this_and_future".to_string(), + crate::components::EditAction::EditThis => "this_only".to_string(), + }; + + calendar_service + .update_series( + &token, + &password, + original_uid.clone(), + params.0, // title + params.1, // description + params.2, // start_date + params.3, // start_time + params.4, // end_date + params.5, // end_time + params.6, // location + params.7, // all_day + params.8, // status + params.9, // class + params.10, // priority + params.11, // organizer + params.12, // attendees + params.13, // categories + params.14, // reminder + params.15, // recurrence + params.17, // calendar_path (skipping recurrence_days) + scope, + event_data_for_update.occurrence_date.map(|d| d.format("%Y-%m-%d").to_string()), // occurrence_date + ) + .await + } else { + // Use regular update endpoint for single events + calendar_service + .update_event( + &token, + &password, + original_uid.clone(), + params.0, // title + params.1, // description + params.2, // start_date + params.3, // start_time + params.4, // end_date + params.5, // end_time + params.6, // location + params.7, // all_day + params.8, // status + params.9, // class + params.10, // priority + params.11, // organizer + params.12, // attendees + params.13, // categories + params.14, // reminder + params.15, // recurrence + params.16, // recurrence_days + params.17, // calendar_path + vec![], // exception_dates - empty for simple updates + None, // update_action - None for regular updates + None, // until_date - None for regular updates + ) + .await + }; + + match update_result { + Ok(_) => { + web_sys::console::log_1(&"Event updated successfully via modal".into()); + // Trigger a page reload to refresh events from all calendars + if let Some(window) = web_sys::window() { + let _ = window.location().reload(); + } + } + Err(err) => { + web_sys::console::error_1( + &format!("Failed to update event: {}", err).into(), + ); + web_sys::window() + .unwrap() + .alert_with_message(&format!("Failed to update event: {}", err)) + .unwrap(); + } + } + }); + } + return; + } + web_sys::console::log_1(&format!("Creating event: {:?}", event_data).into()); // Save the selected calendar as the last used calendar diff --git a/frontend/src/components/create_event_modal.rs b/frontend/src/components/create_event_modal.rs index 7ca42b5..aa28bbd 100644 --- a/frontend/src/components/create_event_modal.rs +++ b/frontend/src/components/create_event_modal.rs @@ -113,8 +113,17 @@ pub fn create_event_modal(props: &CreateEventModalProps) -> Html { let on_save = { let event_data = event_data.clone(); let on_create = props.on_create.clone(); + let event_to_edit = props.event_to_edit.clone(); Callback::from(move |_: MouseEvent| { - on_create.emit((*event_data).clone()); + let mut data = (*event_data).clone(); + + // If we're editing an existing event, mark it as an update operation + if let Some(ref original_event) = event_to_edit { + // Set the original UID so the backend knows to update instead of create + data.original_uid = Some(original_event.uid.clone()); + } + + on_create.emit(data); }) }; @@ -315,5 +324,7 @@ fn vevent_to_creation_data(event: &crate::models::ical::VEvent, available_calend // Edit tracking edit_scope: None, // Will be set by the modal after creation changed_fields: vec![], + original_uid: Some(event.uid.clone()), // Preserve original UID for editing + occurrence_date: Some(start_local.date()), // The occurrence date being edited } } \ No newline at end of file diff --git a/frontend/src/components/event_form/types.rs b/frontend/src/components/event_form/types.rs index 06def68..a058bcf 100644 --- a/frontend/src/components/event_form/types.rs +++ b/frontend/src/components/event_form/types.rs @@ -125,6 +125,8 @@ pub struct EventCreationData { // Edit tracking (for recurring events) pub edit_scope: Option, pub changed_fields: Vec, + pub original_uid: Option, // Set when editing existing events + pub occurrence_date: Option, // The specific occurrence date being edited } impl EventCreationData { @@ -205,6 +207,8 @@ impl Default for EventCreationData { selected_calendar: None, edit_scope: None, changed_fields: vec![], + original_uid: None, + occurrence_date: None, } } }