diff --git a/client/src/components/production-board-kanban/trello-board/controllers/Board.jsx b/client/src/components/production-board-kanban/trello-board/controllers/Board.jsx index 9a177d043..18c7e0dea 100644 --- a/client/src/components/production-board-kanban/trello-board/controllers/Board.jsx +++ b/client/src/components/production-board-kanban/trello-board/controllers/Board.jsx @@ -20,7 +20,7 @@ const Board = ({ id, className, orientation, cardSettings, ...additionalProps }) default: return cardSizesVertical.small; } - }, [cardSettings]); + }, [cardSettings?.cardSize]); return ( <> diff --git a/client/src/components/production-board-kanban/trello-board/controllers/BoardContainer.jsx b/client/src/components/production-board-kanban/trello-board/controllers/BoardContainer.jsx index 21d4792ee..98d026465 100644 --- a/client/src/components/production-board-kanban/trello-board/controllers/BoardContainer.jsx +++ b/client/src/components/production-board-kanban/trello-board/controllers/BoardContainer.jsx @@ -101,11 +101,33 @@ const BoardContainer = ({ async ({ draggableId, type, source, reason, mode, destination, combine }) => { setIsDragging(false); - // Only update drag time if it's a valid drop with a different destination - if (type === "lane" && source && destination && !isEqual(source, destination)) { - setDragTime(source.droppableId); - setIsProcessing(true); + // Validate drag type and source + if (type !== "lane" || !source) { + // Invalid drag type or missing source, attempt to revert if possible + if (source) { + dispatch( + actions.moveCardAcrossLanes({ + fromLaneId: source.droppableId, + toLaneId: source.droppableId, + cardId: draggableId, + index: source.index + }) + ); + } + setIsProcessing(false); + try { + await onDragEnd({ draggableId, type, source, reason, mode, destination, combine }); + } catch (err) { + console.error("Error in onLaneDrag for invalid drag type or source", err); + } + return; + } + setDragTime(source.droppableId); + setIsProcessing(true); + + // Handle valid drop to a different lane or position + if (destination && !isEqual(source, destination)) { dispatch( actions.moveCardAcrossLanes({ fromLaneId: source.droppableId, @@ -114,14 +136,33 @@ const BoardContainer = ({ index: destination.index }) ); + } else { + // Same-lane drop or no destination, revert to original position + dispatch( + actions.moveCardAcrossLanes({ + fromLaneId: source.droppableId, + toLaneId: source.droppableId, + cardId: draggableId, + index: source.index + }) + ); + } - try { - await onDragEnd({ draggableId, type, source, reason, mode, destination, combine }); - } catch (err) { - console.error("Error in onLaneDrag", err); - } finally { - setIsProcessing(false); - } + try { + await onDragEnd({ draggableId, type, source, reason, mode, destination, combine }); + } catch (err) { + console.error("Error in onLaneDrag", err); + // Ensure revert on error + dispatch( + actions.moveCardAcrossLanes({ + fromLaneId: source.droppableId, + toLaneId: source.droppableId, + cardId: draggableId, + index: source.index + }) + ); + } finally { + setIsProcessing(false); } }, [dispatch, onDragEnd, setDragTime] diff --git a/client/src/components/production-board-kanban/trello-board/controllers/Lane.jsx b/client/src/components/production-board-kanban/trello-board/controllers/Lane.jsx index da4ff9f46..22ad8e28b 100644 --- a/client/src/components/production-board-kanban/trello-board/controllers/Lane.jsx +++ b/client/src/components/production-board-kanban/trello-board/controllers/Lane.jsx @@ -133,7 +133,9 @@ const Lane = ({ Item: ItemComponent }, itemContent: (index, item) => {renderDraggable(index, item)}, - overscan: { main: 10, reverse: 10 } + overscan: { main: 10, reverse: 10 }, + // Ensure a minimum height for empty lanes to allow dropping + style: renderedCards.length === 0 ? { minHeight: "5px" } : {} }; const horizontalProps = { @@ -149,8 +151,6 @@ const Lane = ({ const componentProps = orientation === "vertical" ? verticalProps : horizontalProps; - // If the lane is collapsed, we want to render a div instead of the virtualized list, and we want to set the height to the max height of the lane so that - // the lane doesn't shrink when collapsed (in horizontal mode) const finalComponentProps = collapsed ? orientation === "horizontal" ? { @@ -161,9 +161,8 @@ const Lane = ({ : {} : componentProps; - // If the lane is horizontal and collapsed, we want to render a placeholder so that the lane doesn't shrink to 0 height and grows when - // a card is dragged over it - const shouldRenderPlaceholder = orientation !== "horizontal" && (collapsed || renderedCards.length === 0); + // Always render placeholder for empty lanes in vertical mode to ensure droppable area + const shouldRenderPlaceholder = orientation === "vertical" ? collapsed || renderedCards.length === 0 : collapsed; return (