From 8a6fed80788712bc2f9657f9771194d2b556bd77 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 06:48:56 +0000 Subject: [PATCH] Refactor Stacking Blocks interactive Update Stacking Blocks interactive to break stacks on hover, display points in tooltips, and remove the modal. Here are the files that were edited by the AI in that message: -edited src/components/StackingBlocks.tsx --- src/components/StackingBlocks.tsx | 179 +++++++++++------------------- 1 file changed, 62 insertions(+), 117 deletions(-) diff --git a/src/components/StackingBlocks.tsx b/src/components/StackingBlocks.tsx index 2a1af48..2ccc84b 100644 --- a/src/components/StackingBlocks.tsx +++ b/src/components/StackingBlocks.tsx @@ -1,11 +1,10 @@ import React, { useState, useCallback } from 'react'; import { Button } from '@/components/ui/button'; import { Slider } from '@/components/ui/slider'; -import { Input } from '@/components/ui/input'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'; import { Label } from '@/components/ui/label'; import { Separator } from '@/components/ui/separator'; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; import SocialShare from './SocialShare'; import confetti from 'canvas-confetti'; @@ -19,17 +18,16 @@ const StackingBlocks: React.FC = ({ showSocialShare = false const [score, setScore] = useState(0); const [gameStarted, setGameStarted] = useState(false); const [gameComplete, setGameComplete] = useState(false); - const [selectedStack, setSelectedStack] = useState(null); - const [splitSize1, setSplitSize1] = useState(''); - const [splitSize2, setSplitSize2] = useState(''); - const [dialogOpen, setDialogOpen] = useState(false); + const [hoveredStack, setHoveredStack] = useState(null); + const [hoveredSplitPoint, setHoveredSplitPoint] = useState(null); const startGame = useCallback(() => { setStacks([n]); setScore(0); setGameStarted(true); setGameComplete(false); - setSelectedStack(null); + setHoveredStack(null); + setHoveredSplitPoint(null); }, [n]); const resetGame = useCallback(() => { @@ -37,38 +35,23 @@ const StackingBlocks: React.FC = ({ showSocialShare = false setScore(0); setGameStarted(false); setGameComplete(false); - setSelectedStack(null); - setSplitSize1(''); - setSplitSize2(''); - setDialogOpen(false); + setHoveredStack(null); + setHoveredSplitPoint(null); }, []); - const handleStackClick = useCallback((index: number, stackSize: number) => { - if (stackSize === 1) return; // Can't split stacks of size 1 - setSelectedStack(index); - setSplitSize1('1'); - setSplitSize2((stackSize - 1).toString()); - setDialogOpen(true); - }, []); - - const executeSplit = useCallback(() => { - if (selectedStack === null) return; + const handleStackClick = useCallback((stackIndex: number, splitPoint: number) => { + if (hoveredStack !== stackIndex || hoveredSplitPoint !== splitPoint) return; - const size1 = parseInt(splitSize1); - const size2 = parseInt(splitSize2); - const originalSize = stacks[selectedStack]; - - // Validate the split - if (size1 <= 0 || size2 <= 0 || size1 + size2 !== originalSize) { - return; - } + const stackSize = stacks[stackIndex]; + const size1 = splitPoint; + const size2 = stackSize - splitPoint; // Calculate points gained const pointsGained = size1 * size2; // Update stacks const newStacks = [...stacks]; - newStacks.splice(selectedStack, 1); // Remove the original stack + newStacks.splice(stackIndex, 1); // Remove the original stack newStacks.push(size1, size2); // Add the two new stacks newStacks.sort((a, b) => b - a); // Sort in descending order for better visualization @@ -85,20 +68,9 @@ const StackingBlocks: React.FC = ({ showSocialShare = false }); } - setDialogOpen(false); - setSelectedStack(null); - setSplitSize1(''); - setSplitSize2(''); - }, [selectedStack, splitSize1, splitSize2, stacks]); - - const handleSplit1Change = (value: string) => { - setSplitSize1(value); - const size1 = parseInt(value); - if (!isNaN(size1) && selectedStack !== null) { - const originalSize = stacks[selectedStack]; - setSplitSize2((originalSize - size1).toString()); - } - }; + setHoveredStack(null); + setHoveredSplitPoint(null); + }, [stacks, hoveredStack, hoveredSplitPoint]); const getStackColor = (size: number) => { if (size === 1) return 'bg-gray-200'; @@ -108,25 +80,54 @@ const StackingBlocks: React.FC = ({ showSocialShare = false return 'bg-red-200'; }; - const renderStack = (size: number, index: number) => { + const renderStack = (size: number, stackIndex: number) => { const canSplit = size > 1; return ( -
canSplit && handleStackClick(index, size)} - > -
Stack {index + 1}
+
+
Stack {stackIndex + 1}
- {Array.from({ length: size }).map((_, blockIndex) => ( -
- ))} + {Array.from({ length: size }).map((_, blockIndex) => { + const splitPoint = size - blockIndex; // How many blocks would be in the top stack if we split here + const bottomSize = blockIndex + 1; // How many blocks would be in the bottom stack + const pointsGained = canSplit && splitPoint > 0 && bottomSize > 0 ? splitPoint * bottomSize : 0; + const isHovered = hoveredStack === stackIndex && hoveredSplitPoint === splitPoint; + const showSplitLine = canSplit && splitPoint > 0 && bottomSize > 0 && isHovered; + + return ( + + + +
0 && bottomSize > 0 ? 'cursor-pointer hover:brightness-90' : '' + } ${showSplitLine ? 'border-t-4 border-t-red-500' : ''} relative`} + style={{ marginBottom: '-1px' }} + onMouseEnter={() => { + if (canSplit && splitPoint > 0 && bottomSize > 0) { + setHoveredStack(stackIndex); + setHoveredSplitPoint(splitPoint); + } + }} + onMouseLeave={() => { + setHoveredStack(null); + setHoveredSplitPoint(null); + }} + onClick={() => { + if (canSplit && splitPoint > 0 && bottomSize > 0) { + handleStackClick(stackIndex, splitPoint); + } + }} + /> + + {canSplit && pointsGained > 0 && ( + +

Split into {splitPoint} + {bottomSize} = {pointsGained} points

+
+ )} + + + ); + })}
Size: {size}
@@ -189,7 +190,7 @@ const StackingBlocks: React.FC = ({ showSocialShare = false ) : ( <>
- Click on any stack with more than 1 block to split it + Hover over a stack to see where it will split, then click to execute
@@ -202,62 +203,6 @@ const StackingBlocks: React.FC = ({ showSocialShare = false - - - - Split Stack - -
- {selectedStack !== null && ( - <> -
- Splitting stack of size {stacks[selectedStack]} into two stacks: -
-
-
- - handleSplit1Change(e.target.value)} - /> -
-
- - -
-
- {splitSize1 && splitSize2 && ( -
- Points gained: {parseInt(splitSize1) * parseInt(splitSize2)} -
- )} -
- - -
- - )} -
-
-
{showSocialShare && (