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:
shancds
2025-07-08 12:13:23 +05:30
parent d150747f83
commit 2aab2a21b6
3 changed files with 35 additions and 7 deletions

View File

@@ -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}
/> />

View File

@@ -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 */}

View File

@@ -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">