diff --git a/src/components/PricingView.tsx b/src/components/PricingView.tsx index 0a57b75..2118d7f 100644 --- a/src/components/PricingView.tsx +++ b/src/components/PricingView.tsx @@ -115,13 +115,15 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, const [pinnedColumns, setPinnedColumns] = usePersistentState>('pricing-pinnedColumns', new Set(['articleNo', 'articleName'])); const [showPinPanel, setShowPinPanel] = useState(false); - // Drag-to-select state - const [selectedRows, setSelectedRows] = useState>(new Set()); + // Drag-to-check state (Excel-style drag to toggle Check Ying) + const [dragSelectedRows, setDragSelectedRows] = useState>(new Set()); const isDraggingRef = useRef(false); const dragStartIndexRef = useRef(null); - const dragModeRef = useRef<'add' | 'remove'>('add'); + const dragCheckValueRef = useRef(true); // what value to set on mouseup const lastDragIndexRef = useRef(null); const visibleDataIndexesRef = useRef([]); + const dataRef = useRef(data); + dataRef.current = data; const handleRowMouseDown = useCallback((e: React.MouseEvent, dataIndex: number) => { if ((e.target as HTMLElement).closest('input, button, a')) return; @@ -129,20 +131,10 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, isDraggingRef.current = true; dragStartIndexRef.current = dataIndex; lastDragIndexRef.current = dataIndex; - - if (e.ctrlKey || e.metaKey) { - dragModeRef.current = selectedRows.has(dataIndex) ? 'remove' : 'add'; - setSelectedRows(prev => { - const next = new Set(prev); - if (next.has(dataIndex)) next.delete(dataIndex); else next.add(dataIndex); - return next; - }); - return; - } - - dragModeRef.current = selectedRows.has(dataIndex) ? 'remove' : 'add'; - setSelectedRows(new Set([dataIndex])); - }, [selectedRows]); + // Toggle based on current state of the first row touched + dragCheckValueRef.current = !dataRef.current[dataIndex]?.[COLUMNS.VALIDATED_CHECK]; + setDragSelectedRows(new Set([dataIndex])); + }, [COLUMNS.VALIDATED_CHECK]); const handleRowMouseEnter = useCallback((dataIndex: number) => { if (!isDraggingRef.current || dragStartIndexRef.current === null) return; @@ -153,23 +145,30 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, const end = dataIndex; const [lo, hi] = start <= end ? [start, end] : [end, start]; - setSelectedRows(prev => { - const next = new Set(prev); + setDragSelectedRows(() => { + const next = new Set(); visibleDataIndexesRef.current.forEach((idx: number) => { - if (idx >= lo && idx <= hi) { - if (dragModeRef.current === 'add') next.add(idx); - else next.delete(idx); - } + if (idx >= lo && idx <= hi) next.add(idx); }); return next; }); }, []); useEffect(() => { - const handleMouseUp = () => { isDraggingRef.current = false; }; + const handleMouseUp = async () => { + if (!isDraggingRef.current) return; + isDraggingRef.current = false; + const rows = new Set(dragSelectedRows); + if (rows.size === 0) return; + setDragSelectedRows(new Set()); + const targetValue = dragCheckValueRef.current; + for (const idx of Array.from(rows)) { + await handleToggleCheck(idx as number, targetValue); + } + }; document.addEventListener('mouseup', handleMouseUp); return () => document.removeEventListener('mouseup', handleMouseUp); - }, []); + }, [dragSelectedRows]); // Close search dropdown on click outside useEffect(() => { @@ -1900,7 +1899,7 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit, const isValidated = !!row[COLUMNS.VALIDATED_CHECK]; const note = String(row[COLUMNS.VALIDATED_NOTE] || ''); - const isRowSelected = selectedRows.has(dataIndex); + const isRowSelected = dragSelectedRows.has(dataIndex); return ( ยท Click any price cell to edit inline )}

- {selectedRows.size > 0 && ( + {dragSelectedRows.size > 0 && ( - {selectedRows.size} selected + {dragSelectedRows.size} selected