fix: use onClick for card select, right-click safe

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
EENE Dashboard
2026-06-01 11:44:58 +09:00
parent 780b6a9ef5
commit 4142d04361

View File

@@ -1,4 +1,4 @@
import { useState, useRef } from 'react'; import { useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useSortable } from '@dnd-kit/sortable'; import { useSortable } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities'; import { CSS } from '@dnd-kit/utilities';
@@ -62,25 +62,8 @@ export function SortableTaskCard({ task, sectionOptions, onSelect }: { task: Tas
opacity: isDragging ? 0.4 : 1, opacity: isDragging ? 0.4 : 1,
}; };
// dnd-kit이 dragListeners의 onPointerDown을 가로채므로 onClick이 막힐 수 있음. const handleClick = () => {
// pointerDown 시작 위치를 ref로 기억했다가 pointerUp에서 이동이 적으면 클릭으로 판정. if (!isDragging) onSelect?.(task);
const pointerStart = useRef<{ x: number; y: number } | null>(null);
const handlePointerDown = (e: React.PointerEvent) => {
if (e.button !== 0) return; // 좌클릭만
pointerStart.current = { x: e.clientX, y: e.clientY };
};
const handlePointerUp = (e: React.PointerEvent) => {
if (e.button !== 0) return; // 좌클릭만
if (!pointerStart.current || isDragging) return;
const dx = e.clientX - pointerStart.current.x;
const dy = e.clientY - pointerStart.current.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 6) {
onSelect?.(task);
}
pointerStart.current = null;
}; };
return ( return (
@@ -91,8 +74,7 @@ export function SortableTaskCard({ task, sectionOptions, onSelect }: { task: Tas
dragAttributes={attributes} dragAttributes={attributes}
dragListeners={listeners} dragListeners={listeners}
sectionOptions={sectionOptions} sectionOptions={sectionOptions}
onCardPointerDown={handlePointerDown} onCardClick={handleClick}
onCardPointerUp={handlePointerUp}
/> />
); );
} }
@@ -105,8 +87,7 @@ export function TaskCard({
dragAttributes, dragAttributes,
dragListeners, dragListeners,
sectionOptions, sectionOptions,
onCardPointerDown, onCardClick,
onCardPointerUp,
}: { }: {
task: Task; task: Task;
dragRef?: (node: HTMLElement | null) => void; dragRef?: (node: HTMLElement | null) => void;
@@ -114,8 +95,7 @@ export function TaskCard({
dragAttributes?: DraggableAttributes; dragAttributes?: DraggableAttributes;
dragListeners?: SyntheticListenerMap; dragListeners?: SyntheticListenerMap;
sectionOptions?: SectionOption[]; sectionOptions?: SectionOption[];
onCardPointerDown?: (e: React.PointerEvent) => void; onCardClick?: () => void;
onCardPointerUp?: (e: React.PointerEvent) => void;
}) { }) {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const tagCfg = TAG_CONFIG[task.tag ?? ''] ?? { bg: 'bg-gray-100', text: 'text-gray-600' }; const tagCfg = TAG_CONFIG[task.tag ?? ''] ?? { bg: 'bg-gray-100', text: 'text-gray-600' };
@@ -195,8 +175,7 @@ export function TaskCard({
{...dragAttributes} {...dragAttributes}
{...dragListeners} {...dragListeners}
className="bg-white rounded-2xl px-5 py-3 mb-3 shadow-sm border border-gray-100 hover:shadow-md hover:border-gray-200 transition-all select-none h-[112px] cursor-grab active:cursor-grabbing overflow-hidden" className="bg-white rounded-2xl px-5 py-3 mb-3 shadow-sm border border-gray-100 hover:shadow-md hover:border-gray-200 transition-all select-none h-[112px] cursor-grab active:cursor-grabbing overflow-hidden"
onPointerDown={onCardPointerDown} onClick={onCardClick}
onPointerUp={onCardPointerUp}
onContextMenu={handleContextMenu} onContextMenu={handleContextMenu}
> >
{/* ── 상단: 제목 + 진행률 ── */} {/* ── 상단: 제목 + 진행률 ── */}