โ† Components/Gaming

AchievementUnlock

achievementunlock-1779379195935.tsx
'use client'
import { useState, useEffect } from 'react'

const ACHIEVEMENTS = [
  { id: 'first_copy', icon: '๐Ÿ“‹', name: 'First Copy', desc: 'Copied your first component', xp: 50, rarity: 'Common', color: '#64748b' },
  { id: 'power_user', icon: 'โšก', name: 'Power User', desc: 'Copied 100 components', xp: 500, rarity: 'Rare', color: '#6366f1' },
  { id: 'pro_tier', icon: '๐Ÿ‘‘', name: 'Pro Tier', desc: 'Upgraded to Pro plan', xp: 1000, rarity: 'Epic', color: '#C9A84C' },
  { id: 'mcp_setup', icon: '๐Ÿค–', name: 'AI Pioneer', desc: 'Configured MCP in Claude Code', xp: 750, rarity: 'Rare', color: '#22c55e' },
  { id: 'lifetime', icon: '๐Ÿ’Ž', name: 'Lifetime Member', desc: 'Purchased Lifetime access', xp: 5000, rarity: 'Legendary', color: '#f59e0b' },
]

export default function AchievementUnlock() {
  const [active, setActive] = useState<string | null>(null)
  const [unlocked, setUnlocked] = useState<Set<string>>(new Set())
  const [showing, setShowing] = useState(false)

  function unlock(id: string) {
    if (showing) return
    setActive(id)
    setUnlocked(u => new Set([...u, id]))
    setShowing(true)
    setTimeout(() => { setShowing(false); setTimeout(() => setActive(null), 300) }, 3500)
  }

  const ach = active ? ACHIEVEMENTS.find(a => a.id === active) : null
  const RARITY_GLOW: Record<string, string> = { Common: '#64748b', Rare: '#6366f1', Epic: '#C9A84C', Legendary: '#f59e0b' }

  return (
    <div style={{ background: '#0A0A0A', padding: 32, minHeight: 360, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 24 }}>
      {/* Notification */}
      <div style={{ position: 'relative', width: 320, height: 80 }}>
        {ach && (
          <div style={{ position: 'absolute', inset: 0, background: '#111', border: `1px solid ${ach.color}40`, borderRadius: 14, display: 'flex', alignItems: 'center', gap: 14, padding: '12px 16px', animation: showing ? 'slideDown 0.4s ease' : 'slideUp 0.3s ease', boxShadow: `0 0 32px ${ach.color}30` }}>
            <div style={{ width: 48, height: 48, borderRadius: '50%', background: ach.color + '20', border: `2px solid ${ach.color}50`, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 24, flexShrink: 0, animation: 'spin 0.5s ease' }}>{ach.icon}</div>
            <div style={{ flex: 1 }}>
              <div style={{ color: 'rgba(255,255,255,0.5)', fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.1em' }}>Achievement Unlocked</div>
              <div style={{ color: '#F5F5F0', fontSize: 14, fontWeight: 700 }}>{ach.name}</div>
              <div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 11 }}>{ach.desc}</div>
            </div>
            <div style={{ textAlign: 'right', flexShrink: 0 }}>
              <div style={{ color: '#C9A84C', fontSize: 14, fontWeight: 800 }}>+{ach.xp}</div>
              <div style={{ color: 'rgba(255,255,255,0.3)', fontSize: 10 }}>XP</div>
            </div>
          </div>
        )}
        {!ach && <div style={{ position: 'absolute', inset: 0, background: 'rgba(255,255,255,0.02)', border: '1px dashed rgba(255,255,255,0.08)', borderRadius: 14, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'rgba(255,255,255,0.2)', fontSize: 13 }}>Achievement appears here</div>}
      </div>

      {/* Grid */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 10, width: '100%', maxWidth: 340 }}>
        {ACHIEVEMENTS.map(a => (
          <button key={a.id} onClick={() => unlock(a.id)} style={{ background: unlocked.has(a.id) ? a.color + '12' : '#111', border: `1px solid ${unlocked.has(a.id) ? a.color + '30' : 'rgba(255,255,255,0.06)'}`, borderRadius: 12, padding: 14, cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6, opacity: unlocked.has(a.id) ? 1 : 0.5, transition: 'all 0.2s' }}>
            <span style={{ fontSize: 24, filter: unlocked.has(a.id) ? `drop-shadow(0 0 6px ${a.color})` : 'grayscale(1)' }}>{a.icon}</span>
            <span style={{ color: unlocked.has(a.id) ? '#F5F5F0' : 'rgba(255,255,255,0.3)', fontSize: 10, fontWeight: 600, textAlign: 'center' }}>{a.name}</span>
            <span style={{ color: a.color, fontSize: 9, opacity: unlocked.has(a.id) ? 1 : 0.4 }}>{a.rarity}</span>
          </button>
        ))}
      </div>

      <div style={{ color: 'rgba(255,255,255,0.3)', fontSize: 12 }}>{unlocked.size}/{ACHIEVEMENTS.length} unlocked ยท Click to unlock</div>
      <style>{`@keyframes slideDown { from { opacity:0; transform:translateY(-20px) } to { opacity:1; transform:translateY(0) } } @keyframes slideUp { from { opacity:1; transform:translateY(0) } to { opacity:0; transform:translateY(-20px) } } @keyframes spin { from { transform:rotate(-20deg) scale(0.8) } to { transform:rotate(0deg) scale(1) } }`}</style>
    </div>
  )
}

Component info

CategoryGaming
Frameworkreact
TierFREE
Views0
Copies0

About

Achievement unlock notification with animated badge, progress bar, XP reward, and sound icon