Hamdast1/src/app/components/RewardModal.tsx
2026-05-20 12:31:48 +03:30

276 lines
11 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { motion, AnimatePresence } from "motion/react";
import { useMemo } from "react";
import { Sparkles, Gift, Check } from "lucide-react";
interface RewardModalProps {
isOpen: boolean;
onClose: () => void;
topicTitle: string;
}
interface FloatingParticle {
id: number;
x: number;
duration: number;
delay: number;
color: string;
}
export function RewardModal({ isOpen, onClose, topicTitle }: RewardModalProps) {
const floatingParticles = useMemo<FloatingParticle[]>(() => {
const viewportWidth =
typeof window !== "undefined" ? window.innerWidth : 390;
return Array.from({ length: 20 }, (_, i) => ({
id: i,
x: Math.random() * viewportWidth,
duration: 3 + Math.random() * 2,
delay: Math.random() * 2,
color: i % 2 === 0 ? "#FFB800" : "#8ACEE0",
}));
}, []);
return (
<AnimatePresence>
{isOpen && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-[100] flex items-center justify-center p-4"
onClick={onClose}
>
{/* Backdrop */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="absolute inset-0"
style={{
background: "radial-gradient(circle at center, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.95) 100%)",
backdropFilter: "blur(8px)",
}}
/>
{/* Modal Content */}
<motion.div
initial={{ scale: 0.5, opacity: 0, y: 50 }}
animate={{ scale: 1, opacity: 1, y: 0 }}
exit={{ scale: 0.8, opacity: 0, y: 30 }}
transition={{ type: "spring", stiffness: 300, damping: 25 }}
onClick={(e) => e.stopPropagation()}
className="relative max-w-sm w-full"
dir="rtl"
>
{/* Sparkle effects around the card */}
{Array.from({ length: 12 }).map((_, i) => (
<motion.div
key={i}
initial={{ opacity: 0, scale: 0 }}
animate={{
opacity: [0, 1, 0],
scale: [0, 1.5, 0],
x: [0, Math.cos((i / 12) * 2 * Math.PI) * 100],
y: [0, Math.sin((i / 12) * 2 * Math.PI) * 100],
}}
transition={{
duration: 2,
delay: i * 0.1,
repeat: Infinity,
repeatDelay: 1,
}}
className="absolute top-1/2 left-1/2 w-2 h-2 rounded-full"
style={{
background: "radial-gradient(circle, rgba(255, 215, 0, 1) 0%, rgba(255, 165, 0, 0.8) 100%)",
boxShadow: "0 0 10px rgba(255, 215, 0, 0.8)",
}}
/>
))}
{/* Main Card */}
<div
className="relative overflow-hidden rounded-3xl p-8"
style={{
background: "linear-gradient(135deg, rgba(30, 60, 90, 0.95) 0%, rgba(20, 40, 70, 0.98) 100%)",
border: "3px solid rgba(138, 206, 224, 0.6)",
boxShadow: "0 20px 60px rgba(0, 0, 0, 0.6), 0 0 40px rgba(138, 206, 224, 0.3), inset 0 2px 10px rgba(138, 206, 224, 0.2)",
}}
>
{/* Animated background gradient */}
<motion.div
animate={{
background: [
"radial-gradient(circle at 20% 20%, rgba(138, 206, 224, 0.15) 0%, transparent 50%)",
"radial-gradient(circle at 80% 80%, rgba(138, 206, 224, 0.15) 0%, transparent 50%)",
"radial-gradient(circle at 20% 20%, rgba(138, 206, 224, 0.15) 0%, transparent 50%)",
],
}}
transition={{ duration: 4, repeat: Infinity }}
className="absolute inset-0 pointer-events-none"
/>
{/* Success Icon */}
<div className="flex justify-center mb-4">
<motion.div
initial={{ scale: 0, rotate: -180 }}
animate={{ scale: 1, rotate: 0 }}
transition={{ delay: 0.2, type: "spring", stiffness: 200 }}
className="relative"
>
<div
className="w-20 h-20 rounded-full flex items-center justify-center"
style={{
background: "linear-gradient(135deg, #4ade80 0%, #22c55e 100%)",
boxShadow: "0 10px 30px rgba(34, 197, 94, 0.5), inset 0 2px 10px rgba(255, 255, 255, 0.3)",
}}
>
<Check className="w-10 h-10 text-white" strokeWidth={3} />
</div>
{/* Glow effect */}
<motion.div
animate={{ scale: [1, 1.3, 1], opacity: [0.5, 0, 0.5] }}
transition={{ duration: 2, repeat: Infinity }}
className="absolute inset-0 rounded-full"
style={{
background: "radial-gradient(circle, rgba(74, 222, 128, 0.6) 0%, transparent 70%)",
}}
/>
</motion.div>
</div>
{/* Title */}
<motion.h2
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
className="text-2xl font-black text-center mb-3"
style={{
color: "#8ACEE0",
textShadow: "0 2px 10px rgba(138, 206, 224, 0.5), 0 0 20px rgba(138, 206, 224, 0.3)",
}}
>
🎉 تبریک! 🎉
</motion.h2>
{/* Description */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.5 }}
className="space-y-3 mb-6"
>
<p className="text-white text-center text-base leading-relaxed font-bold">
چالش با موفقیت به پایان رسید!
</p>
<p className="text-white/80 text-center text-sm leading-relaxed">
پست شما بعد از بررسی منتشر میشود
</p>
</motion.div>
{/* Reward Section */}
<motion.div
initial={{ scale: 0, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ delay: 0.7, type: "spring", stiffness: 150 }}
className="relative mb-6"
>
<div
className="relative overflow-hidden rounded-2xl p-6"
style={{
background: "linear-gradient(135deg, rgba(255, 184, 0, 0.2) 0%, rgba(255, 140, 0, 0.15) 100%)",
border: "2px solid rgba(255, 184, 0, 0.5)",
boxShadow: "0 10px 30px rgba(255, 165, 0, 0.3), inset 0 2px 8px rgba(255, 255, 255, 0.2)",
}}
>
{/* Animated shine effect */}
<motion.div
animate={{
x: ["-100%", "200%"],
}}
transition={{
duration: 2,
repeat: Infinity,
repeatDelay: 1,
}}
className="absolute inset-0"
style={{
background: "linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.3) 50%, transparent 100%)",
}}
/>
<div className="flex items-center justify-center gap-3 mb-2">
<motion.div
animate={{ rotate: [0, 10, -10, 0] }}
transition={{ duration: 1, repeat: Infinity, repeatDelay: 1 }}
>
<Gift className="w-8 h-8" style={{ color: "#FFB800" }} />
</motion.div>
<h3 className="text-xl font-black" style={{ color: "#FFB800", textShadow: "0 2px 10px rgba(255, 184, 0, 0.5)" }}>
جایزه دریافت شد!
</h3>
<motion.div
animate={{ rotate: [0, -10, 10, 0] }}
transition={{ duration: 1, repeat: Infinity, repeatDelay: 1, delay: 0.2 }}
>
<Sparkles className="w-7 h-7" style={{ color: "#FFB800" }} />
</motion.div>
</div>
<p className="text-white text-center text-base font-bold leading-relaxed">
مدال <span style={{ color: "#FFB800" }}>{topicTitle}</span> به کیف جادوییت اضافه شد!
</p>
</div>
</motion.div>
{/* Close Button */}
<motion.button
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.9 }}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
onClick={onClose}
className="w-full py-4 rounded-full font-black text-lg"
style={{
background: "linear-gradient(180deg, #8ACEE0 0%, #5A9FB0 100%)",
boxShadow: "0 6px 20px rgba(138, 206, 224, 0.4), inset 0 2px 4px rgba(255, 255, 255, 0.3)",
color: "#0a1f2e",
textShadow: "0 1px 0 rgba(255, 255, 255, 0.3)",
}}
>
باشه، بریم!
</motion.button>
</div>
</motion.div>
{/* Floating particles in background */}
{floatingParticles.map((particle) => (
<motion.div
key={`particle-${particle.id}`}
initial={{
x: particle.x,
y: window.innerHeight + 20,
opacity: 0,
}}
animate={{
y: -20,
opacity: [0, 1, 0],
}}
transition={{
duration: particle.duration,
delay: particle.delay,
repeat: Infinity,
}}
className="absolute w-1 h-1 rounded-full"
style={{
background: particle.color,
boxShadow: `0 0 6px ${particle.color}`,
}}
/>
))}
</motion.div>
)}
</AnimatePresence>
);
}