diff --git a/src/components/week_view.rs b/src/components/week_view.rs index 9afbd8b..51c18be 100644 --- a/src/components/week_view.rs +++ b/src/components/week_view.rs @@ -44,6 +44,7 @@ struct DragState { start_y: f64, current_y: f64, 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)] @@ -163,6 +164,7 @@ pub fn week_view(props: &WeekViewProps) -> Html { start_y: snapped_y, current_y: snapped_y, offset_y: 0.0, + has_moved: false, })); e.prevent_default(); }) @@ -175,11 +177,21 @@ pub fn week_view(props: &WeekViewProps) -> Html { if let Some(mut current_drag) = (*drag_state).clone() { if current_drag.is_dragging { // Use layer_y for consistent coordinate calculation - 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 mouse_y = e.layer_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 - 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; drag_state.set(Some(current_drag)); @@ -194,7 +206,7 @@ pub fn week_view(props: &WeekViewProps) -> Html { let on_event_update = props.on_event_update.clone(); Callback::from(move |_e: MouseEvent| { 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 { DragType::CreateEvent => { // Calculate start and end times @@ -223,8 +235,9 @@ pub fn week_view(props: &WeekViewProps) -> Html { } }, DragType::MoveEvent(event) => { - // Calculate new start time based on drag position - let new_start_time = pixels_to_time(current_drag.current_y); + // Calculate new start time based on drag position (accounting for click offset) + let event_top_position = current_drag.current_y - current_drag.offset_y; + let new_start_time = pixels_to_time(event_top_position); // Calculate duration from original event let original_duration = if let Some(end) = event.end { @@ -344,7 +357,7 @@ pub fn week_view(props: &WeekViewProps) -> Html { let drag_state = drag_state.clone(); let event_for_drag = event.clone(); let date_for_drag = *date; - let time_increment = props.time_increment; + let _time_increment = props.time_increment; Callback::from(move |e: MouseEvent| { e.stop_propagation(); // Prevent drag-to-create from starting on event clicks @@ -353,25 +366,30 @@ pub fn week_view(props: &WeekViewProps) -> Html { return; } - // Calculate absolute Y position for drag calculations - let absolute_y = e.layer_y() as f64; - let absolute_y = if absolute_y > 0.0 { absolute_y } else { e.offset_y() as f64 }; + // Calculate click position relative to event element + let click_y_relative = e.layer_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 for offset calculation + // 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 = event_start_pixels as f64; - let offset_y = absolute_y - event_start_pixels; - // Snap to increment - let snapped_y = snap_to_increment(absolute_y, time_increment); + // Convert click position to day column coordinates + let click_y = event_start_pixels + click_y_relative; + // Store the offset from the event's top where the user clicked + // 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 { is_dragging: true, drag_type: DragType::MoveEvent(event_for_drag.clone()), start_date: date_for_drag, - start_y: snapped_y, - current_y: snapped_y, + start_y: click_y, + current_y: click_y, offset_y, + has_moved: false, })); e.prevent_default(); }) @@ -470,6 +488,7 @@ pub fn week_view(props: &WeekViewProps) -> Html { start_y: snapped_y, current_y: snapped_y, offset_y: 0.0, + has_moved: false, })); e.prevent_default(); }) @@ -494,6 +513,7 @@ pub fn week_view(props: &WeekViewProps) -> Html { start_y: snapped_y, current_y: snapped_y, offset_y: 0.0, + has_moved: false, })); e.prevent_default(); }) @@ -580,8 +600,9 @@ pub fn week_view(props: &WeekViewProps) -> Html { } }, DragType::MoveEvent(event) => { - // Show the event being moved at its new position - let new_start_time = pixels_to_time(drag.current_y); + // Calculate the event's new position accounting for click offset + let preview_position = drag.current_y - drag.offset_y; + let new_start_time = pixels_to_time(preview_position); let original_duration = if let Some(end) = event.end { end.signed_duration_since(event.start) } else { @@ -595,7 +616,7 @@ pub fn week_view(props: &WeekViewProps) -> Html { html! {