Refactor Binary Search Trick interactive
- Move share elements to the bottom. - Center "How it works" button. - Add one-by-one and all-at-once modes. - Randomize card numbers on load.
This commit is contained in:
parent
27f179e517
commit
325b0dd139
1 changed files with 101 additions and 38 deletions
|
|
@ -1,8 +1,10 @@
|
||||||
import { useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Checkbox } from '@/components/ui/checkbox';
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
|
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog';
|
||||||
|
import { Switch } from '@/components/ui/switch';
|
||||||
|
import { Label } from '@/components/ui/label';
|
||||||
import { HelpCircle, RefreshCw } from 'lucide-react';
|
import { HelpCircle, RefreshCw } from 'lucide-react';
|
||||||
import SocialShare from '@/components/SocialShare';
|
import SocialShare from '@/components/SocialShare';
|
||||||
|
|
||||||
|
|
@ -14,35 +16,78 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
|
||||||
const [selectedCards, setSelectedCards] = useState<number[]>([]);
|
const [selectedCards, setSelectedCards] = useState<number[]>([]);
|
||||||
const [result, setResult] = useState<number | null>(null);
|
const [result, setResult] = useState<number | null>(null);
|
||||||
const [showResult, setShowResult] = useState(false);
|
const [showResult, setShowResult] = useState(false);
|
||||||
|
const [isOneByOne, setIsOneByOne] = useState(false);
|
||||||
|
const [visibleCards, setVisibleCards] = useState<number[]>([]);
|
||||||
|
const [cards, setCards] = useState<Array<{id: number; title: string; numbers: number[]}>>([]);
|
||||||
|
|
||||||
// Define the 5 binary cards
|
// Function to shuffle array
|
||||||
const cards = [
|
const shuffleArray = <T,>(array: T[]): T[] => {
|
||||||
{
|
const shuffled = [...array];
|
||||||
id: 16,
|
for (let i = shuffled.length - 1; i > 0; i--) {
|
||||||
title: "Card 16",
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
numbers: [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
|
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 8,
|
|
||||||
title: "Card 8",
|
|
||||||
numbers: [8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
title: "Card 4",
|
|
||||||
numbers: [4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
title: "Card 2",
|
|
||||||
numbers: [2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
title: "Card 1",
|
|
||||||
numbers: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]
|
|
||||||
}
|
}
|
||||||
];
|
return shuffled;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Generate cards with randomized numbers but maintaining binary logic
|
||||||
|
const generateCards = () => {
|
||||||
|
const baseCards = [
|
||||||
|
{
|
||||||
|
id: 16,
|
||||||
|
title: "Card 16",
|
||||||
|
numbers: [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
title: "Card 8",
|
||||||
|
numbers: [8, 9, 10, 11, 12, 13, 14, 15, 24, 25, 26, 27, 28, 29, 30, 31]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: "Card 4",
|
||||||
|
numbers: [4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: "Card 2",
|
||||||
|
numbers: [2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: "Card 1",
|
||||||
|
numbers: [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Randomize the order of numbers within each card
|
||||||
|
return baseCards.map(card => ({
|
||||||
|
...card,
|
||||||
|
numbers: shuffleArray(card.numbers)
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize cards on component mount
|
||||||
|
useEffect(() => {
|
||||||
|
setCards(generateCards());
|
||||||
|
setVisibleCards([16, 8, 4, 2, 1]); // All cards visible by default
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Handle mode toggle
|
||||||
|
const handleModeToggle = (checked: boolean) => {
|
||||||
|
setIsOneByOne(checked);
|
||||||
|
if (checked) {
|
||||||
|
// Start one-by-one mode - show first card
|
||||||
|
setVisibleCards([16]);
|
||||||
|
setTimeout(() => setVisibleCards(prev => [...prev, 8]), 500);
|
||||||
|
setTimeout(() => setVisibleCards(prev => [...prev, 4]), 1000);
|
||||||
|
setTimeout(() => setVisibleCards(prev => [...prev, 2]), 1500);
|
||||||
|
setTimeout(() => setVisibleCards(prev => [...prev, 1]), 2000);
|
||||||
|
} else {
|
||||||
|
// Show all cards immediately
|
||||||
|
setVisibleCards([16, 8, 4, 2, 1]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleCardToggle = (cardId: number) => {
|
const handleCardToggle = (cardId: number) => {
|
||||||
setSelectedCards(prev =>
|
setSelectedCards(prev =>
|
||||||
|
|
@ -72,7 +117,7 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
|
||||||
<CardTitle className="text-3xl font-bold bg-gradient-to-r from-primary to-primary/70 bg-clip-text text-transparent">
|
<CardTitle className="text-3xl font-bold bg-gradient-to-r from-primary to-primary/70 bg-clip-text text-transparent">
|
||||||
Binary Search Magic Trick
|
Binary Search Magic Trick
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
<div className="flex items-center justify-center gap-4">
|
<div className="flex justify-center mt-4">
|
||||||
<Dialog>
|
<Dialog>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button variant="outline" size="sm">
|
<Button variant="outline" size="sm">
|
||||||
|
|
@ -122,13 +167,6 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
{showSocialShare && (
|
|
||||||
<SocialShare
|
|
||||||
title="Binary Search Magic Trick"
|
|
||||||
description="Learn how binary numbers work through this amazing magic trick! Can you figure out how it works?"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
|
|
@ -136,15 +174,31 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
|
||||||
<p className="text-lg text-muted-foreground">
|
<p className="text-lg text-muted-foreground">
|
||||||
Think of a number between 1 and 31, then select all the cards that contain your number:
|
Think of a number between 1 and 31, then select all the cards that contain your number:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<div className="flex items-center justify-center gap-3 pt-4">
|
||||||
|
<Label htmlFor="mode-toggle" className="text-sm font-medium">
|
||||||
|
All at once
|
||||||
|
</Label>
|
||||||
|
<Switch
|
||||||
|
id="mode-toggle"
|
||||||
|
checked={isOneByOne}
|
||||||
|
onCheckedChange={handleModeToggle}
|
||||||
|
/>
|
||||||
|
<Label htmlFor="mode-toggle" className="text-sm font-medium">
|
||||||
|
One by one
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-4">
|
||||||
{cards.map((card) => (
|
{cards
|
||||||
|
.filter(card => visibleCards.includes(card.id))
|
||||||
|
.map((card) => (
|
||||||
<Card
|
<Card
|
||||||
key={card.id}
|
key={card.id}
|
||||||
className={`cursor-pointer transition-all duration-200 hover:shadow-lg ${
|
className={`cursor-pointer transition-all duration-500 hover:shadow-lg animate-fade-in ${
|
||||||
selectedCards.includes(card.id)
|
selectedCards.includes(card.id)
|
||||||
? 'ring-2 ring-primary bg-primary/5'
|
? 'ring-2 ring-primary bg-primary/5'
|
||||||
: 'hover:bg-muted/50'
|
: 'hover:bg-muted/50'
|
||||||
|
|
@ -210,6 +264,15 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{showSocialShare && (
|
||||||
|
<div className="flex justify-center pt-6">
|
||||||
|
<SocialShare
|
||||||
|
title="Binary Search Magic Trick"
|
||||||
|
description="Learn how binary numbers work through this amazing magic trick! Can you figure out how it works?"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue