Compare commits
	
		
			3 Commits
		
	
	
		
			d36609d8c2
			...
			53ea5e3fc1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 53ea5e3fc1 | ||
|   | d35fc11267 | ||
|   | 697eb64dd4 | 
| @@ -32,6 +32,8 @@ pub struct WeekViewProps { | |||||||
| enum DragType { | enum DragType { | ||||||
|     CreateEvent, |     CreateEvent, | ||||||
|     MoveEvent(CalendarEvent), |     MoveEvent(CalendarEvent), | ||||||
|  |     ResizeEventStart(CalendarEvent), // Resizing from the top edge (start time) | ||||||
|  |     ResizeEventEnd(CalendarEvent),   // Resizing from the bottom edge (end time) | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Clone, PartialEq)] | #[derive(Clone, PartialEq)] | ||||||
| @@ -42,6 +44,7 @@ struct DragState { | |||||||
|     start_y: f64, |     start_y: f64, | ||||||
|     current_y: f64, |     current_y: f64, | ||||||
|     offset_y: f64, // For event moves, this is the offset from the event's top |     offset_y: f64, // For event moves, this is the offset from the event's top | ||||||
|  |     has_moved: bool, // Track if we've moved enough to constitute a real drag | ||||||
| } | } | ||||||
|  |  | ||||||
| #[function_component(WeekView)] | #[function_component(WeekView)] | ||||||
| @@ -161,6 +164,7 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                             start_y: snapped_y, |                                             start_y: snapped_y, | ||||||
|                                             current_y: snapped_y, |                                             current_y: snapped_y, | ||||||
|                                             offset_y: 0.0, |                                             offset_y: 0.0, | ||||||
|  |                                             has_moved: false, | ||||||
|                                         })); |                                         })); | ||||||
|                                         e.prevent_default(); |                                         e.prevent_default(); | ||||||
|                                     }) |                                     }) | ||||||
| @@ -173,11 +177,21 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                         if let Some(mut current_drag) = (*drag_state).clone() { |                                         if let Some(mut current_drag) = (*drag_state).clone() { | ||||||
|                                             if current_drag.is_dragging { |                                             if current_drag.is_dragging { | ||||||
|                                                 // Use layer_y for consistent coordinate calculation |                                                 // Use layer_y for consistent coordinate calculation | ||||||
|                                                 let relative_y = e.layer_y() as f64; |                                                 let mouse_y = e.layer_y() as f64; | ||||||
|                                                 let relative_y = if relative_y > 0.0 { relative_y } else { e.offset_y() as f64 }; |                                                 let mouse_y = if mouse_y > 0.0 { mouse_y } else { e.offset_y() as f64 }; | ||||||
|  |                                                  | ||||||
|  |                                                 // For move operations, we now follow the mouse directly since we start at click position | ||||||
|  |                                                 // For resize operations, we still use the mouse position directly | ||||||
|  |                                                 let adjusted_y = mouse_y; | ||||||
|                                                  |                                                  | ||||||
|                                                 // Snap to increment |                                                 // Snap to increment | ||||||
|                                                 let snapped_y = snap_to_increment(relative_y, time_increment); |                                                 let snapped_y = snap_to_increment(adjusted_y, time_increment); | ||||||
|  |                                                  | ||||||
|  |                                                 // Check if we've moved enough to constitute a real drag (5 pixels minimum) | ||||||
|  |                                                 let movement_distance = (snapped_y - current_drag.start_y).abs(); | ||||||
|  |                                                 if movement_distance > 5.0 { | ||||||
|  |                                                     current_drag.has_moved = true; | ||||||
|  |                                                 } | ||||||
|                                                  |                                                  | ||||||
|                                                 current_drag.current_y = snapped_y; |                                                 current_drag.current_y = snapped_y; | ||||||
|                                                 drag_state.set(Some(current_drag)); |                                                 drag_state.set(Some(current_drag)); | ||||||
| @@ -190,9 +204,10 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                     let drag_state = drag_state_clone.clone(); |                                     let drag_state = drag_state_clone.clone(); | ||||||
|                                     let on_create_event = props.on_create_event.clone(); |                                     let on_create_event = props.on_create_event.clone(); | ||||||
|                                     let on_event_update = props.on_event_update.clone(); |                                     let on_event_update = props.on_event_update.clone(); | ||||||
|  |                                     let time_increment = props.time_increment; | ||||||
|                                     Callback::from(move |_e: MouseEvent| { |                                     Callback::from(move |_e: MouseEvent| { | ||||||
|                                         if let Some(current_drag) = (*drag_state).clone() { |                                         if let Some(current_drag) = (*drag_state).clone() { | ||||||
|                                             if current_drag.is_dragging { |                                             if current_drag.is_dragging && current_drag.has_moved { | ||||||
|                                                 match ¤t_drag.drag_type { |                                                 match ¤t_drag.drag_type { | ||||||
|                                                     DragType::CreateEvent => { |                                                     DragType::CreateEvent => { | ||||||
|                                                         // Calculate start and end times |                                                         // Calculate start and end times | ||||||
| @@ -221,8 +236,11 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                                         } |                                                         } | ||||||
|                                                     }, |                                                     }, | ||||||
|                                                     DragType::MoveEvent(event) => { |                                                     DragType::MoveEvent(event) => { | ||||||
|                                                         // Calculate new start time based on drag position |                                                         // Calculate new start time based on drag position (accounting for click offset) | ||||||
|                                                         let new_start_time = pixels_to_time(current_drag.current_y); |                                                         let unsnapped_position = current_drag.current_y - current_drag.offset_y; | ||||||
|  |                                                         // Snap the final position to maintain time increment alignment | ||||||
|  |                                                         let event_top_position = snap_to_increment(unsnapped_position, time_increment); | ||||||
|  |                                                         let new_start_time = pixels_to_time(event_top_position); | ||||||
|                                                          |                                                          | ||||||
|                                                         // Calculate duration from original event |                                                         // Calculate duration from original event | ||||||
|                                                         let original_duration = if let Some(end) = event.end { |                                                         let original_duration = if let Some(end) = event.end { | ||||||
| @@ -234,6 +252,51 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                                         let new_start_datetime = NaiveDateTime::new(current_drag.start_date, new_start_time); |                                                         let new_start_datetime = NaiveDateTime::new(current_drag.start_date, new_start_time); | ||||||
|                                                         let new_end_datetime = new_start_datetime + original_duration; |                                                         let new_end_datetime = new_start_datetime + original_duration; | ||||||
|                                                          |                                                          | ||||||
|  |                                                         if let Some(callback) = &on_event_update { | ||||||
|  |                                                             callback.emit((event.clone(), new_start_datetime, new_end_datetime)); | ||||||
|  |                                                         } | ||||||
|  |                                                     }, | ||||||
|  |                                                     DragType::ResizeEventStart(event) => { | ||||||
|  |                                                         // Calculate new start time based on drag position | ||||||
|  |                                                         let new_start_time = pixels_to_time(current_drag.current_y); | ||||||
|  |                                                          | ||||||
|  |                                                         // Keep the original end time | ||||||
|  |                                                         let original_end = if let Some(end) = event.end { | ||||||
|  |                                                             end.with_timezone(&chrono::Local).naive_local() | ||||||
|  |                                                         } else { | ||||||
|  |                                                             // If no end time, use start time + 1 hour as default | ||||||
|  |                                                             event.start.with_timezone(&chrono::Local).naive_local() + chrono::Duration::hours(1) | ||||||
|  |                                                         }; | ||||||
|  |                                                          | ||||||
|  |                                                         let new_start_datetime = NaiveDateTime::new(current_drag.start_date, new_start_time); | ||||||
|  |                                                          | ||||||
|  |                                                         // Ensure start is before end (minimum 15 minutes) | ||||||
|  |                                                         let new_end_datetime = if new_start_datetime >= original_end { | ||||||
|  |                                                             new_start_datetime + chrono::Duration::minutes(15) | ||||||
|  |                                                         } else { | ||||||
|  |                                                             original_end | ||||||
|  |                                                         }; | ||||||
|  |                                                          | ||||||
|  |                                                         if let Some(callback) = &on_event_update { | ||||||
|  |                                                             callback.emit((event.clone(), new_start_datetime, new_end_datetime)); | ||||||
|  |                                                         } | ||||||
|  |                                                     }, | ||||||
|  |                                                     DragType::ResizeEventEnd(event) => { | ||||||
|  |                                                         // Calculate new end time based on drag position | ||||||
|  |                                                         let new_end_time = pixels_to_time(current_drag.current_y); | ||||||
|  |                                                          | ||||||
|  |                                                         // Keep the original start time | ||||||
|  |                                                         let original_start = event.start.with_timezone(&chrono::Local).naive_local(); | ||||||
|  |                                                          | ||||||
|  |                                                         let new_end_datetime = NaiveDateTime::new(current_drag.start_date, new_end_time); | ||||||
|  |                                                          | ||||||
|  |                                                         // Ensure end is after start (minimum 15 minutes) | ||||||
|  |                                                         let new_start_datetime = if new_end_datetime <= original_start { | ||||||
|  |                                                             new_end_datetime - chrono::Duration::minutes(15) | ||||||
|  |                                                         } else { | ||||||
|  |                                                             original_start | ||||||
|  |                                                         }; | ||||||
|  |                                                          | ||||||
|                                                         if let Some(callback) = &on_event_update { |                                                         if let Some(callback) = &on_event_update { | ||||||
|                                                             callback.emit((event.clone(), new_start_datetime, new_end_datetime)); |                                                             callback.emit((event.clone(), new_start_datetime, new_end_datetime)); | ||||||
|                                                         } |                                                         } | ||||||
| @@ -297,36 +360,39 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                                         let drag_state = drag_state.clone(); |                                                         let drag_state = drag_state.clone(); | ||||||
|                                                         let event_for_drag = event.clone(); |                                                         let event_for_drag = event.clone(); | ||||||
|                                                         let date_for_drag = *date; |                                                         let date_for_drag = *date; | ||||||
|                                                         let time_increment = props.time_increment; |                                                         let _time_increment = props.time_increment; | ||||||
|                                                         Callback::from(move |e: MouseEvent| { |                                                         Callback::from(move |e: MouseEvent| { | ||||||
|                                                             e.stop_propagation(); // Prevent drag-to-create from starting on event clicks |                                                             e.stop_propagation(); // Prevent drag-to-create from starting on event clicks | ||||||
|                                                              |                                                              | ||||||
|                                                             // Only handle left-click (button 0) |                                                             // Only handle left-click (button 0) for moving | ||||||
|                                                             if e.button() != 0 { |                                                             if e.button() != 0 { | ||||||
|                                                                 return; |                                                                 return; | ||||||
|                                                             } |                                                             } | ||||||
|                                                              |                                                              | ||||||
|                                                             // Calculate Y position relative to the day column |                                                             // Calculate click position relative to event element | ||||||
|                                                             let relative_y = e.layer_y() as f64; |                                                             let click_y_relative = e.layer_y() as f64; | ||||||
|                                                             let relative_y = if relative_y > 0.0 { relative_y } else { e.offset_y() as f64 }; |                                                             let click_y_relative = if click_y_relative > 0.0 { click_y_relative } else { e.offset_y() as f64 }; | ||||||
|                                                              |                                                              | ||||||
|                                                             // Get event's current position |                                                             // Get event's current position in day column coordinates | ||||||
|                                                             let (event_start_pixels, _, _) = calculate_event_position(&event_for_drag, date_for_drag); |                                                             let (event_start_pixels, _, _) = calculate_event_position(&event_for_drag, date_for_drag); | ||||||
|                                                             let event_start_pixels = event_start_pixels as f64; |                                                             let event_start_pixels = event_start_pixels as f64; | ||||||
|                                                              |                                                              | ||||||
|                                                             // Calculate offset from the top of the event |                                                             // Convert click position to day column coordinates | ||||||
|                                                             let offset_y = relative_y - event_start_pixels; |                                                             let click_y = event_start_pixels + click_y_relative; | ||||||
|                                                              |                                                              | ||||||
|                                                             // Snap to increment |                                                             // Store the offset from the event's top where the user clicked | ||||||
|                                                             let snapped_y = snap_to_increment(relative_y, time_increment); |                                                             // This will be used to maintain the relative click position | ||||||
|  |                                                             let offset_y = click_y_relative; | ||||||
|                                                              |                                                              | ||||||
|  |                                                             // Start drag tracking from where we clicked (in day column coordinates) | ||||||
|                                                             drag_state.set(Some(DragState { |                                                             drag_state.set(Some(DragState { | ||||||
|                                                                 is_dragging: true, |                                                                 is_dragging: true, | ||||||
|                                                                 drag_type: DragType::MoveEvent(event_for_drag.clone()), |                                                                 drag_type: DragType::MoveEvent(event_for_drag.clone()), | ||||||
|                                                                 start_date: date_for_drag, |                                                                 start_date: date_for_drag, | ||||||
|                                                                 start_y: snapped_y, |                                                                 start_y: click_y, | ||||||
|                                                                 current_y: snapped_y, |                                                                 current_y: click_y, | ||||||
|                                                                 offset_y, |                                                                 offset_y, | ||||||
|  |                                                                 has_moved: false, | ||||||
|                                                             })); |                                                             })); | ||||||
|                                                             e.prevent_default(); |                                                             e.prevent_default(); | ||||||
|                                                         }) |                                                         }) | ||||||
| @@ -336,7 +402,16 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                                         if let Some(callback) = &props.on_event_context_menu { |                                                         if let Some(callback) = &props.on_event_context_menu { | ||||||
|                                                             let callback = callback.clone(); |                                                             let callback = callback.clone(); | ||||||
|                                                             let event = event.clone(); |                                                             let event = event.clone(); | ||||||
|  |                                                             let drag_state_for_context = drag_state.clone(); | ||||||
|                                                             Some(Callback::from(move |e: web_sys::MouseEvent| { |                                                             Some(Callback::from(move |e: web_sys::MouseEvent| { | ||||||
|  |                                                                 // Check if we're currently dragging - if so, prevent context menu | ||||||
|  |                                                                 if let Some(drag) = (*drag_state_for_context).clone() { | ||||||
|  |                                                                     if drag.is_dragging { | ||||||
|  |                                                                         e.prevent_default(); | ||||||
|  |                                                                         return; | ||||||
|  |                                                                     } | ||||||
|  |                                                                 } | ||||||
|  |                                                                  | ||||||
|                                                                 e.prevent_default(); |                                                                 e.prevent_default(); | ||||||
|                                                                 e.stop_propagation(); // Prevent calendar context menu from also triggering |                                                                 e.stop_propagation(); // Prevent calendar context menu from also triggering | ||||||
|                                                                 callback.emit((e, event.clone())); |                                                                 callback.emit((e, event.clone())); | ||||||
| @@ -377,12 +452,16 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                                         } |                                                         } | ||||||
|                                                     }; |                                                     }; | ||||||
|                                                      |                                                      | ||||||
|                                                     // Check if this event is currently being dragged |                                                     // Check if this event is currently being dragged or resized | ||||||
|                                                     let is_being_dragged = if let Some(drag) = (*drag_state).clone() { |                                                     let is_being_dragged = if let Some(drag) = (*drag_state).clone() { | ||||||
|                                                         if let DragType::MoveEvent(dragged_event) = &drag.drag_type { |                                                         match &drag.drag_type { | ||||||
|                                                             dragged_event.uid == event.uid && drag.is_dragging |                                                             DragType::MoveEvent(dragged_event) =>  | ||||||
|                                                         } else { |                                                                 dragged_event.uid == event.uid && drag.is_dragging, | ||||||
|                                                             false |                                                             DragType::ResizeEventStart(dragged_event) =>  | ||||||
|  |                                                                 dragged_event.uid == event.uid && drag.is_dragging, | ||||||
|  |                                                             DragType::ResizeEventEnd(dragged_event) =>  | ||||||
|  |                                                                 dragged_event.uid == event.uid && drag.is_dragging, | ||||||
|  |                                                             _ => false, | ||||||
|                                                         } |                                                         } | ||||||
|                                                     } else { |                                                     } else { | ||||||
|                                                         false |                                                         false | ||||||
| @@ -392,6 +471,57 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                                         // Hide the original event while being dragged |                                                         // Hide the original event while being dragged | ||||||
|                                                         Some(html! {}) |                                                         Some(html! {}) | ||||||
|                                                     } else { |                                                     } else { | ||||||
|  |                                                         // Create resize handles for left-click resize | ||||||
|  |                                                         let resize_start_handler = { | ||||||
|  |                                                             let drag_state = drag_state.clone(); | ||||||
|  |                                                             let event_for_resize = event.clone(); | ||||||
|  |                                                             let date_for_drag = *date; | ||||||
|  |                                                             let time_increment = props.time_increment; | ||||||
|  |                                                             Callback::from(move |e: web_sys::MouseEvent| { | ||||||
|  |                                                                 e.stop_propagation(); | ||||||
|  |                                                                  | ||||||
|  |                                                                 let relative_y = e.layer_y() as f64; | ||||||
|  |                                                                 let relative_y = if relative_y > 0.0 { relative_y } else { e.offset_y() as f64 }; | ||||||
|  |                                                                 let snapped_y = snap_to_increment(relative_y, time_increment); | ||||||
|  |                                                                  | ||||||
|  |                                                                 drag_state.set(Some(DragState { | ||||||
|  |                                                                     is_dragging: true, | ||||||
|  |                                                                     drag_type: DragType::ResizeEventStart(event_for_resize.clone()), | ||||||
|  |                                                                     start_date: date_for_drag, | ||||||
|  |                                                                     start_y: snapped_y, | ||||||
|  |                                                                     current_y: snapped_y, | ||||||
|  |                                                                     offset_y: 0.0, | ||||||
|  |                                                                     has_moved: false, | ||||||
|  |                                                                 })); | ||||||
|  |                                                                 e.prevent_default(); | ||||||
|  |                                                             }) | ||||||
|  |                                                         }; | ||||||
|  |                                                          | ||||||
|  |                                                         let resize_end_handler = { | ||||||
|  |                                                             let drag_state = drag_state.clone(); | ||||||
|  |                                                             let event_for_resize = event.clone(); | ||||||
|  |                                                             let date_for_drag = *date; | ||||||
|  |                                                             let time_increment = props.time_increment; | ||||||
|  |                                                             Callback::from(move |e: web_sys::MouseEvent| { | ||||||
|  |                                                                 e.stop_propagation(); | ||||||
|  |                                                                  | ||||||
|  |                                                                 let relative_y = e.layer_y() as f64; | ||||||
|  |                                                                 let relative_y = if relative_y > 0.0 { relative_y } else { e.offset_y() as f64 }; | ||||||
|  |                                                                 let snapped_y = snap_to_increment(relative_y, time_increment); | ||||||
|  |                                                                  | ||||||
|  |                                                                 drag_state.set(Some(DragState { | ||||||
|  |                                                                     is_dragging: true, | ||||||
|  |                                                                     drag_type: DragType::ResizeEventEnd(event_for_resize.clone()), | ||||||
|  |                                                                     start_date: date_for_drag, | ||||||
|  |                                                                     start_y: snapped_y, | ||||||
|  |                                                                     current_y: snapped_y, | ||||||
|  |                                                                     offset_y: 0.0, | ||||||
|  |                                                                     has_moved: false, | ||||||
|  |                                                                 })); | ||||||
|  |                                                                 e.prevent_default(); | ||||||
|  |                                                             }) | ||||||
|  |                                                         }; | ||||||
|  |                                                          | ||||||
|                                                         Some(html! { |                                                         Some(html! { | ||||||
|                                                             <div  |                                                             <div  | ||||||
|                                                                 class={classes!( |                                                                 class={classes!( | ||||||
| @@ -409,9 +539,36 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                                                 {oncontextmenu} |                                                                 {oncontextmenu} | ||||||
|                                                                 onmousedown={onmousedown_event} |                                                                 onmousedown={onmousedown_event} | ||||||
|                                                             > |                                                             > | ||||||
|                                                                 <div class="event-title">{event.summary.as_ref().unwrap_or(&"Untitled".to_string())}</div> |                                                                 // Top resize handle | ||||||
|                                                                 {if !is_all_day { |                                                                 {if !is_all_day { | ||||||
|                                                                     html! { <div class="event-time">{time_display}</div> } |                                                                     html! { | ||||||
|  |                                                                         <div  | ||||||
|  |                                                                             class="resize-handle resize-handle-top" | ||||||
|  |                                                                             onmousedown={resize_start_handler} | ||||||
|  |                                                                         /> | ||||||
|  |                                                                     } | ||||||
|  |                                                                 } else { | ||||||
|  |                                                                     html! {} | ||||||
|  |                                                                 }} | ||||||
|  |                                                                  | ||||||
|  |                                                                 // Event content | ||||||
|  |                                                                 <div class="event-content"> | ||||||
|  |                                                                     <div class="event-title">{event.summary.as_ref().unwrap_or(&"Untitled".to_string())}</div> | ||||||
|  |                                                                     {if !is_all_day { | ||||||
|  |                                                                         html! { <div class="event-time">{time_display}</div> } | ||||||
|  |                                                                     } else { | ||||||
|  |                                                                         html! {} | ||||||
|  |                                                                     }} | ||||||
|  |                                                                 </div> | ||||||
|  |                                                                  | ||||||
|  |                                                                 // Bottom resize handle | ||||||
|  |                                                                 {if !is_all_day { | ||||||
|  |                                                                     html! { | ||||||
|  |                                                                         <div  | ||||||
|  |                                                                             class="resize-handle resize-handle-bottom" | ||||||
|  |                                                                             onmousedown={resize_end_handler} | ||||||
|  |                                                                         /> | ||||||
|  |                                                                     } | ||||||
|                                                                 } else { |                                                                 } else { | ||||||
|                                                                     html! {} |                                                                     html! {} | ||||||
|                                                                 }} |                                                                 }} | ||||||
| @@ -446,8 +603,11 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                                             } |                                                             } | ||||||
|                                                         }, |                                                         }, | ||||||
|                                                         DragType::MoveEvent(event) => { |                                                         DragType::MoveEvent(event) => { | ||||||
|                                                             // Show the event being moved at its new position |                                                             // Calculate the event's new position accounting for click offset | ||||||
|                                                             let new_start_time = pixels_to_time(drag.current_y); |                                                             let unsnapped_position = drag.current_y - drag.offset_y; | ||||||
|  |                                                             // Snap the final position to maintain time increment alignment | ||||||
|  |                                                             let preview_position = snap_to_increment(unsnapped_position, props.time_increment); | ||||||
|  |                                                             let new_start_time = pixels_to_time(preview_position); | ||||||
|                                                             let original_duration = if let Some(end) = event.end { |                                                             let original_duration = if let Some(end) = event.end { | ||||||
|                                                                 end.signed_duration_since(event.start) |                                                                 end.signed_duration_since(event.start) | ||||||
|                                                             } else { |                                                             } else { | ||||||
| @@ -461,12 +621,64 @@ pub fn week_view(props: &WeekViewProps) -> Html { | |||||||
|                                                             html! { |                                                             html! { | ||||||
|                                                                 <div |                                                                 <div | ||||||
|                                                                     class="temp-event-box moving-event" |                                                                     class="temp-event-box moving-event" | ||||||
|                                                                     style={format!("top: {}px; height: {}px; background-color: {}; opacity: 0.7;", drag.current_y, duration_pixels, event_color)} |                                                                     style={format!("top: {}px; height: {}px; background-color: {}; opacity: 0.7;", preview_position, duration_pixels, event_color)} | ||||||
|                                                                 > |                                                                 > | ||||||
|                                                                     <div class="event-title">{event.summary.as_ref().unwrap_or(&"Untitled".to_string())}</div> |                                                                     <div class="event-title">{event.summary.as_ref().unwrap_or(&"Untitled".to_string())}</div> | ||||||
|                                                                     <div class="event-time">{format!("{} - {}", new_start_time.format("%I:%M %p"), new_end_time.format("%I:%M %p"))}</div> |                                                                     <div class="event-time">{format!("{} - {}", new_start_time.format("%I:%M %p"), new_end_time.format("%I:%M %p"))}</div> | ||||||
|                                                                 </div> |                                                                 </div> | ||||||
|                                                             } |                                                             } | ||||||
|  |                                                         }, | ||||||
|  |                                                         DragType::ResizeEventStart(event) => { | ||||||
|  |                                                             // Show the event being resized from the start | ||||||
|  |                                                             let new_start_time = pixels_to_time(drag.current_y); | ||||||
|  |                                                             let original_end = if let Some(end) = event.end { | ||||||
|  |                                                                 end.with_timezone(&chrono::Local).naive_local() | ||||||
|  |                                                             } else { | ||||||
|  |                                                                 event.start.with_timezone(&chrono::Local).naive_local() + chrono::Duration::hours(1) | ||||||
|  |                                                             }; | ||||||
|  |                                                              | ||||||
|  |                                                             // Calculate positions for the preview | ||||||
|  |                                                             let (original_start_pixels, _, _) = calculate_event_position(event, drag.start_date); | ||||||
|  |                                                             let original_duration = original_end.signed_duration_since(event.start.with_timezone(&chrono::Local).naive_local()); | ||||||
|  |                                                             let original_end_pixels = original_start_pixels + (original_duration.num_minutes() as f32); | ||||||
|  |                                                              | ||||||
|  |                                                             let new_start_pixels = drag.current_y; | ||||||
|  |                                                             let new_height = (original_end_pixels as f64 - new_start_pixels).max(20.0); | ||||||
|  |                                                              | ||||||
|  |                                                             let event_color = get_event_color(event); | ||||||
|  |                                                              | ||||||
|  |                                                             html! { | ||||||
|  |                                                                 <div | ||||||
|  |                                                                     class="temp-event-box resizing-event" | ||||||
|  |                                                                     style={format!("top: {}px; height: {}px; background-color: {}; opacity: 0.7;", new_start_pixels, new_height, event_color)} | ||||||
|  |                                                                 > | ||||||
|  |                                                                     <div class="event-title">{event.summary.as_ref().unwrap_or(&"Untitled".to_string())}</div> | ||||||
|  |                                                                     <div class="event-time">{format!("{} - {}", new_start_time.format("%I:%M %p"), original_end.time().format("%I:%M %p"))}</div> | ||||||
|  |                                                                 </div> | ||||||
|  |                                                             } | ||||||
|  |                                                         }, | ||||||
|  |                                                         DragType::ResizeEventEnd(event) => { | ||||||
|  |                                                             // Show the event being resized from the end | ||||||
|  |                                                             let new_end_time = pixels_to_time(drag.current_y); | ||||||
|  |                                                             let original_start = event.start.with_timezone(&chrono::Local).naive_local(); | ||||||
|  |                                                              | ||||||
|  |                                                             // Calculate positions for the preview | ||||||
|  |                                                             let (original_start_pixels, _, _) = calculate_event_position(event, drag.start_date); | ||||||
|  |                                                              | ||||||
|  |                                                             let new_end_pixels = drag.current_y; | ||||||
|  |                                                             let new_height = (new_end_pixels - original_start_pixels as f64).max(20.0); | ||||||
|  |                                                              | ||||||
|  |                                                             let event_color = get_event_color(event); | ||||||
|  |                                                              | ||||||
|  |                                                             html! { | ||||||
|  |                                                                 <div | ||||||
|  |                                                                     class="temp-event-box resizing-event" | ||||||
|  |                                                                     style={format!("top: {}px; height: {}px; background-color: {}; opacity: 0.7;", original_start_pixels, new_height, event_color)} | ||||||
|  |                                                                 > | ||||||
|  |                                                                     <div class="event-title">{event.summary.as_ref().unwrap_or(&"Untitled".to_string())}</div> | ||||||
|  |                                                                     <div class="event-time">{format!("{} - {}", original_start.time().format("%I:%M %p"), new_end_time.format("%I:%M %p"))}</div> | ||||||
|  |                                                                 </div> | ||||||
|  |                                                             } | ||||||
|                                                         } |                                                         } | ||||||
|                                                     } |                                                     } | ||||||
|                                                 } else { |                                                 } else { | ||||||
|   | |||||||
							
								
								
									
										87
									
								
								styles.css
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								styles.css
									
									
									
									
									
								
							| @@ -727,6 +727,93 @@ body { | |||||||
|     width: 100%; |     width: 100%; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Resizing event during drag */ | ||||||
|  | .temp-event-box.resizing-event { | ||||||
|  |     background: inherit; | ||||||
|  |     border: 2px solid rgba(255, 255, 255, 0.9); | ||||||
|  |     color: white; | ||||||
|  |     flex-direction: column; | ||||||
|  |     align-items: flex-start; | ||||||
|  |     justify-content: flex-start; | ||||||
|  |     text-align: left; | ||||||
|  |     box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); | ||||||
|  |     transform: scale(1.01); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .temp-event-box.resizing-event .event-title { | ||||||
|  |     font-weight: 600; | ||||||
|  |     margin-bottom: 2px; | ||||||
|  |     overflow: hidden; | ||||||
|  |     text-overflow: ellipsis; | ||||||
|  |     white-space: nowrap; | ||||||
|  |     width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .temp-event-box.resizing-event .event-time { | ||||||
|  |     font-size: 0.65rem; | ||||||
|  |     opacity: 0.9; | ||||||
|  |     overflow: hidden; | ||||||
|  |     text-overflow: ellipsis; | ||||||
|  |     white-space: nowrap; | ||||||
|  |     width: 100%; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Event resize zones and handles */ | ||||||
|  | .week-event { | ||||||
|  |     position: relative; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .week-event .event-content { | ||||||
|  |     padding: 2px; | ||||||
|  |     height: 100%; | ||||||
|  |     display: flex; | ||||||
|  |     flex-direction: column; | ||||||
|  |     justify-content: center; | ||||||
|  |     pointer-events: auto; | ||||||
|  |     z-index: 5; | ||||||
|  |     position: relative; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Left-click drag handles */ | ||||||
|  | .resize-handle { | ||||||
|  |     position: absolute; | ||||||
|  |     left: 0; | ||||||
|  |     right: 0; | ||||||
|  |     height: 4px; | ||||||
|  |     background: transparent; | ||||||
|  |     cursor: ns-resize; | ||||||
|  |     z-index: 10; | ||||||
|  |     transition: background-color 0.2s; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .resize-handle-top { | ||||||
|  |     top: 0; | ||||||
|  |     border-top: 2px solid transparent; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .resize-handle-bottom { | ||||||
|  |     bottom: 0; | ||||||
|  |     border-bottom: 2px solid transparent; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .week-event:hover .resize-handle { | ||||||
|  |     background: rgba(255, 255, 255, 0.3); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .week-event:hover .resize-handle-top { | ||||||
|  |     border-top-color: rgba(255, 255, 255, 0.8); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .week-event:hover .resize-handle-bottom { | ||||||
|  |     border-bottom-color: rgba(255, 255, 255, 0.8); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .resize-handle:hover { | ||||||
|  |     background: rgba(255, 255, 255, 0.5) !important; | ||||||
|  |     border-color: rgba(255, 255, 255, 1) !important; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| .week-event .event-title { | .week-event .event-title { | ||||||
|     font-weight: 600; |     font-weight: 600; | ||||||
|     margin-bottom: 2px; |     margin-bottom: 2px; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user