trianglewebsite / components /sections /ContactSection.tsx
Antaram's picture
Upload 26 files
35a92dd verified
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>
);
};