feat(EnhancedKanbanBoard): implement drag end handling for improved task interaction
- Added handleDragEnd function to reset hovered task and group states after drag operations in EnhancedKanbanBoard. - Updated KanbanGroup and TaskCard components to support onDragEnd prop, enhancing drag-and-drop functionality and user experience during task management.
This commit is contained in:
@@ -263,6 +263,11 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
setDragType(null);
|
setDragType(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDragEnd = () => {
|
||||||
|
setHoveredGroupId(null);
|
||||||
|
setHoveredTaskIdx(null);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!socket) return;
|
if (!socket) return;
|
||||||
|
|
||||||
@@ -332,6 +337,7 @@ const EnhancedKanbanBoardNativeDnD: React.FC<{ projectId: string }> = ({ project
|
|||||||
onTaskDragStart={handleTaskDragStart}
|
onTaskDragStart={handleTaskDragStart}
|
||||||
onTaskDragOver={handleTaskDragOver}
|
onTaskDragOver={handleTaskDragOver}
|
||||||
onTaskDrop={handleTaskDrop}
|
onTaskDrop={handleTaskDrop}
|
||||||
|
onDragEnd={handleDragEnd}
|
||||||
hoveredTaskIdx={hoveredGroupId === group.id ? hoveredTaskIdx : null}
|
hoveredTaskIdx={hoveredGroupId === group.id ? hoveredTaskIdx : null}
|
||||||
hoveredGroupId={hoveredGroupId}
|
hoveredGroupId={hoveredGroupId}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ interface KanbanGroupProps {
|
|||||||
onTaskDragStart: (e: React.DragEvent, taskId: string, groupId: string) => void;
|
onTaskDragStart: (e: React.DragEvent, taskId: string, groupId: string) => void;
|
||||||
onTaskDragOver: (e: React.DragEvent, groupId: string, taskIdx: number | null) => void;
|
onTaskDragOver: (e: React.DragEvent, groupId: string, taskIdx: number | null) => void;
|
||||||
onTaskDrop: (e: React.DragEvent, groupId: string, taskIdx: number | null) => void;
|
onTaskDrop: (e: React.DragEvent, groupId: string, taskIdx: number | null) => void;
|
||||||
|
onDragEnd: (e: React.DragEvent) => void;
|
||||||
hoveredTaskIdx: number | null;
|
hoveredTaskIdx: number | null;
|
||||||
hoveredGroupId: string | null;
|
hoveredGroupId: string | null;
|
||||||
}
|
}
|
||||||
@@ -46,6 +47,7 @@ const KanbanGroup: React.FC<KanbanGroupProps> = memo(({
|
|||||||
onTaskDragStart,
|
onTaskDragStart,
|
||||||
onTaskDragOver,
|
onTaskDragOver,
|
||||||
onTaskDrop,
|
onTaskDrop,
|
||||||
|
onDragEnd,
|
||||||
hoveredTaskIdx,
|
hoveredTaskIdx,
|
||||||
hoveredGroupId
|
hoveredGroupId
|
||||||
}) => {
|
}) => {
|
||||||
@@ -259,6 +261,7 @@ const KanbanGroup: React.FC<KanbanGroupProps> = memo(({
|
|||||||
onDragStart={e => onGroupDragStart(e, group.id)}
|
onDragStart={e => onGroupDragStart(e, group.id)}
|
||||||
onDragOver={onGroupDragOver}
|
onDragOver={onGroupDragOver}
|
||||||
onDrop={e => onGroupDrop(e, group.id)}
|
onDrop={e => onGroupDrop(e, group.id)}
|
||||||
|
onDragEnd={onDragEnd}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="flex items-center justify-between w-full font-semibold rounded-md"
|
className="flex items-center justify-between w-full font-semibold rounded-md"
|
||||||
@@ -520,8 +523,16 @@ const KanbanGroup: React.FC<KanbanGroupProps> = memo(({
|
|||||||
<React.Fragment key={task.id}>
|
<React.Fragment key={task.id}>
|
||||||
{/* Drop indicator before this card */}
|
{/* Drop indicator before this card */}
|
||||||
{hoveredGroupId === group.id && hoveredTaskIdx === idx && (
|
{hoveredGroupId === group.id && hoveredTaskIdx === idx && (
|
||||||
<div className="drop-preview-indicator" style={{height: 24, display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '4px 0'}}>
|
<div
|
||||||
<div className="drop-line" style={{width: '90%', height: 4, background: '#1976d2', borderRadius: 2, boxShadow: '0 0 4px #1976d2'}} />
|
onDragOver={e => onTaskDragOver(e, group.id, idx)}
|
||||||
|
onDrop={e => onTaskDrop(e, group.id, idx)}
|
||||||
|
>
|
||||||
|
<div className="w-full h-full bg-red-500" style={{
|
||||||
|
height: 80,
|
||||||
|
background: themeMode === 'dark' ? '#2a2a2a' : '#E2EAF4',
|
||||||
|
borderRadius: 6,
|
||||||
|
border: `5px`
|
||||||
|
}}></div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<TaskCard
|
<TaskCard
|
||||||
@@ -531,14 +542,23 @@ const KanbanGroup: React.FC<KanbanGroupProps> = memo(({
|
|||||||
onTaskDrop={onTaskDrop}
|
onTaskDrop={onTaskDrop}
|
||||||
groupId={group.id}
|
groupId={group.id}
|
||||||
idx={idx}
|
idx={idx}
|
||||||
|
onDragEnd={onDragEnd}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
{/* Drop indicator at the end of the group */}
|
{/* Drop indicator at the end of the group */}
|
||||||
{hoveredGroupId === group.id && hoveredTaskIdx === group.tasks.length && (
|
{hoveredGroupId === group.id && hoveredTaskIdx === group.tasks.length && (
|
||||||
<div className="drop-preview-indicator" style={{height: 24, display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '4px 0'}}>
|
<div
|
||||||
<div className="drop-line" style={{width: '90%', height: 4, background: '#1976d2', borderRadius: 2, boxShadow: '0 0 4px #1976d2'}} />
|
onDragOver={e => onTaskDragOver(e, group.id, group.tasks.length)}
|
||||||
</div>
|
onDrop={e => onTaskDrop(e, group.id, group.tasks.length)}
|
||||||
|
>
|
||||||
|
<div className="w-full h-full bg-red-500" style={{
|
||||||
|
height: 80,
|
||||||
|
background: themeMode === 'dark' ? '#2a2a2a' : '#E2EAF4',
|
||||||
|
borderRadius: 6,
|
||||||
|
border: `5px`
|
||||||
|
}}></div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Create card at bottom */}
|
{/* Create card at bottom */}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ interface TaskCardProps {
|
|||||||
onTaskDrop: (e: React.DragEvent, groupId: string, taskIdx: number) => void;
|
onTaskDrop: (e: React.DragEvent, groupId: string, taskIdx: number) => void;
|
||||||
groupId: string;
|
groupId: string;
|
||||||
idx: number;
|
idx: number;
|
||||||
|
onDragEnd: (e: React.DragEvent) => void; // <-- add this
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDaysInMonth(year: number, month: number) {
|
function getDaysInMonth(year: number, month: number) {
|
||||||
@@ -45,7 +46,8 @@ const TaskCard: React.FC<TaskCardProps> = memo(({
|
|||||||
onTaskDragOver,
|
onTaskDragOver,
|
||||||
onTaskDrop,
|
onTaskDrop,
|
||||||
groupId,
|
groupId,
|
||||||
idx
|
idx,
|
||||||
|
onDragEnd // <-- add this
|
||||||
}) => {
|
}) => {
|
||||||
const { socket } = useSocket();
|
const { socket } = useSocket();
|
||||||
const themeMode = useSelector((state: RootState) => state.themeReducer.mode);
|
const themeMode = useSelector((state: RootState) => state.themeReducer.mode);
|
||||||
@@ -213,7 +215,7 @@ const TaskCard: React.FC<TaskCardProps> = memo(({
|
|||||||
onTaskDragOver(e, groupId, isDown ? idx + 1 : idx);
|
onTaskDragOver(e, groupId, isDown ? idx + 1 : idx);
|
||||||
}}
|
}}
|
||||||
onDrop={e => onTaskDrop(e, groupId, idx)}
|
onDrop={e => onTaskDrop(e, groupId, idx)}
|
||||||
|
onDragEnd={onDragEnd} // <-- add this
|
||||||
onClick={e => handleCardClick(e, task.id!)}
|
onClick={e => handleCardClick(e, task.id!)}
|
||||||
>
|
>
|
||||||
<div className="task-content">
|
<div className="task-content">
|
||||||
|
|||||||
Reference in New Issue
Block a user