File size: 7,199 Bytes
f91a684
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { X, Check } from 'lucide-react';
import { cn } from '@/lib/utils';

export type AvatarConfig = {
  id: string;
  hue: number;
  saturate: number;
  glowColor: string;
};

export const AURAS: (AvatarConfig & { label: string })[] = [
  { id: 'default', label: 'Classic', glowColor: 'transparent', hue: 0, saturate: 100 },
  { id: 'neon-cyber', label: 'Neon Cyber', glowColor: '#06b6d4', hue: 160, saturate: 150 },
  { id: 'crimson', label: 'Crimson', glowColor: '#e11d48', hue: 330, saturate: 130 },
  { id: 'matrix', label: 'Matrix', glowColor: '#22c55e', hue: 100, saturate: 200 },
  { id: 'golden', label: 'Golden', glowColor: '#fbbf24', hue: 45, saturate: 140 },
  { id: 'void', label: 'The Void', glowColor: '#a855f7', hue: 280, saturate: 180 },
];

export default function AvatarCustomizerModal({
  isOpen,
  onClose,
  initialConfig,
  onSave,
}: {
  isOpen: boolean;
  onClose: () => void;
  initialConfig: AvatarConfig;
  onSave: (config: AvatarConfig) => void;
}) {
  const [activeTab, setActiveTab] = useState('aura');
  const [selectedConfig, setSelectedConfig] = useState<AvatarConfig>(initialConfig);

  useEffect(() => {
    if (isOpen) setSelectedConfig(initialConfig);
  }, [isOpen, initialConfig]);

  return (
    <AnimatePresence>
      {isOpen && (
        <div className="fixed inset-0 z-50 flex items-center justify-center pointer-events-none p-4 md:p-12 font-sans font-medium">
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="absolute inset-0 bg-black/60 backdrop-blur-md pointer-events-auto"
            onClick={onClose}
          />
          <motion.div
            initial={{ scale: 0.95, opacity: 0, y: 30 }}
            animate={{ scale: 1, opacity: 1, y: 0 }}
            exit={{ scale: 0.95, opacity: 0, y: 30 }}
            transition={{ type: 'spring', damping: 25, stiffness: 300 }}
            className="relative bg-[#0d0f1a] w-full max-w-4xl h-[85vh] md:h-[75vh] rounded-[2.5rem] border border-white/10 shadow-[0_0_80px_rgba(0,0,0,0.8)] overflow-hidden flex flex-col pointer-events-auto"
          >
            {/* Header */}
            <div className="flex justify-between items-center p-6 border-b border-white/5 bg-[#121422]/50">
              <h2 className="text-xl font-black text-white px-2">Customize Avatar</h2>
              <button 
                onClick={onClose}
                className="p-2 rounded-full hover:bg-white/10 text-slate-400 hover:text-white transition-colors"
              >
                <X size={24} />
              </button>
            </div>

            {/* Content Split */}
            <div className="flex flex-col md:flex-row flex-1 overflow-hidden">
              {/* Avatar Stage */}
              <div className="flex-1 bg-[radial-gradient(ellipse_at_center,rgba(255,255,255,0.05),transparent_70%)] relative flex items-center justify-center p-8 md:p-12 overflow-hidden border-b md:border-b-0 md:border-r border-white/5">
                <motion.div 
                   animate={{ rotate: 360 }}
                   transition={{ duration: 25, repeat: Infinity, ease: "linear" }}
                   className="absolute md:-inset-1/2 -inset-[10%] opacity-60 mix-blend-screen transform-gpu"
                   style={{
                     background: selectedConfig.glowColor !== 'transparent' ? `conic-gradient(from 0deg, transparent 0 90deg, ${selectedConfig.glowColor}40 90deg 180deg, transparent 180deg 270deg, ${selectedConfig.glowColor}20 270deg 360deg)` : 'transparent'
                   }}
                 />
                 <div 
                   className="relative z-10 w-64 h-64 md:w-80 md:h-80 transition-all duration-500 ease-out"
                   style={{
                     filter: selectedConfig.glowColor !== 'transparent' ? `drop-shadow(0 0 50px ${selectedConfig.glowColor}80) hue-rotate(${selectedConfig.hue}deg) saturate(${selectedConfig.saturate}%)` : 'none'
                   }}
                 >
                   <img src="/avatar.png" alt="Avatar Preview" className="w-full h-full object-contain" />
                 </div>
              </div>

              {/* Drawer Menu */}
              <div className="w-full md:w-[400px] flex flex-col bg-[#121422]/70 h-full">
                <div className="flex gap-6 p-6 border-b border-white/5 overflow-x-auto no-scrollbar">
                  {['Aura'].map(tab => (
                     <button key={tab} onClick={() => setActiveTab(tab.toLowerCase())} className={cn("text-[11px] font-black uppercase tracking-[0.2em] pb-3 border-b-2 transition-colors", activeTab === tab.toLowerCase() ? "border-indigo-400 text-white" : "border-transparent text-slate-500 hover:text-slate-300")}>
                        {tab}
                     </button>
                  ))}
                </div>
                
                <div className="flex-1 overflow-y-auto p-6 custom-scrollbar">
                   <div className="grid grid-cols-2 gap-4">
                      {AURAS.map(aura => (
                        <button 
                          key={aura.id}
                          onClick={() => setSelectedConfig(aura)}
                          className={cn("flex flex-col items-center justify-center p-4 rounded-2xl border transition-all h-28 group", selectedConfig.id === aura.id ? "bg-white/10 border-white/20 shadow-[0_0_25px_rgba(255,255,255,0.05)] scale-[1.02]" : "bg-white/5 border-transparent hover:bg-white/10")}
                        >
                           <div 
                             className="w-10 h-10 rounded-full mb-3 shadow-lg group-hover:scale-110 transition-transform" 
                             style={{ 
                                background: aura.glowColor === 'transparent' ? 'linear-gradient(135deg, #475569, #1e293b)' : aura.glowColor,
                                boxShadow: aura.glowColor !== 'transparent' ? `0 0 15px ${aura.glowColor}` : 'none'
                             }} 
                           />
                           <span className={cn("text-xs font-bold transition-colors", selectedConfig.id === aura.id ? "text-white" : "text-slate-400 group-hover:text-slate-300")}>{aura.label}</span>
                        </button>
                      ))}
                   </div>
                </div>

                <div className="p-6 border-t border-white/5 bg-[#0d0f1a]">
                   <button 
                     onClick={() => { onSave(selectedConfig); onClose(); }}
                     className="w-full bg-white hover:bg-indigo-400 text-black hover:text-white py-3.5 rounded-full text-sm font-black tracking-wide shadow-[0_0_20px_rgba(255,255,255,0.1)] hover:shadow-[0_0_20px_rgba(99,102,241,0.4)] transition-all flex items-center justify-center gap-2"
                   >
                     <Check size={18} strokeWidth={3} /> Apply Appearance
                   </button>
                </div>
              </div>
            </div>
          </motion.div>
        </div>
      )}
    </AnimatePresence>
  );
}