Spaces:
Sleeping
Sleeping
| 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> | |
| ); | |
| }; | |