refactor(KanbanGroup, TaskCard): enhance drag-and-drop indicators and task rendering

- Added visual drop indicators before and after task cards in the KanbanGroup component to improve user experience during drag-and-drop operations.
- Removed the isDropIndicator prop from TaskCard as the drop indicator logic is now handled within the KanbanGroup, simplifying the TaskCard component.
- Updated drag-and-drop event handling in TaskCard to better manage task positioning during drag operations, enhancing overall functionality.
This commit is contained in:
shancds
2025-07-07 17:20:34 +05:30
parent 8e62594eff
commit fa9e765e37
2 changed files with 31 additions and 28 deletions

View File

@@ -517,17 +517,29 @@ const KanbanGroup: React.FC<KanbanGroupProps> = memo(({
)} )}
{group.tasks.map((task, idx) => ( {group.tasks.map((task, idx) => (
<TaskCard <React.Fragment key={task.id}>
key={task.id} {/* Drop indicator before this card */}
task={task} {hoveredGroupId === group.id && hoveredTaskIdx === idx && (
onTaskDragStart={onTaskDragStart} <div className="drop-preview-indicator" style={{height: 24, display: 'flex', alignItems: 'center', justifyContent: 'center', margin: '4px 0'}}>
onTaskDragOver={onTaskDragOver} <div className="drop-line" style={{width: '90%', height: 4, background: '#1976d2', borderRadius: 2, boxShadow: '0 0 4px #1976d2'}} />
onTaskDrop={onTaskDrop} </div>
groupId={group.id} )}
isDropIndicator={hoveredGroupId === group.id && hoveredTaskIdx === idx} <TaskCard
idx={idx} task={task}
/> onTaskDragStart={onTaskDragStart}
onTaskDragOver={onTaskDragOver}
onTaskDrop={onTaskDrop}
groupId={group.id}
idx={idx}
/>
</React.Fragment>
))} ))}
{/* Drop indicator at the end of the group */}
{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 className="drop-line" style={{width: '90%', height: 4, background: '#1976d2', borderRadius: 2, boxShadow: '0 0 4px #1976d2'}} />
</div>
)}
{/* Create card at bottom */} {/* Create card at bottom */}
{showNewCardBottom && ( {showNewCardBottom && (

View File

@@ -28,7 +28,6 @@ interface TaskCardProps {
onTaskDragOver: (e: React.DragEvent, groupId: string, taskIdx: number) => void; onTaskDragOver: (e: React.DragEvent, groupId: string, taskIdx: number) => void;
onTaskDrop: (e: React.DragEvent, groupId: string, taskIdx: number) => void; onTaskDrop: (e: React.DragEvent, groupId: string, taskIdx: number) => void;
groupId: string; groupId: string;
isDropIndicator: boolean;
idx: number; idx: number;
} }
@@ -46,7 +45,6 @@ const TaskCard: React.FC<TaskCardProps> = memo(({
onTaskDragOver, onTaskDragOver,
onTaskDrop, onTaskDrop,
groupId, groupId,
isDropIndicator,
idx idx
}) => { }) => {
const { socket } = useSocket(); const { socket } = useSocket();
@@ -198,29 +196,22 @@ const TaskCard: React.FC<TaskCardProps> = memo(({
while (week.length < 7) week.push(null); while (week.length < 7) week.push(null);
weeks.push(week); weeks.push(week);
} }
const [isDown, setIsDown] = useState(false);
return ( return (
<> <>
{isDropIndicator && (
<div
onDragStart={e => onTaskDragStart(e, task.id!, groupId)}
onDragOver={e => onTaskDragOver(e, groupId, idx)}
onDrop={e => onTaskDrop(e, groupId, 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 className="enhanced-kanban-task-card" style={{ background, color, display: 'block' }} > <div className="enhanced-kanban-task-card" style={{ background, color, display: 'block' }} >
<div <div
draggable draggable
onDragStart={e => onTaskDragStart(e, task.id!, groupId)} onDragStart={e => onTaskDragStart(e, task.id!, groupId)}
onDragOver={e => onTaskDragOver(e, groupId, idx)} onDragOver={e => {
e.preventDefault();
const rect = e.currentTarget.getBoundingClientRect();
const offsetY = e.clientY - rect.top;
const isDown = offsetY > rect.height / 2;
setIsDown(isDown);
onTaskDragOver(e, groupId, isDown ? idx + 1 : idx);
}}
onDrop={e => onTaskDrop(e, groupId, idx)} onDrop={e => onTaskDrop(e, groupId, idx)}
onClick={e => handleCardClick(e, task.id!)} onClick={e => handleCardClick(e, task.id!)}