Refactor card options
Replace checkboxes with "Present" and "Absent" options. Disable "Reveal Number" until an option is selected.
This commit is contained in:
parent
5861189703
commit
eb15a2d5ac
1 changed files with 65 additions and 46 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
import { useState, useEffect } 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 { 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 { Switch } from '@/components/ui/switch';
|
||||||
import { Label } from '@/components/ui/label';
|
import { Label } from '@/components/ui/label';
|
||||||
|
|
@ -13,7 +12,7 @@ interface BinarySearchTrickProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) => {
|
const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) => {
|
||||||
const [selectedCards, setSelectedCards] = useState<number[]>([]);
|
const [cardStates, setCardStates] = useState<Record<number, 'unselected' | 'present' | 'absent'>>({});
|
||||||
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 [isOneByOne, setIsOneByOne] = useState(false);
|
||||||
|
|
@ -76,7 +75,7 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
|
||||||
const handleModeToggle = (checked: boolean) => {
|
const handleModeToggle = (checked: boolean) => {
|
||||||
setIsOneByOne(checked);
|
setIsOneByOne(checked);
|
||||||
setCurrentCardIndex(0);
|
setCurrentCardIndex(0);
|
||||||
setSelectedCards([]);
|
setCardStates({});
|
||||||
setShowResult(false);
|
setShowResult(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -89,29 +88,33 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
|
||||||
setCurrentCardIndex(prev => Math.min(cards.length - 1, prev + 1));
|
setCurrentCardIndex(prev => Math.min(cards.length - 1, prev + 1));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCardToggle = (cardId: number) => {
|
const handleCardSelection = (cardId: number, state: 'present' | 'absent') => {
|
||||||
setSelectedCards(prev =>
|
setCardStates(prev => ({
|
||||||
prev.includes(cardId)
|
...prev,
|
||||||
? prev.filter(id => id !== cardId)
|
[cardId]: state
|
||||||
: [...prev, cardId]
|
}));
|
||||||
);
|
|
||||||
setShowResult(false);
|
setShowResult(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateResult = () => {
|
const calculateResult = () => {
|
||||||
const sum = selectedCards.reduce((acc, cardId) => acc + cardId, 0);
|
const sum = Object.entries(cardStates)
|
||||||
|
.filter(([_, state]) => state === 'present')
|
||||||
|
.reduce((acc, [cardId, _]) => acc + parseInt(cardId), 0);
|
||||||
setResult(sum);
|
setResult(sum);
|
||||||
setShowResult(true);
|
setShowResult(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
setSelectedCards([]);
|
setCardStates({});
|
||||||
setResult(null);
|
setResult(null);
|
||||||
setShowResult(false);
|
setShowResult(false);
|
||||||
setCurrentCardIndex(0);
|
setCurrentCardIndex(0);
|
||||||
setCards(generateCards()); // Regenerate with new randomized order
|
setCards(generateCards()); // Regenerate with new randomized order
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check if at least one card has been selected (present or absent)
|
||||||
|
const hasAnySelection = Object.values(cardStates).some(state => state !== 'unselected');
|
||||||
|
|
||||||
// Get cards to display based on mode
|
// Get cards to display based on mode
|
||||||
const getDisplayCards = () => {
|
const getDisplayCards = () => {
|
||||||
if (isOneByOne) {
|
if (isOneByOne) {
|
||||||
|
|
@ -232,48 +235,64 @@ const BinarySearchTrick = ({ showSocialShare = true }: BinarySearchTrickProps) =
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className={`grid gap-4 ${isOneByOne ? 'grid-cols-1 justify-items-center' : 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5'}`}>
|
<div className={`grid gap-4 ${isOneByOne ? 'grid-cols-1 justify-items-center' : 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5'}`}>
|
||||||
{getDisplayCards().map((card) => (
|
{getDisplayCards().map((card) => {
|
||||||
<Card
|
const cardState = cardStates[card.id] || 'unselected';
|
||||||
key={card.id}
|
return (
|
||||||
className={`cursor-pointer transition-all duration-500 hover:shadow-lg animate-fade-in ${
|
<Card
|
||||||
selectedCards.includes(card.id)
|
key={card.id}
|
||||||
? 'ring-2 ring-primary bg-primary/5'
|
className={`transition-all duration-500 hover:shadow-lg animate-fade-in ${
|
||||||
: 'hover:bg-muted/50'
|
cardState === 'present'
|
||||||
} ${isOneByOne ? 'max-w-md w-full' : ''}`}
|
? 'ring-2 ring-green-500 bg-green-50'
|
||||||
onClick={() => handleCardToggle(card.id)}
|
: cardState === 'absent'
|
||||||
>
|
? 'ring-2 ring-red-500 bg-red-50'
|
||||||
<CardHeader className={`${isOneByOne ? 'pb-4' : 'pb-2'}`}>
|
: 'hover:bg-muted/50'
|
||||||
<div className="flex items-center justify-between">
|
} ${isOneByOne ? 'max-w-md w-full' : ''}`}
|
||||||
<CardTitle className={`font-bold text-primary ${isOneByOne ? 'text-3xl' : 'text-xl'}`}>
|
>
|
||||||
{card.id}
|
<CardHeader className={`${isOneByOne ? 'pb-4' : 'pb-2'}`}>
|
||||||
</CardTitle>
|
<div className="flex items-center justify-between">
|
||||||
<Checkbox
|
<CardTitle className={`font-bold text-primary ${isOneByOne ? 'text-3xl' : 'text-xl'}`}>
|
||||||
checked={selectedCards.includes(card.id)}
|
{card.id}
|
||||||
onChange={() => {}} // Controlled by card click
|
</CardTitle>
|
||||||
/>
|
<div className="flex gap-2">
|
||||||
</div>
|
<Button
|
||||||
</CardHeader>
|
size="sm"
|
||||||
<CardContent>
|
variant={cardState === 'present' ? 'default' : 'outline'}
|
||||||
<div className={`grid grid-cols-4 gap-1 ${isOneByOne ? 'text-lg gap-2' : 'text-sm'}`}>
|
onClick={() => handleCardSelection(card.id, 'present')}
|
||||||
{card.numbers.map((num) => (
|
>
|
||||||
<div
|
Present
|
||||||
key={num}
|
</Button>
|
||||||
className={`text-center bg-muted/30 rounded border ${isOneByOne ? 'p-3' : 'p-1'}`}
|
<Button
|
||||||
>
|
size="sm"
|
||||||
{num}
|
variant={cardState === 'absent' ? 'destructive' : 'outline'}
|
||||||
|
onClick={() => handleCardSelection(card.id, 'absent')}
|
||||||
|
>
|
||||||
|
Absent
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
))}
|
</div>
|
||||||
</div>
|
</CardHeader>
|
||||||
</CardContent>
|
<CardContent>
|
||||||
</Card>
|
<div className={`grid grid-cols-4 gap-1 ${isOneByOne ? 'text-lg gap-2' : 'text-sm'}`}>
|
||||||
))}
|
{card.numbers.map((num) => (
|
||||||
|
<div
|
||||||
|
key={num}
|
||||||
|
className={`text-center bg-muted/30 rounded border ${isOneByOne ? 'p-3' : 'p-1'}`}
|
||||||
|
>
|
||||||
|
{num}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<Button
|
<Button
|
||||||
onClick={calculateResult}
|
onClick={calculateResult}
|
||||||
disabled={selectedCards.length === 0}
|
disabled={!hasAnySelection}
|
||||||
size="lg"
|
size="lg"
|
||||||
className="min-w-32"
|
className="min-w-32"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue