Donat nezd majd át mert a backenden is lett valtozas nem tudom pontosan hogy kell e vagy sem Köszi
This commit is contained in:
@@ -0,0 +1,280 @@
|
||||
import React, { useState, useEffect } from "react"
|
||||
import { motion, AnimatePresence } from "framer-motion"
|
||||
|
||||
/**
|
||||
* CardDisplayModal - Kártya megjelenítése a játékos számára
|
||||
*
|
||||
* @param {Object} props
|
||||
* @param {boolean} props.isOpen - Modal megjelenítése
|
||||
* @param {Function} props.onClose - Modal bezárása
|
||||
* @param {Object} props.card - Kártya adatok
|
||||
* @param {string} props.cardType - Kártya típusa (QUESTION, LUCK, JOKER)
|
||||
* @param {Function} props.onSubmitAnswer - Válasz beküldése (csak QUESTION típusnál)
|
||||
* @param {number} props.timeLimit - Időkorlát másodpercben (default: 60)
|
||||
*/
|
||||
const CardDisplayModal = ({
|
||||
isOpen,
|
||||
onClose,
|
||||
card,
|
||||
cardType = "QUESTION",
|
||||
onSubmitAnswer,
|
||||
timeLimit = 60
|
||||
}) => {
|
||||
const [playerAnswer, setPlayerAnswer] = useState("")
|
||||
const [selectedOption, setSelectedOption] = useState(null)
|
||||
const [timeLeft, setTimeLeft] = useState(timeLimit)
|
||||
const [isProcessing, setIsProcessing] = useState(false)
|
||||
|
||||
// Timer countdown
|
||||
useEffect(() => {
|
||||
if (!isOpen || cardType !== "QUESTION") return
|
||||
|
||||
setTimeLeft(timeLimit)
|
||||
const timer = setInterval(() => {
|
||||
setTimeLeft(prev => {
|
||||
if (prev <= 1) {
|
||||
clearInterval(timer)
|
||||
handleTimeout()
|
||||
return 0
|
||||
}
|
||||
return prev - 1
|
||||
})
|
||||
}, 1000)
|
||||
|
||||
return () => clearInterval(timer)
|
||||
}, [isOpen, timeLimit])
|
||||
|
||||
// Reset state when modal opens
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
setPlayerAnswer("")
|
||||
setSelectedOption(null)
|
||||
setIsProcessing(false)
|
||||
}
|
||||
}, [isOpen])
|
||||
|
||||
const handleTimeout = () => {
|
||||
if (onSubmitAnswer) {
|
||||
onSubmitAnswer(null) // null = timeout
|
||||
}
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (isProcessing) return
|
||||
|
||||
let answer = null
|
||||
|
||||
// Quiz típus - A, B, C, D
|
||||
if (card?.type === 0 || card?.answerOptions) {
|
||||
answer = selectedOption
|
||||
}
|
||||
// Szöveges válasz
|
||||
else {
|
||||
answer = playerAnswer.trim()
|
||||
}
|
||||
|
||||
if (!answer) return
|
||||
|
||||
setIsProcessing(true)
|
||||
|
||||
try {
|
||||
await onSubmitAnswer(answer)
|
||||
} catch (error) {
|
||||
console.error("Válasz küldési hiba:", error)
|
||||
}
|
||||
}
|
||||
|
||||
const getCardIcon = () => {
|
||||
switch (cardType) {
|
||||
case "QUESTION": return "❓"
|
||||
case "LUCK": return "🍀"
|
||||
case "JOKER": return "🃏"
|
||||
default: return "📝"
|
||||
}
|
||||
}
|
||||
|
||||
const getCardTitle = () => {
|
||||
switch (cardType) {
|
||||
case "QUESTION": return "Feladat Kártya"
|
||||
case "LUCK": return "Szerencse Kártya"
|
||||
case "JOKER": return "Joker Kártya"
|
||||
default: return "Kártya"
|
||||
}
|
||||
}
|
||||
|
||||
const getCardBgGradient = () => {
|
||||
switch (cardType) {
|
||||
case "QUESTION": return "from-blue-600 via-purple-600 to-blue-600"
|
||||
case "LUCK": return "from-green-600 via-teal-600 to-green-600"
|
||||
case "JOKER": return "from-purple-600 via-pink-600 to-purple-600"
|
||||
default: return "from-gray-600 via-gray-700 to-gray-600"
|
||||
}
|
||||
}
|
||||
|
||||
const formatTime = (seconds) => {
|
||||
const mins = Math.floor(seconds / 60)
|
||||
const secs = seconds % 60
|
||||
return `${mins}:${secs.toString().padStart(2, '0')}`
|
||||
}
|
||||
|
||||
const getTimeColor = () => {
|
||||
if (timeLeft > 30) return "text-green-400"
|
||||
if (timeLeft > 10) return "text-yellow-400"
|
||||
return "text-red-400 animate-pulse"
|
||||
}
|
||||
|
||||
if (!isOpen || !card) return null
|
||||
|
||||
return (
|
||||
<AnimatePresence>
|
||||
{isOpen && (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
|
||||
{/* Backdrop */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="absolute inset-0 bg-black/80 backdrop-blur-sm"
|
||||
/>
|
||||
|
||||
{/* Modal Content */}
|
||||
<motion.div
|
||||
initial={{ scale: 0.9, opacity: 0, y: 20 }}
|
||||
animate={{ scale: 1, opacity: 1, y: 0 }}
|
||||
exit={{ scale: 0.9, opacity: 0, y: 20 }}
|
||||
transition={{ type: "spring", duration: 0.5 }}
|
||||
className="relative bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 rounded-2xl shadow-2xl border-2 border-purple-500/30 max-w-2xl w-full overflow-hidden"
|
||||
>
|
||||
{/* Header */}
|
||||
<div className={`bg-gradient-to-r ${getCardBgGradient()} p-6 relative overflow-hidden`}>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/10 to-transparent animate-pulse" />
|
||||
<div className="relative flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="text-5xl animate-bounce">{getCardIcon()}</div>
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-white">{getCardTitle()}</h2>
|
||||
{cardType === "QUESTION" && (
|
||||
<p className="text-white/80 text-sm">Válaszolj a kérdésre!</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Timer - csak QUESTION típusnál */}
|
||||
{cardType === "QUESTION" && (
|
||||
<div className="bg-black/30 rounded-lg px-4 py-2">
|
||||
<div className={`text-2xl font-bold ${getTimeColor()}`}>
|
||||
⏱️ {formatTime(timeLeft)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="p-6 space-y-6">
|
||||
{/* Question/Text */}
|
||||
<div className="bg-gray-800/50 rounded-xl p-5 border border-gray-700">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="text-3xl">📝</div>
|
||||
<div className="flex-1">
|
||||
<p className="text-white text-lg leading-relaxed">
|
||||
{card.question || card.text || card.statement}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Answer Options - Quiz típus (type: 0) */}
|
||||
{cardType === "QUESTION" && (card.type === 0 || card.answerOptions) && (
|
||||
<div className="space-y-3">
|
||||
<h3 className="text-purple-300 font-semibold">Válaszd ki a helyes választ:</h3>
|
||||
{card.answerOptions?.map((option, index) => (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => setSelectedOption(option.answer)}
|
||||
disabled={isProcessing}
|
||||
className={`w-full text-left p-4 rounded-lg border-2 transition-all ${
|
||||
selectedOption === option.answer
|
||||
? "bg-purple-600 border-purple-400 text-white"
|
||||
: "bg-gray-800 border-gray-600 text-gray-300 hover:border-purple-500"
|
||||
} ${isProcessing ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}`}
|
||||
>
|
||||
<span className="font-bold">{option.answer})</span> {option.text}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Text Input - egyéb kérdés típusok */}
|
||||
{cardType === "QUESTION" && card.type !== 0 && !card.answerOptions && (
|
||||
<div className="space-y-3">
|
||||
<h3 className="text-purple-300 font-semibold">Írd be a választ:</h3>
|
||||
<input
|
||||
type="text"
|
||||
value={playerAnswer}
|
||||
onChange={(e) => setPlayerAnswer(e.target.value)}
|
||||
onKeyPress={(e) => e.key === 'Enter' && handleSubmit()}
|
||||
disabled={isProcessing}
|
||||
placeholder="Válaszod..."
|
||||
className="w-full bg-gray-800 border-2 border-gray-600 rounded-lg px-4 py-3 text-white focus:border-purple-500 focus:outline-none disabled:opacity-50"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Hint (if available) */}
|
||||
{card.hint && (
|
||||
<div className="bg-yellow-900/20 rounded-xl p-4 border border-yellow-500/30">
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="text-2xl">💡</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-yellow-300 font-semibold mb-2">Segítség</h3>
|
||||
<p className="text-gray-300 text-sm">{card.hint}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Submit Button - csak QUESTION típusnál */}
|
||||
{cardType === "QUESTION" && (
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
disabled={isProcessing || (!playerAnswer && !selectedOption)}
|
||||
className="w-full bg-gradient-to-r from-purple-600 to-blue-600 hover:from-purple-500 hover:to-blue-500
|
||||
text-white font-bold py-4 px-6 rounded-xl shadow-lg
|
||||
transform transition-all duration-200 hover:scale-105 active:scale-95
|
||||
disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100
|
||||
border border-purple-500/50"
|
||||
>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<span className="text-2xl">✅</span>
|
||||
<span className="text-lg">
|
||||
{isProcessing ? "Feldolgozás..." : "Válasz beküldése"}
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Close Button - LUCK és JOKER típusnál */}
|
||||
{(cardType === "LUCK" || cardType === "JOKER") && (
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="w-full bg-gradient-to-r from-green-600 to-teal-600 hover:from-green-500 hover:to-teal-500
|
||||
text-white font-bold py-4 px-6 rounded-xl shadow-lg
|
||||
transform transition-all duration-200 hover:scale-105 active:scale-95
|
||||
border border-green-500/50"
|
||||
>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<span className="text-2xl">👍</span>
|
||||
<span className="text-lg">Rendben</span>
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
)
|
||||
}
|
||||
|
||||
export default CardDisplayModal
|
||||
Reference in New Issue
Block a user