2025-12-12 13:15:44 +05:30

336 lines
15 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import { useState, useRef, useEffect } from 'react';
import styles from './SocialConnect.module.css';
const socialPlatforms = [
{ name: 'Bluesky', icon: '🦋', color: '#0085ff', delay: 0, symbol: 'B' },
{ name: 'Facebook', icon: 'f', color: '#1877f2', delay: 0.1, symbol: 'F' },
{ name: 'Google', icon: 'G', color: '#4285f4', delay: 0.2, symbol: 'G' },
{ name: 'Instagram', icon: '📷', color: '#e4405f', delay: 0.3, symbol: 'I' },
{ name: 'LinkedIn', icon: 'in', color: '#0a66c2', delay: 0.4, symbol: 'L' },
{ name: 'Mastodon', icon: '🐘', color: '#6364ff', delay: 0.5, symbol: 'M' },
{ name: 'Pinterest', icon: 'P', color: '#e60023', delay: 0.6, symbol: 'P' },
{ name: 'Threads', icon: '@', color: '#000000', delay: 0.7, symbol: 'T' },
{ name: 'TikTok', icon: '♪', color: '#000000', delay: 0.8, symbol: 'TT' },
{ name: 'X', icon: '𝕏', color: '#000000', delay: 0.9, symbol: 'X' },
{ name: 'YouTube', icon: '▶', color: '#ff0000', delay: 1.0, symbol: 'Y' },
];
interface Particle {
x: number;
y: number;
vx: number;
vy: number;
life: number;
color: string;
}
export default function SocialConnect() {
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
const [selectedPlatforms, setSelectedPlatforms] = useState<number[]>([]);
const [particles, setParticles] = useState<Particle[]>([]);
const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
const containerRef = useRef<HTMLDivElement>(null);
const cardRefs = useRef<(HTMLDivElement | null)[]>([]);
// 3D Tilt Effect on Mouse Move
const handleMouseMove = (e: React.MouseEvent, index: number) => {
const card = cardRefs.current[index];
if (!card) return;
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
const rotateX = ((y - centerY) / centerY) * -15;
const rotateY = ((x - centerX) / centerX) * 15;
card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) translateY(-10px) scale(1.05)`;
};
const handleMouseLeave = (index: number) => {
const card = cardRefs.current[index];
if (card) {
card.style.transform = '';
}
setHoveredIndex(null);
};
// Particle Explosion on Click
const createParticles = (e: React.MouseEvent, color: string) => {
const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const newParticles: Particle[] = [];
for (let i = 0; i < 12; i++) {
const angle = (Math.PI * 2 * i) / 12;
newParticles.push({
x,
y,
vx: Math.cos(angle) * (2 + Math.random() * 3),
vy: Math.sin(angle) * (2 + Math.random() * 3),
life: 1,
color,
});
}
setParticles(prev => [...prev, ...newParticles]);
};
const handlePlatformClick = (index: number, e: React.MouseEvent) => {
const isSelected = selectedPlatforms.includes(index);
setSelectedPlatforms(prev =>
prev.includes(index)
? prev.filter(i => i !== index)
: [...prev, index]
);
// Create particle explosion
createParticles(e, socialPlatforms[index].color);
};
// Animate particles
useEffect(() => {
if (particles.length === 0) return;
const interval = setInterval(() => {
setParticles(prev =>
prev
.map(p => ({
...p,
x: p.x + p.vx,
y: p.y + p.vy,
vy: p.vy + 0.2, // gravity
life: p.life - 0.02,
}))
.filter(p => p.life > 0)
);
}, 16);
return () => clearInterval(interval);
}, [particles]);
// Magnetic cursor effect
const handleContainerMouseMove = (e: React.MouseEvent) => {
setMousePos({ x: e.clientX, y: e.clientY });
};
return (
<section className={styles.connectSection} onMouseMove={handleContainerMouseMove}>
<div className="container">
{/* Animated Background Elements */}
<div className={styles.backgroundAnimation}>
<div className={styles.floatingOrb1}></div>
<div className={styles.floatingOrb2}></div>
<div className={styles.floatingOrb3}></div>
<div className={styles.gridPattern}></div>
</div>
{/* Header */}
<div className={styles.header}>
<span className={styles.badge}>
<span className={styles.badgeIcon}>🔗</span>
<span>One Platform, All Networks</span>
<span className={styles.badgePulse}></span>
</span>
<h2 className={styles.title}>
Connect Your <span className={styles.highlight}>Favorite Accounts</span>
</h2>
<p className={styles.subtitle}>
Seamlessly integrate all your social media platforms in one place.
Manage, schedule, and analyze everything from a single dashboard.
</p>
</div>
{/* Interactive Platform Grid */}
<div className={styles.platformsContainer} ref={containerRef}>
<div className={styles.connectText}>
<div className={styles.connectIconWrapper}>
<div className={styles.connectIcon}>🌐</div>
<div className={styles.iconRings}>
<div className={styles.ring}></div>
<div className={styles.ring}></div>
<div className={styles.ring}></div>
</div>
</div>
<h3>Connect your<br /><span className={styles.gradientText}>favorite accounts</span></h3>
<p className={styles.connectSubtext}>Click to select platforms</p>
</div>
<div className={styles.platformsGrid}>
{socialPlatforms.map((platform, index) => (
<div
key={platform.name}
ref={el => { cardRefs.current[index] = el; }}
className={`${styles.platformCard} ${selectedPlatforms.includes(index) ? styles.selected : ''
} ${hoveredIndex === index ? styles.hovered : ''}`}
style={{
animationDelay: `${platform.delay}s`,
'--platform-color': platform.color
} as React.CSSProperties}
onMouseEnter={() => setHoveredIndex(index)}
onMouseMove={(e) => handleMouseMove(e, index)}
onMouseLeave={() => handleMouseLeave(index)}
onClick={(e) => handlePlatformClick(index, e)}
>
{/* 3D Card Inner */}
<div className={styles.cardInner}>
<div className={styles.cardFront}>
<div className={styles.platformIcon}>
<span className={styles.iconEmoji} style={{ color: platform.color }}>
{platform.icon}
</span>
<div className={styles.platformName}>{platform.name}</div>
{selectedPlatforms.includes(index) && (
<div className={styles.checkmark}>
<span></span>
</div>
)}
</div>
{/* Animated border */}
<div className={styles.animatedBorder}></div>
{/* Shine effect */}
<div className={styles.shineEffect}></div>
</div>
</div>
<div className={styles.platformRipple}></div>
<div className={styles.platformGlow}></div>
{/* Connection dots */}
{selectedPlatforms.includes(index) && (
<div className={styles.connectionDots}>
<span></span>
<span></span>
<span></span>
</div>
)}
</div>
))}
</div>
{/* Particle System */}
<div className={styles.particleContainer}>
{particles.map((particle, i) => (
<div
key={i}
className={styles.particle}
style={{
left: `${particle.x}px`,
top: `${particle.y}px`,
backgroundColor: particle.color,
opacity: particle.life,
transform: `scale(${particle.life})`,
}}
/>
))}
</div>
</div>
{/* Enhanced Stats Bar */}
<div className={styles.statsBar}>
<div className={styles.statItem}>
<div className={styles.statIconWrapper}>
<div className={styles.statIcon}>🎯</div>
<div className={styles.statIconGlow}></div>
</div>
<div className={styles.statContent}>
<div className={styles.statNumber}>11+</div>
<div className={styles.statLabel}>Platforms Supported</div>
</div>
</div>
<div className={styles.statDivider}></div>
<div className={styles.statItem}>
<div className={styles.statIconWrapper}>
<div className={styles.statIcon}></div>
<div className={styles.statIconGlow}></div>
</div>
<div className={styles.statContent}>
<div className={`${styles.statNumber} ${styles.animated}`}>
{selectedPlatforms.length > 0 ? selectedPlatforms.length : '0'}
</div>
<div className={styles.statLabel}>Selected Networks</div>
</div>
</div>
<div className={styles.statDivider}></div>
<div className={styles.statItem}>
<div className={styles.statIconWrapper}>
<div className={styles.statIcon}>🚀</div>
<div className={styles.statIconGlow}></div>
</div>
<div className={styles.statContent}>
<div className={styles.statNumber}>1-Click</div>
<div className={styles.statLabel}>Easy Integration</div>
</div>
</div>
</div>
{/* Enhanced CTA Section */}
<div className={styles.ctaSection}>
<div className={styles.ctaBackground}>
<div className={styles.ctaOrb1}></div>
<div className={styles.ctaOrb2}></div>
</div>
<div className={styles.ctaContent}>
<h3 className={styles.ctaTitle}>Ready to streamline your social media?</h3>
<p className={styles.ctaText}>
Connect all your accounts now and start managing them from one powerful dashboard.
</p>
</div>
<div className={styles.ctaButtons}>
<button className="btn btn-primary btn-large">
Get Started Free
<span className={styles.arrow}></span>
</button>
<button className="btn btn-secondary btn-large">
View All Features
</button>
</div>
</div>
{/* Floating Connection Lines Animation */}
<svg className={styles.connectionLines} viewBox="0 0 1200 400" preserveAspectRatio="none">
<defs>
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#ec4899" stopOpacity="0.6" />
<stop offset="50%" stopColor="#a855f7" stopOpacity="0.6" />
<stop offset="100%" stopColor="#3b82f6" stopOpacity="0.6" />
</linearGradient>
<filter id="glow">
<feGaussianBlur stdDeviation="3" result="coloredBlur" />
<feMerge>
<feMergeNode in="coloredBlur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<path
className={styles.animatedPath}
d="M 0 200 Q 300 100 600 200 T 1200 200"
stroke="url(#lineGradient)"
strokeWidth="3"
fill="none"
filter="url(#glow)"
/>
<path
className={styles.animatedPath}
d="M 0 250 Q 300 350 600 250 T 1200 250"
stroke="url(#lineGradient)"
strokeWidth="3"
fill="none"
filter="url(#glow)"
style={{ animationDelay: '1s' }}
/>
</svg>
</div>
</section>
);
}