203 lines
7.8 KiB
React
203 lines
7.8 KiB
React
import React from "react"
|
||
import { motion, AnimatePresence } from "framer-motion"
|
||
|
||
/**
|
||
* ConsequenceModal - Következmények megjelenítése (jó/rossz válasz után)
|
||
*
|
||
* @param {Object} props
|
||
* @param {boolean} props.isOpen - Modal megjelenítése
|
||
* @param {Function} props.onClose - Modal bezárása
|
||
* @param {boolean} props.isCorrect - Helyes volt-e a válasz
|
||
* @param {string} props.consequence - Következmény szövege
|
||
* @param {number} props.consequenceType - Következmény típusa:
|
||
* 0 = MOVE_FORWARD (előre lépés)
|
||
* 1 = MOVE_BACKWARD (hátra lépés)
|
||
* 2 = LOSE_TURN (körkihagyás)
|
||
* 3 = EXTRA_TURN (extra kör)
|
||
* 5 = GO_TO_START (vissza a starthoz)
|
||
* @param {number} props.consequenceValue - Következmény értéke (hány mező/kör)
|
||
* @param {string} props.playerAnswer - Játékos válasza
|
||
* @param {string} props.correctAnswer - Helyes válasz
|
||
* @param {string} props.explanation - Magyarázat
|
||
*/
|
||
const ConsequenceModal = ({
|
||
isOpen,
|
||
onClose,
|
||
isCorrect,
|
||
consequence,
|
||
consequenceType,
|
||
consequenceValue,
|
||
playerAnswer,
|
||
correctAnswer,
|
||
explanation
|
||
}) => {
|
||
|
||
const getConsequenceIcon = (type) => {
|
||
switch(type) {
|
||
case 0: return "🚀" // MOVE_FORWARD
|
||
case 1: return "⬅️" // MOVE_BACKWARD
|
||
case 2: return "😴" // LOSE_TURN
|
||
case 3: return "🎉" // EXTRA_TURN
|
||
case 5: return "🏁" // GO_TO_START
|
||
default: return "📢"
|
||
}
|
||
}
|
||
|
||
const getConsequenceText = (type, value) => {
|
||
switch(type) {
|
||
case 0: return `${value} mezőt léphetsz előre! 🚀`
|
||
case 1: return `${value} mezőt lépsz vissza! �`
|
||
case 2: return `${value} kört ki kell hagyni! �`
|
||
case 3: return `${value} extra kör jár neked! 🎉`
|
||
case 5: return "Vissza a starthoz! 🏁"
|
||
default: return consequence || "Következmény"
|
||
}
|
||
}
|
||
|
||
const getBgGradient = () => {
|
||
if (isCorrect) {
|
||
return "from-green-600 via-teal-600 to-green-600"
|
||
}
|
||
return "from-red-600 via-orange-600 to-red-600"
|
||
}
|
||
|
||
const getBorderColor = () => {
|
||
if (isCorrect) return "border-green-500/50"
|
||
return "border-red-500/50"
|
||
}
|
||
|
||
if (!isOpen) 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"
|
||
onClick={onClose}
|
||
/>
|
||
|
||
{/* Modal Content */}
|
||
<motion.div
|
||
initial={{ scale: 0.5, opacity: 0, rotate: -10 }}
|
||
animate={{ scale: 1, opacity: 1, rotate: 0 }}
|
||
exit={{ scale: 0.5, opacity: 0, rotate: 10 }}
|
||
transition={{ type: "spring", duration: 0.6 }}
|
||
className={`relative bg-gradient-to-br from-gray-900 via-gray-800 to-gray-900 rounded-2xl shadow-2xl border-2 ${getBorderColor()} max-w-2xl w-full overflow-hidden`}
|
||
>
|
||
{/* Header with result */}
|
||
<div className={`bg-gradient-to-r ${getBgGradient()} p-6 relative overflow-hidden`}>
|
||
<div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/20 to-transparent animate-pulse" />
|
||
|
||
<div className="relative text-center">
|
||
<motion.div
|
||
initial={{ scale: 0 }}
|
||
animate={{ scale: 1 }}
|
||
transition={{ delay: 0.2, type: "spring" }}
|
||
className="text-8xl mb-2"
|
||
>
|
||
{isCorrect ? "✅" : "❌"}
|
||
</motion.div>
|
||
<h2 className="text-3xl font-bold text-white mb-2">
|
||
{isCorrect ? "Helyes válasz!" : "Helytelen válasz!"}
|
||
</h2>
|
||
<p className="text-white/90 text-lg">
|
||
{isCorrect ? "Gratulálunk! 🎉" : "Ne add fel! 💪"}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Content */}
|
||
<div className="p-6 space-y-6">
|
||
{/* Player Answer */}
|
||
{playerAnswer && (
|
||
<div className="bg-gray-800/50 rounded-xl p-4 border border-gray-700">
|
||
<div className="flex items-start gap-3">
|
||
<div className="text-2xl">💭</div>
|
||
<div className="flex-1">
|
||
<p className="text-gray-400 text-sm mb-1">A te válaszod:</p>
|
||
<p className="text-white font-semibold">{playerAnswer}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Correct Answer - ha helytelen volt */}
|
||
{!isCorrect && correctAnswer && (
|
||
<div className="bg-green-900/20 rounded-xl p-4 border border-green-500/30">
|
||
<div className="flex items-start gap-3">
|
||
<div className="text-2xl">✔️</div>
|
||
<div className="flex-1">
|
||
<p className="text-green-300 text-sm mb-1">A helyes válasz:</p>
|
||
<p className="text-white font-semibold">{correctAnswer}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Explanation */}
|
||
{explanation && (
|
||
<div className="bg-blue-900/20 rounded-xl p-4 border border-blue-500/30">
|
||
<div className="flex items-start gap-3">
|
||
<div className="text-2xl">💡</div>
|
||
<div className="flex-1">
|
||
<p className="text-blue-300 text-sm mb-1">Magyarázat:</p>
|
||
<p className="text-gray-300">{explanation}</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* Consequence */}
|
||
<motion.div
|
||
initial={{ scale: 0.8, opacity: 0 }}
|
||
animate={{ scale: 1, opacity: 1 }}
|
||
transition={{ delay: 0.4 }}
|
||
className={`${isCorrect ? 'bg-gradient-to-br from-green-900/30 to-teal-900/30 border-green-500/40' : 'bg-gradient-to-br from-red-900/30 to-orange-900/30 border-red-500/40'} rounded-xl p-6 border-2`}
|
||
>
|
||
<div className="text-center">
|
||
<motion.div
|
||
animate={{ rotate: [0, 10, -10, 10, 0] }}
|
||
transition={{ repeat: Infinity, duration: 2 }}
|
||
className="text-6xl mb-3"
|
||
>
|
||
{getConsequenceIcon(consequenceType)}
|
||
</motion.div>
|
||
<h3 className={`text-xl font-bold mb-2 ${isCorrect ? 'text-green-300' : 'text-red-300'}`}>
|
||
Következmény:
|
||
</h3>
|
||
<p className="text-white text-2xl font-bold">
|
||
{getConsequenceText(consequenceType, consequenceValue)}
|
||
</p>
|
||
</div>
|
||
</motion.div>
|
||
|
||
{/* Close Button */}
|
||
<button
|
||
onClick={onClose}
|
||
className={`w-full bg-gradient-to-r ${
|
||
isCorrect
|
||
? 'from-green-600 to-teal-600 hover:from-green-500 hover:to-teal-500 border-green-500/50'
|
||
: 'from-red-600 to-orange-600 hover:from-red-500 hover:to-orange-500 border-red-500/50'
|
||
} text-white font-bold py-4 px-6 rounded-xl shadow-lg
|
||
transform transition-all duration-200 hover:scale-105 active:scale-95 border`}
|
||
>
|
||
<div className="flex items-center justify-center gap-2">
|
||
<span className="text-2xl">👍</span>
|
||
<span className="text-lg">Rendben, folytatom!</span>
|
||
</div>
|
||
</button>
|
||
</div>
|
||
</motion.div>
|
||
</div>
|
||
)}
|
||
</AnimatePresence>
|
||
)
|
||
}
|
||
|
||
export default ConsequenceModal
|