Spaces:
Sleeping
Sleeping
File size: 14,326 Bytes
35a92dd | 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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | import React, { useEffect, useState, useRef } from 'react';
interface ContactSectionProps {
onClose: () => void;
isAudioMuted: boolean;
onToggleAudioMuted: () => void;
}
export const ContactSection: React.FC<ContactSectionProps> = ({ onClose, isAudioMuted, onToggleAudioMuted }) => {
const [isLoaded, setIsLoaded] = useState(false);
const [activeFounder, setActiveFounder] = useState<string | null>(null);
const [aiText, setAiText] = useState("System Online. Initializing Team Triangle Protocol...");
const founderAudioRef = useRef<Record<string, HTMLAudioElement>>({});
const activeFounderAudioIdRef = useRef<string | null>(null);
// For the typing effect
const [displayedText, setDisplayedText] = useState("");
const typingTimeoutRef = useRef<any>(null);
useEffect(() => {
const t = setTimeout(() => setIsLoaded(true), 100);
const t2 = setTimeout(() => typeMessage("Greetings. I am Triangle.AI. Below are my creators. Or as they refer to themselves: 'The Three Dumb Founders'."), 800);
return () => { clearTimeout(t); clearTimeout(t2); };
}, []);
useEffect(() => {
if (isAudioMuted) {
(Object.values(founderAudioRef.current) as HTMLAudioElement[]).forEach((a) => {
a.pause();
});
activeFounderAudioIdRef.current = null;
}
}, [isAudioMuted]);
useEffect(() => {
return () => {
(Object.values(founderAudioRef.current) as HTMLAudioElement[]).forEach((a) => {
a.pause();
a.src = '';
a.load();
});
founderAudioRef.current = {};
activeFounderAudioIdRef.current = null;
};
}, []);
const typeMessage = (message: string) => {
if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current);
setAiText(message);
setDisplayedText("");
let i = 0;
const type = () => {
if (i < message.length) {
setDisplayedText(message.substring(0, i + 1));
i++;
typingTimeoutRef.current = setTimeout(type, 20); // Typing speed
}
};
type();
};
const getFounderAudio = (id: string) => {
if (founderAudioRef.current[id]) return founderAudioRef.current[id];
const srcMap: Record<string, string> = {
ADI: '/audio/aditya.wav',
YOGI: '/audio/yogiraj.wav',
MAN: '/audio/aman.wav',
};
const src = srcMap[id];
if (!src) return null;
const a = new Audio(src);
a.preload = 'auto';
a.volume = 0.9;
founderAudioRef.current[id] = a;
return a;
};
const stopFounderAudio = () => {
const activeId = activeFounderAudioIdRef.current;
if (!activeId) return;
const a = founderAudioRef.current[activeId];
if (a) {
a.pause();
try {
a.currentTime = 0;
} catch {
// ignore
}
}
activeFounderAudioIdRef.current = null;
};
const playFounderAudio = async (id: string) => {
if (isAudioMuted) return;
stopFounderAudio();
const a = getFounderAudio(id);
if (!a) return;
activeFounderAudioIdRef.current = id;
try {
a.currentTime = 0;
} catch {
// ignore
}
try {
await a.play();
} catch {
// ignore
}
};
const founders = [
{
id: "ADI",
name: "Aditya Devarshi",
role: "Visual Architect",
color: "text-cyan-400",
borderColor: "border-cyan-500/30",
bgHover: "hover:bg-cyan-900/10",
desc: "The Brain. He claims he designed me. I let him believe it to keep his ego stable. He paints pixels while the rest of us do the math.",
icon: "๐จ"
},
{
id: "YOGI",
name: "Yogiraj Umadi",
role: "System Criticizer",
color: "text-red-500",
borderColor: "border-red-500/30",
bgHover: "hover:bg-red-900/10",
desc: "The Breaker. If logic exists, he will find a way to smash it. He tests my systems until they cry. I believe he thinks he is smart.",
icon: "๐ ๏ธ"
},
{
id: "MAN",
name: "Aman Sutar",
role: "Cloud Phantom",
color: "text-indigo-300",
borderColor: "border-indigo-500/30",
bgHover: "hover:bg-indigo-900/10",
desc: "Shantit Kranti (Peaceful Revolution). The introvert who put me in the clouds. I am everywhere because of him. He speaks little, codes much.",
icon: "โ๏ธ"
}
];
const handleFounderEnter = (id: string) => {
setActiveFounder(id);
const f = founders.find(x => x.id === id);
if(f) typeMessage(f.desc);
void playFounderAudio(id);
};
const handleFounderLeave = () => {
setActiveFounder(null);
typeMessage("Select a founder to analyze their neural patterns. Or contact us directly below.");
stopFounderAudio();
};
return (
<div className={`fixed inset-0 z-50 flex flex-col bg-[#050000]/95 backdrop-blur-xl overflow-hidden transition-opacity duration-700 ${isLoaded ? 'opacity-100' : 'opacity-0'}`}>
{/* Top Bar */}
<div className="w-full max-w-[1400px] mx-auto px-6 py-6 md:px-12 flex justify-between items-center z-10 border-b border-white/5">
<div className="flex items-center gap-4">
{/* Animated Speaker Icon */}
<button onClick={onToggleAudioMuted} className="flex items-center gap-2 group cursor-pointer">
<div className={`relative w-8 h-8 rounded-full border border-white/10 flex items-center justify-center bg-white/5 group-hover:border-white/30 transition-all ${!isAudioMuted ? 'animate-pulse' : ''}`}>
{isAudioMuted ? (
<span className="text-xs text-white/30">๐</span>
) : (
<div className="flex gap-0.5 items-end h-3">
<span className="w-0.5 bg-white/80 h-1 animate-[bounce_0.8s_infinite]"></span>
<span className="w-0.5 bg-white/80 h-3 animate-[bounce_1.2s_infinite]"></span>
<span className="w-0.5 bg-white/80 h-2 animate-[bounce_0.5s_infinite]"></span>
</div>
)}
</div>
<span className="text-white/80 font-mono text-xs uppercase tracking-widest hidden sm:block">Triangle.AI Audio</span>
</button>
</div>
<button
onClick={onClose}
className="group flex items-center gap-3 text-white/50 hover:text-white transition-colors"
>
<span className="text-[10px] uppercase tracking-widest group-hover:tracking-[0.2em] transition-all duration-300">Disconnect</span>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
{/* Main Content */}
<div className="flex-1 w-full overflow-y-auto overflow-x-hidden scroll-smooth custom-scrollbar">
<div className="w-full max-w-[1400px] mx-auto px-6 md:px-12 pt-12 pb-32">
{/* AI AVATAR & DIALOGUE */}
<div className={`flex flex-col items-center justify-center mb-16 transition-all duration-1000 ease-out ${isLoaded ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-12'}`}>
<div className="relative w-24 h-24 mb-8">
{/* Generative Orb CSS */}
<div className="absolute inset-0 rounded-full border border-white/20 animate-[spin_10s_linear_infinite]"></div>
<div className="absolute inset-2 rounded-full border border-t-white/50 border-r-transparent border-b-white/10 border-l-transparent animate-[spin_3s_linear_infinite_reverse]"></div>
<div className="absolute inset-0 flex items-center justify-center">
<div className={`w-2 h-2 bg-white rounded-full shadow-[0_0_20px_rgba(255,255,255,0.8)] ${!isAudioMuted ? 'animate-ping' : 'opacity-50'}`}></div>
</div>
</div>
<div className="max-w-2xl text-center min-h-[80px]">
<p className="text-white/80 font-mono text-sm md:text-base leading-relaxed">
<span className="text-white/30 mr-2">[{!isAudioMuted ? 'VOICE_ACTIVE' : 'TEXT_ONLY'}]:</span>
{displayedText}
<span className="inline-block w-2 h-4 bg-white/50 ml-1 align-middle animate-pulse"></span>
</p>
</div>
</div>
{/* FOUNDERS TRIANGLE */}
<div className={`grid grid-cols-1 md:grid-cols-3 gap-6 lg:gap-12 mb-24 transition-all duration-1000 delay-200 ${isLoaded ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-12'}`}>
{founders.map((f) => (
<div
key={f.id}
onMouseEnter={() => handleFounderEnter(f.id)}
onMouseLeave={handleFounderLeave}
className={`relative group p-8 border bg-white/5 backdrop-blur-sm transition-all duration-500 cursor-pointer ${f.borderColor} ${f.bgHover} ${activeFounder === f.id ? 'scale-105 z-10' : 'scale-100 grayscale hover:grayscale-0'}`}
>
<div className="flex justify-between items-start mb-4">
<span className="text-3xl filter drop-shadow-lg">{f.icon}</span>
<span className={`text-[10px] font-mono border border-white/10 px-2 py-1 rounded-full ${f.color}`}>{f.id}</span>
</div>
<h3 className="text-xl font-light text-white mb-1">{f.name}</h3>
<p className={`text-xs font-mono uppercase tracking-widest ${f.color} opacity-70`}>{f.role}</p>
{/* Decorative Corner */}
<div className={`absolute bottom-0 right-0 w-4 h-4 border-b border-r ${f.borderColor.replace('/30', '/60')}`}></div>
</div>
))}
</div>
{/* CONTACT & SOCIALS */}
<div className={`grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-24 transition-all duration-1000 delay-400 ${isLoaded ? 'opacity-100' : 'opacity-0'}`}>
{/* Left: Chat Form */}
<div>
<div className="flex items-center gap-3 mb-8">
<span className="w-8 h-[1px] bg-white/20"></span>
<h2 className="text-2xl font-light text-white">Transmission Uplink</h2>
</div>
<form className="space-y-6" onSubmit={(e) => { e.preventDefault(); typeMessage("Transmission received. Processing... I will notify the humans."); }}>
<div className="grid grid-cols-2 gap-6">
<div className="space-y-2">
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest">Identity</label>
<input type="text" className="w-full bg-transparent border-b border-white/20 py-2 text-white font-light focus:outline-none focus:border-white transition-colors" placeholder="Name" />
</div>
<div className="space-y-2">
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest">Frequency</label>
<input type="email" className="w-full bg-transparent border-b border-white/20 py-2 text-white font-light focus:outline-none focus:border-white transition-colors" placeholder="Email" />
</div>
</div>
<div className="space-y-2">
<label className="text-[10px] font-mono text-white/40 uppercase tracking-widest">Packet Data</label>
<textarea rows={4} className="w-full bg-white/5 border border-white/10 p-4 text-white font-light focus:outline-none focus:border-white/30 transition-colors" placeholder="Message to the Team..."></textarea>
</div>
<button type="submit" className="px-8 py-3 bg-white text-black text-xs font-mono uppercase tracking-widest hover:bg-white/90 transition-colors">
Send Packet
</button>
</form>
</div>
{/* Right: Socials & Info */}
<div className="flex flex-col justify-between">
<div>
<div className="flex items-center gap-3 mb-8">
<span className="w-8 h-[1px] bg-white/20"></span>
<h2 className="text-2xl font-light text-white">Direct Line</h2>
</div>
<p className="text-white/50 text-sm leading-relaxed mb-8">
We are currently operating in stealth mode across multiple clouds.
You can find us where the pixels meet the data streams.
</p>
<div className="space-y-4">
<a href="#" className="flex items-center gap-4 group p-4 border border-white/5 hover:bg-white/5 transition-all">
<span className="text-xl">๐ธ</span>
<div>
<p className="text-white text-sm group-hover:text-pink-400 transition-colors">Instagram</p>
<p className="text-white/20 text-xs font-mono">@TeamTriangle</p>
</div>
</a>
<a href="#" className="flex items-center gap-4 group p-4 border border-white/5 hover:bg-white/5 transition-all">
<span className="text-xl">๐ผ</span>
<div>
<p className="text-white text-sm group-hover:text-blue-400 transition-colors">LinkedIn</p>
<p className="text-white/20 text-xs font-mono">/company/team-triangle</p>
</div>
</a>
</div>
</div>
<div className="mt-12 lg:mt-0 pt-8 border-t border-white/10">
<p className="text-white/30 font-mono text-xs">
"We build the sphere, you live in it."
</p>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
|