From cbe2461204b15bb6c75d63497ecc43ed5c0e6477 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Fri, 22 Aug 2025 04:57:14 +0000 Subject: [PATCH] Refactor drag and drop for mobile Replaced drag and drop functionality with a click-to-select and click-to-drop interaction for mobile friendliness. When a box in the container is clicked, columns become highlighted and clickable. Clicking a column drops the box there, and the columns return to their default state. Existing features like double-clicking and desktop drag-and-drop remain. --- src/components/BulgarianSolitaire.tsx | 46 +++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/components/BulgarianSolitaire.tsx b/src/components/BulgarianSolitaire.tsx index f7efad6..d61dfa8 100644 --- a/src/components/BulgarianSolitaire.tsx +++ b/src/components/BulgarianSolitaire.tsx @@ -24,6 +24,7 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare const [highlightedBoxes, setHighlightedBoxes] = useState>(new Set()); const [isAnimating, setIsAnimating] = useState(false); const [lastUsedColumn, setLastUsedColumn] = useState(null); + const [selectedBoxForMove, setSelectedBoxForMove] = useState(null); const totalBoxes = (n * (n + 1)) / 2; @@ -98,6 +99,33 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare setDraggedBox(null); }; + const handleBoxClick = (boxId: number) => { + const box = boxes.find(b => b.id === boxId); + if (!box || box.columnIndex !== null || isPlaying) return; + + // Select box for moving + setSelectedBoxForMove(boxId); + }; + + const handleColumnClick = (e: React.MouseEvent, columnIndex: number) => { + e.stopPropagation(); + if (selectedBoxForMove === null || isPlaying) return; + + // Move selected box to this column + setColumns(prev => prev.map((col, idx) => + idx === columnIndex ? [...col, selectedBoxForMove] : col + )); + + // Update box location + setBoxes(prev => prev.map(b => + b.id === selectedBoxForMove ? { ...b, columnIndex } : b + )); + + // Track last used column and clear selection + setLastUsedColumn(columnIndex); + setSelectedBoxForMove(null); + }; + const handleDoubleClick = (boxId: number) => { const box = boxes.find(b => b.id === boxId); if (!box) return; @@ -258,8 +286,14 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare const containerBoxes = boxes.filter(box => box.columnIndex === null); + const handleBackgroundClick = () => { + if (selectedBoxForMove !== null) { + setSelectedBoxForMove(null); + } + }; + return ( -
+

Bulgarian Solitaire

@@ -302,7 +336,10 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare draggable={!isPlaying} onDragStart={(e) => handleDragStart(e, box.id)} onDoubleClick={() => handleDoubleClick(box.id)} - className="w-8 h-8 bg-primary rounded cursor-move hover:bg-primary/80 transition-colors" + onClick={() => handleBoxClick(box.id)} + className={`w-8 h-8 bg-primary rounded cursor-pointer hover:bg-primary/80 transition-colors ${ + selectedBoxForMove === box.id ? 'ring-2 ring-blue-500 ring-offset-2' : '' + }`} >

))} @@ -325,7 +362,10 @@ const BulgarianSolitaire: React.FC = ({ showSocialShare key={index} onDragOver={handleDragOver} onDrop={(e) => handleDrop(e, index)} - className="border border-muted-foreground rounded-lg min-h-[100px] w-12 p-1 bg-background/50 flex flex-col-reverse gap-1 transition-all duration-500" + onClick={(e) => handleColumnClick(e, index)} + className={`border rounded-lg min-h-[100px] w-12 p-1 bg-background/50 flex flex-col-reverse gap-1 transition-all duration-500 ${ + selectedBoxForMove !== null ? 'border-blue-500 border-2 cursor-pointer hover:bg-blue-50' : 'border-muted-foreground' + }`} style={{ flexBasis: `calc(${100/15}% - 0.25rem)`, minWidth: '48px' }} >