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:
@@ -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 && (
|
||||||
|
|||||||
@@ -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!)}
|
||||||
|
|||||||
Reference in New Issue
Block a user