| import React from 'react'; |
| import { Activity, BarChart2, Radio, Shield, Swords, Zap } from 'lucide-react'; |
| import { motion } from 'motion/react'; |
|
|
| const workflowSteps = [ |
| { label: 'Queue', detail: '' }, |
| { label: 'Match', detail: '' }, |
| { label: 'Solve', detail: '' }, |
| { label: 'Rank', detail: '' }, |
| ]; |
|
|
| export default function ArenaHubSection({ onEnterArena }: { onEnterArena: () => void }) { |
| return ( |
| <div className="relative w-full max-w-6xl mx-auto space-y-6"> |
| <motion.div |
| initial={{ opacity: 0, y: 28 }} |
| animate={{ opacity: 1, y: 0 }} |
| transition={{ duration: 0.55, ease: 'easeOut' }} |
| className="relative overflow-hidden rounded-[8px] border border-white/10 bg-[linear-gradient(135deg,#071117,#12141a_48%,#171018)] p-6 md:p-10 shadow-2xl" |
| > |
| <div className="absolute inset-0 opacity-[0.16] [background-image:linear-gradient(rgba(34,211,238,0.22)_1px,transparent_1px),linear-gradient(90deg,rgba(251,113,133,0.18)_1px,transparent_1px)] [background-size:46px_46px]" /> |
| <motion.div |
| className="absolute inset-y-0 -left-20 w-32 bg-[linear-gradient(90deg,transparent,rgba(34,211,238,0.14),transparent)]" |
| animate={{ x: ['0%', '900%'] }} |
| transition={{ duration: 7, repeat: Infinity, ease: 'linear' }} |
| /> |
| |
| <div className="relative z-10 grid gap-10 lg:grid-cols-[1.15fr_0.85fr] lg:items-center"> |
| <div> |
| <motion.div |
| initial={{ opacity: 0, x: -12 }} |
| animate={{ opacity: 1, x: 0 }} |
| transition={{ delay: 0.15 }} |
| className="mb-6 inline-flex items-center gap-2 rounded-[8px] border border-rose-400/25 bg-rose-400/10 px-3 py-1 text-xs font-semibold text-rose-200" |
| > |
| <Radio size={14} className="text-rose-300" /> |
| Live Playground Active |
| </motion.div> |
| |
| <h1 className="text-5xl font-black text-white md:text-7xl"> |
| Playground |
| </h1> |
| |
| <p className="mt-5 max-w-2xl text-lg leading-8 text-zinc-300 md:text-xl"> |
| 1v1 coding battles. |
| </p> |
| |
| <div className="mt-9 text-sm text-zinc-500">Arena stats will appear after real matches are tracked.</div> |
| </div> |
| |
| <div className="relative min-h-[300px]"> |
| <motion.div |
| className="absolute right-0 top-0 text-cyan-200/10" |
| animate={{ rotate: [0, 3, 0], scale: [1, 1.04, 1] }} |
| transition={{ duration: 6, repeat: Infinity, ease: 'easeInOut' }} |
| > |
| <Shield size={260} strokeWidth={1} /> |
| </motion.div> |
| |
| <div className="relative z-10 flex h-full min-h-[300px] flex-col justify-center"> |
| <div className="mb-6 flex items-center gap-3 text-sm font-semibold text-cyan-100"> |
| <Activity size={18} /> |
| Match workflow |
| </div> |
| |
| <div className="space-y-4"> |
| {workflowSteps.map((step, index) => ( |
| <motion.div |
| key={step.label} |
| initial={{ opacity: 0, x: 18 }} |
| animate={{ opacity: 1, x: 0 }} |
| transition={{ delay: 0.25 + index * 0.12 }} |
| className="flex items-center gap-4" |
| > |
| <motion.div |
| className="flex h-9 w-9 items-center justify-center rounded-[8px] border border-cyan-300/25 bg-cyan-300/10 text-sm font-black text-cyan-100" |
| animate={{ boxShadow: ['0 0 0 rgba(34,211,238,0)', '0 0 22px rgba(34,211,238,0.24)', '0 0 0 rgba(34,211,238,0)'] }} |
| transition={{ duration: 2.6, repeat: Infinity, delay: index * 0.2 }} |
| > |
| {index + 1} |
| </motion.div> |
| <div> |
| <div className="font-bold text-white">{step.label}</div> |
| </div> |
| </motion.div> |
| ))} |
| </div> |
| </div> |
| </div> |
| </div> |
| </motion.div> |
| |
| <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> |
| {/* CodeBattle Card */} |
| <motion.div |
| initial={{ opacity: 0, y: 24 }} |
| animate={{ opacity: 1, y: 0 }} |
| transition={{ delay: 0.12, duration: 0.45 }} |
| whileHover={{ y: -6 }} |
| className="group relative overflow-hidden rounded-[8px] border border-cyan-400/20 bg-[linear-gradient(145deg,#101820,#15151c_55%,#1a1018)] p-8 transition-all hover:border-cyan-300/45 hover:shadow-[0_24px_80px_rgba(34,211,238,0.14)]" |
| > |
| <motion.div |
| className="absolute inset-x-0 top-0 h-[2px] bg-[linear-gradient(90deg,transparent,#22d3ee,#fb7185,transparent)]" |
| animate={{ x: ['-40%', '40%'] }} |
| transition={{ duration: 4.5, repeat: Infinity, repeatType: 'mirror', ease: 'easeInOut' }} |
| /> |
| |
| <div className="relative z-10 mb-6 flex items-start justify-between"> |
| <div className="flex h-14 w-14 items-center justify-center rounded-[8px] bg-[#ff5a3d] text-white shadow-lg shadow-[#ff5a3d]/20"> |
| <Swords size={28} /> |
| </div> |
| <div className="rounded-[8px] border border-white/10 bg-white/5 px-3 py-1 text-xs font-medium text-zinc-300"> |
| Competitive |
| </div> |
| </div> |
| |
| <div className="relative z-10"> |
| <h2 className="mb-3 text-2xl font-black text-white">CodeBattle</h2> |
| <p className="min-h-[80px] leading-relaxed text-zinc-400"> |
| 1v1 live duels. |
| </p> |
| </div> |
| |
| <div className="relative z-10 mt-8 flex items-center justify-between gap-4"> |
| <div className="text-xs font-bold uppercase text-cyan-300">Live count unavailable</div> |
| <motion.button |
| onClick={onEnterArena} |
| whileTap={{ scale: 0.96 }} |
| className="flex items-center gap-2 rounded-[8px] bg-[#f43f5e] px-6 py-3 font-bold text-white shadow-lg shadow-rose-500/25 transition-all hover:bg-[#e11d48]" |
| > |
| Start CodeBattle <Zap size={16} className="fill-current" /> |
| </motion.button> |
| </div> |
| |
| <motion.div |
| className="pointer-events-none absolute right-0 top-0 -translate-y-4 translate-x-4 opacity-[0.04] transition-opacity group-hover:opacity-[0.08]" |
| animate={{ rotate: [0, -4, 0] }} |
| transition={{ duration: 7, repeat: Infinity, ease: 'easeInOut' }} |
| > |
| <Swords size={200} strokeWidth={1.5} /> |
| </motion.div> |
| </motion.div> |
| |
| <motion.div |
| initial={{ opacity: 0, y: 24 }} |
| animate={{ opacity: 1, y: 0 }} |
| transition={{ delay: 0.22, duration: 0.45 }} |
| whileHover={{ y: -6 }} |
| className="group relative overflow-hidden rounded-[8px] border border-emerald-400/20 bg-[linear-gradient(145deg,#111816,#15151c_58%,#18120b)] p-8 transition-all hover:border-emerald-300/45 hover:shadow-[0_24px_80px_rgba(52,211,153,0.12)]" |
| > |
| <motion.div |
| className="absolute inset-x-0 top-0 h-[2px] bg-[linear-gradient(90deg,transparent,#34d399,#facc15,transparent)]" |
| animate={{ x: ['40%', '-40%'] }} |
| transition={{ duration: 4.5, repeat: Infinity, repeatType: 'mirror', ease: 'easeInOut' }} |
| /> |
| |
| <div className="relative z-10 mb-6 flex items-start justify-between"> |
| <div className="flex h-14 w-14 items-center justify-center rounded-[8px] bg-[#0ea5e9] text-white shadow-lg shadow-cyan-500/20"> |
| <BarChart2 size={28} /> |
| </div> |
| <div className="rounded-[8px] border border-white/10 bg-white/5 px-3 py-1 text-xs font-medium text-zinc-300"> |
| Ranked |
| </div> |
| </div> |
| |
| <div className="relative z-10"> |
| <h2 className="mb-3 text-2xl font-black text-white">Global Rankings</h2> |
| <p className="min-h-[80px] leading-relaxed text-zinc-400"> |
| Leaderboard. |
| </p> |
| </div> |
| |
| <div className="relative z-10 mt-8 flex items-center justify-between gap-4"> |
| <div className="text-xs font-bold uppercase text-emerald-300">Rank data unavailable</div> |
| <motion.button |
| whileTap={{ scale: 0.96 }} |
| className="flex items-center gap-2 rounded-[8px] bg-[#0891b2] px-6 py-3 font-bold text-white shadow-lg shadow-cyan-500/25 transition-all hover:bg-[#0e7490]" |
| > |
| View Rankings <BarChart2 size={16} /> |
| </motion.button> |
| </div> |
| |
| <motion.div |
| className="pointer-events-none absolute right-0 top-0 -translate-y-4 translate-x-4 opacity-[0.04] transition-opacity group-hover:opacity-[0.08]" |
| animate={{ rotate: [0, 4, 0] }} |
| transition={{ duration: 7, repeat: Infinity, ease: 'easeInOut' }} |
| > |
| <BarChart2 size={200} strokeWidth={1.5} /> |
| </motion.div> |
| </motion.div> |
| </div> |
| </div> |
| ); |
| } |
|
|