lukcy-draw/src/components/WinnerModal.jsx
2025-12-12 09:15:19 +07:00

229 lines
11 KiB
JavaScript

import { motion, AnimatePresence } from 'framer-motion';
import { createPortal } from 'react-dom';
import { Trophy, Star } from 'lucide-react';
export function WinnerModal({ isOpen, winner, onConfirm }) {
if (!isOpen) return null;
return createPortal(
<AnimatePresence>
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-50 flex items-center justify-center p-4"
style={{
background: 'rgba(0, 0, 0, 0.92)',
backdropFilter: 'blur(8px)'
}}
onClick={onConfirm}
>
{/* Floating particles animation */}
<div className="absolute inset-0 overflow-hidden pointer-events-none">
{[...Array(20)].map((_, i) => (
<motion.div
key={i}
className="absolute"
initial={{
x: Math.random() * window.innerWidth,
y: window.innerHeight + 100,
opacity: 0
}}
animate={{
y: -100,
opacity: [0, 1, 0],
scale: [0, 1, 0]
}}
transition={{
duration: 3 + Math.random() * 2,
repeat: Infinity,
delay: Math.random() * 3,
ease: "easeOut"
}}
>
<Star size={20} fill="#D4AF37" color="#D4AF37" />
</motion.div>
))}
</div>
<motion.div
initial={{ scale: 0.5, opacity: 0, rotateY: -180 }}
animate={{ scale: 1, opacity: 1, rotateY: 0 }}
exit={{ scale: 0.5, opacity: 0, rotateY: 180 }}
transition={{
type: 'spring',
duration: 0.8,
bounce: 0.3
}}
className="relative max-w-2xl w-full overflow-hidden rounded-[2rem] shadow-2xl"
style={{
background: 'linear-gradient(135deg, rgba(0, 0, 0, 0.95) 0%, rgba(20, 20, 20, 0.9) 100%)',
backdropFilter: 'blur(20px)',
}}
onClick={(e) => e.stopPropagation()}
>
{/* Metallic border */}
<div className="absolute inset-0 rounded-[2rem] pointer-events-none" style={{
background: 'linear-gradient(135deg, #bf953f 0%, #fcf6ba 25%, #b38728 50%, #fbf5b7 75%, #aa771c 100%)',
padding: '4px',
WebkitMask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
WebkitMaskComposite: 'xor',
maskComposite: 'exclude',
}}></div>
{/* Glow effect */}
<div className="absolute inset-0 rounded-[2rem] pointer-events-none" style={{
boxShadow: '0 0 80px rgba(212, 175, 55, 0.5), inset 0 0 80px rgba(212, 175, 55, 0.1)'
}}></div>
<div className="relative z-10 p-8 md:p-12 lg:p-16">
{/* Animated Trophy Icon */}
<motion.div
className="flex justify-center mb-8"
animate={{
rotate: [0, -10, 10, -10, 10, 0],
scale: [1, 1.1, 1]
}}
transition={{
duration: 2,
repeat: Infinity,
repeatDelay: 1
}}
>
<div
className="relative w-28 h-28 md:w-32 md:h-32 rounded-full flex items-center justify-center"
style={{
background: 'linear-gradient(135deg, #bf953f 0%, #fcf6ba 50%, #b38728 100%)',
boxShadow: '0 8px 40px rgba(212, 175, 55, 0.6), inset 0 2px 4px rgba(255, 255, 255, 0.3)'
}}
>
<Trophy size={60} color="#FFFFFF" strokeWidth={2.5} />
{/* Sparkle effect */}
<motion.div
className="absolute top-0 right-0"
animate={{
scale: [0, 1, 0],
rotate: [0, 180, 360]
}}
transition={{
duration: 2,
repeat: Infinity,
repeatDelay: 0.5
}}
>
<Star size={24} fill="#FFE87C" color="#FFE87C" />
</motion.div>
</div>
</motion.div>
{/* Title with shimmer effect */}
<motion.h2
className="text-4xl md:text-5xl lg:text-6xl font-black text-center mb-6 relative"
initial={{ y: -20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ delay: 0.3 }}
>
<span style={{
background: 'linear-gradient(to bottom, #bf953f 0%, #fcf6ba 40%, #b38728 55%, #fbf5b7 100%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
filter: 'drop-shadow(0 4px 12px rgba(212, 175, 55, 0.8))',
}}>
WINNER!
</span>
</motion.h2>
{/* Subtitle */}
<motion.p
className="text-center text-white/70 text-xl md:text-2xl mb-10 font-medium"
initial={{ y: -10, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ delay: 0.4 }}
>
The winning number is
</motion.p>
{/* Winner Number with luxury card */}
<motion.div
initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ delay: 0.5, type: 'spring' }}
className="relative mb-12 p-8 md:p-10 rounded-3xl overflow-hidden"
style={{
background: 'linear-gradient(135deg, rgba(191, 149, 63, 0.15) 0%, rgba(179, 135, 40, 0.1) 100%)',
border: '3px solid rgba(212, 175, 55, 0.5)',
boxShadow: '0 8px 40px rgba(212, 175, 55, 0.3), inset 0 2px 4px rgba(255, 255, 255, 0.1)'
}}
>
{/* Animated shimmer overlay */}
<motion.div
className="absolute inset-0 pointer-events-none"
style={{
background: 'linear-gradient(90deg, transparent 0%, rgba(252, 246, 186, 0.3) 50%, transparent 100%)',
}}
animate={{
x: ['-100%', '200%']
}}
transition={{
duration: 3,
repeat: Infinity,
ease: 'linear'
}}
></motion.div>
<div
className="text-center text-8xl md:text-9xl font-black tabular-nums relative z-10"
style={{
background: 'linear-gradient(to bottom, #bf953f 0%, #fcf6ba 40%, #b38728 55%, #fbf5b7 100%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
filter: 'drop-shadow(0 6px 16px rgba(212, 175, 55, 0.5))',
letterSpacing: '0.1em'
}}
>
{winner !== null ? winner.toString().padStart(3, '0') : '000'}
</div>
</motion.div>
{/* OK Button with luxury styling */}
<motion.button
onClick={onConfirm}
className="w-full py-5 rounded-2xl text-2xl font-bold uppercase tracking-wider relative overflow-hidden group"
style={{
background: 'linear-gradient(135deg, #bf953f 0%, #fcf6ba 25%, #b38728 50%, #fbf5b7 75%, #aa771c 100%)',
boxShadow: '0 6px 30px rgba(212, 175, 55, 0.6)',
color: '#000000',
fontFamily: "'Inter', sans-serif",
}}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
initial={{ y: 20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ delay: 0.6 }}
>
{/* Button shimmer effect */}
<motion.div
className="absolute inset-0 pointer-events-none"
style={{
background: 'linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.6) 50%, transparent 100%)',
}}
animate={{
x: ['-100%', '200%']
}}
transition={{
duration: 2,
repeat: Infinity,
ease: 'linear'
}}
></motion.div>
<span className="relative z-10 font-black">CONTINUE</span>
</motion.button>
</div>
</motion.div>
</motion.div>
</AnimatePresence>,
document.body
);
}