953 lines
50 KiB
TypeScript
953 lines
50 KiB
TypeScript
import { useState, useMemo } from 'react';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import {
|
|
Users, Tag, X, Mail, Phone, UserCheck, GraduationCap, Info,
|
|
Atom, Wifi, Printer, Zap, Languages, Calculator, HeartHandshake,
|
|
Rocket, Camera, Sparkles, Mic, Target, ArrowRight, RotateCcw,
|
|
MessageCircle, ExternalLink, CheckCircle2, Compass, Globe, BookOpen, Heart,
|
|
Building2, Search, Cpu, Smartphone, Bot, SlidersHorizontal, Layers, Activity, Brain
|
|
} from 'lucide-react';
|
|
import SectionTitle from '@/components/SectionTitle/SectionTitle';
|
|
import { StaggerContainer, StaggerItem } from '@/components/AnimatedContainer/AnimatedContainer';
|
|
import AnimatedContainer from '@/components/AnimatedContainer/AnimatedContainer';
|
|
import { CLUBS_DATA } from '@/constants';
|
|
import type { Club } from '@/types';
|
|
|
|
const CLUB_CATEGORY_COLORS: Record<string, string> = {
|
|
Technical: '#3B82F6',
|
|
Cultural: '#EC4899',
|
|
Social: '#10B981',
|
|
Creative: '#F59E0B',
|
|
'Center of Excellence': '#8B5CF6',
|
|
};
|
|
|
|
const CLUB_ICON_MAP: Record<string, React.ComponentType<{ className?: string }>> = {
|
|
Atom,
|
|
Wifi,
|
|
Printer,
|
|
Zap,
|
|
Languages,
|
|
Calculator,
|
|
HeartHandshake,
|
|
Rocket,
|
|
Camera,
|
|
Sparkles,
|
|
Mic,
|
|
BookOpen,
|
|
Globe,
|
|
Users,
|
|
Cpu,
|
|
Smartphone,
|
|
Bot,
|
|
Brain,
|
|
Activity,
|
|
};
|
|
|
|
// ─── Inline Brand SVG Icons ──────────────────────────────────────────────────────
|
|
const InstagramIcon = ({ className = 'w-4 h-4' }: { className?: string }) => (
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}>
|
|
<rect width="20" height="20" x="2" y="2" rx="5" ry="5" />
|
|
<path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z" />
|
|
<line x1="17.5" x2="17.51" y1="6.5" y2="6.5" />
|
|
</svg>
|
|
);
|
|
|
|
const LinkedinIcon = ({ className = 'w-4 h-4' }: { className?: string }) => (
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}>
|
|
<path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z" />
|
|
<rect width="4" height="12" x="2" y="9" />
|
|
<circle cx="4" cy="4" r="2" />
|
|
</svg>
|
|
);
|
|
|
|
const YoutubeIcon = ({ className = 'w-4 h-4' }: { className?: string }) => (
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}>
|
|
<path d="M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-16.2 0A2 2 0 0 1 2.5 17" />
|
|
<polygon points="10 15 15 12 10 9 10 15" fill="currentColor" />
|
|
</svg>
|
|
);
|
|
|
|
// ─── Quiz Questions Data (Supporting Clubs, Centers, and Hybrid Matching) ───────
|
|
const QUIZ_QUESTIONS_ALL = [
|
|
{
|
|
id: 'domain',
|
|
title: '1. What technology or activity domain excites you the most?',
|
|
options: [
|
|
{ label: '🤖 AI, Machine Learning, Neural Networks & Data Science', clubIds: ['center_ai', 'center_data_science', 'wistem'] },
|
|
{ label: '⚡ Semiconductor VLSI, Microchip Architecture & Hardware', clubIds: ['center_semiconductor', 'steam'] },
|
|
{ label: '📱 Apple iOS, SwiftUI & Mobile Ecosystem', clubIds: ['center_apple_tech', 'techspark'] },
|
|
{ label: '🕶️ AR/VR, Metaverse, Spatial Computing & 3D Interactive Media', clubIds: ['center_ar_vr', 'mediastic'] },
|
|
{ label: '🔒 Cybersecurity, Ethical Hacking & Cryptography', clubIds: ['center_cybersecurity', 'techspark'] },
|
|
{ label: '🏥 Healthcare AI, RADAR Medical Diagnostics & Patient Care', clubIds: ['center_radar_healthcare', 'yrc'] },
|
|
{ label: '📡 IoT, Smart Automation & Embedded Sensors', clubIds: ['center_iot', 'steam'] },
|
|
{ label: '🚗 Electric Vehicles, Battery Systems & Autonomous Tech', clubIds: ['center_ev_energy', 'center_zf_transportation'] },
|
|
{ label: '☁️ Cloud Architecture, DevOps & Distributed Systems', clubIds: ['center_cloud_computing', 'techspark'] },
|
|
{ label: '🚀 Aerospace, Satellite Tech & Space Robotics', clubIds: ['center_space', 'steam'] },
|
|
{ label: '⚛️ Quantum Computing, Quantum Search & Grover Algorithms', clubIds: ['grover_center_quantum', 'infinitus'] },
|
|
{ label: '🎙️ Radio, Podcasting, Live Media & Content Creation', clubIds: ['podx', 'mediastic', 'helios'] },
|
|
{ label: '🤝 Community Service, Village Adoption & NSS Drives', clubIds: ['nss', 'unnat_bharat', 'rotaract'] },
|
|
{ label: '🎭 Cultural Arts, Dance, Music, Band & Drama', clubIds: ['artist_league', 'vaarithi', 'fusion'] },
|
|
],
|
|
},
|
|
{
|
|
id: 'skill',
|
|
title: '2. What practical skill do you want to master at RIT?',
|
|
options: [
|
|
{ label: '📊 Predictive Analytics, Python ML Pipelines & Data Modeling', clubIds: ['center_data_science', 'center_ai', 'center_zf_transportation'] },
|
|
{ label: '💻 Microchip IC Layout, Verilog/VHDL & FPGA Prototyping', clubIds: ['center_semiconductor', 'steam'] },
|
|
{ label: '🍎 Native iOS SwiftUI Coding & macOS Enterprise Apps', clubIds: ['center_apple_tech', 'techspark'] },
|
|
{ label: '🥽 Unity 3D, Spatial Audio & Metaverse Experience Design', clubIds: ['center_ar_vr', 'mediastic'] },
|
|
{ label: '🛡️ Network Security Audit, Cyber Threat Defense & Ethical Hacking', clubIds: ['center_cybersecurity'] },
|
|
{ label: '🩺 Medical Signal Processing & AI Diagnosis Tools', clubIds: ['center_radar_healthcare', 'center_image_processing'] },
|
|
{ label: '🔌 Smart Sensors, ESP32/Arduino, Edge Computing & CAN Bus', clubIds: ['center_iot', 'center_ev_energy'] },
|
|
{ label: '🎙️ Voice Recording, Public Speaking & Event Management', clubIds: ['podx', 'yuva', 'artist_league'] },
|
|
{ label: '🌱 Sustainable Rural Development & Eco-System Restoration', clubIds: ['unnat_bharat', 'nss', 'rotaract'] },
|
|
],
|
|
},
|
|
{
|
|
id: 'goal',
|
|
title: '3. What is your primary career aspiration during college?',
|
|
options: [
|
|
{ label: '🔬 Lead innovative research in a specialized Future Tech Center (CoE)', clubIds: ['center_ai', 'center_semiconductor', 'grover_center_quantum', 'center_apple_tech', 'center_space'] },
|
|
{ label: '🏆 Win technical hackathons & build product prototypes', clubIds: ['steam', 'wistem', 'techspark', 'center_data_science'] },
|
|
{ label: '🌟 Build a strong personal brand, public speaking & media portfolio', clubIds: ['podx', 'mediastic', 'helios'] },
|
|
{ label: '🤝 Drive impactful social initiatives & community leadership', clubIds: ['nss', 'rotaract', 'yuva', 'wec'] },
|
|
{ label: '💼 Connect with industry leaders, CII, and top startup networks', clubIds: ['yuva', 'wec', 'center_cloud_computing'] },
|
|
],
|
|
},
|
|
];
|
|
|
|
export default function Events() {
|
|
const [selectedClub, setSelectedClub] = useState<Club | null>(null);
|
|
const [searchQuery, setSearchQuery] = useState('');
|
|
const [selectedCategory, setSelectedCategory] = useState<string>('All');
|
|
const [selectedType, setSelectedType] = useState<'All' | 'Club' | 'Center'>('All');
|
|
|
|
// Compute counts dynamically
|
|
const { totalCount, centersCount, clubsCount } = useMemo(() => {
|
|
let centers = 0;
|
|
let clubs = 0;
|
|
CLUBS_DATA.forEach((item) => {
|
|
const isCenter =
|
|
item.type === 'Center' ||
|
|
item.category === 'Center of Excellence' ||
|
|
item.id.startsWith('center_') ||
|
|
item.id.includes('grover_center');
|
|
if (isCenter) centers++;
|
|
else clubs++;
|
|
});
|
|
return { totalCount: CLUBS_DATA.length, centersCount: centers, clubsCount: clubs };
|
|
}, []);
|
|
|
|
// ─── Interactive Like System ─────────────────────────────────────────────
|
|
const [likedClubs, setLikedClubs] = useState<Set<string>>(() => {
|
|
try {
|
|
localStorage.removeItem('rit_freshers_liked_clubs');
|
|
const saved = localStorage.getItem('rit_freshers_liked_clubs_v3');
|
|
return saved ? new Set(JSON.parse(saved)) : new Set();
|
|
} catch {
|
|
return new Set();
|
|
}
|
|
});
|
|
|
|
const [likesMap, setLikesMap] = useState<Record<string, number>>(() => {
|
|
const initialMap: Record<string, number> = {};
|
|
CLUBS_DATA.forEach((c) => {
|
|
initialMap[c.id] = 0;
|
|
});
|
|
return initialMap;
|
|
});
|
|
|
|
const toggleLike = (clubId: string) => {
|
|
const isCurrentlyLiked = likedClubs.has(clubId);
|
|
const next = new Set(likedClubs);
|
|
|
|
if (isCurrentlyLiked) {
|
|
next.delete(clubId);
|
|
setLikesMap((l) => ({ ...l, [clubId]: Math.max(0, (l[clubId] || 1) - 1) }));
|
|
} else {
|
|
next.add(clubId);
|
|
setLikesMap((l) => ({ ...l, [clubId]: (l[clubId] || 0) + 1 }));
|
|
}
|
|
|
|
setLikedClubs(next);
|
|
try {
|
|
localStorage.setItem('rit_freshers_liked_clubs_v3', JSON.stringify(Array.from(next)));
|
|
} catch {}
|
|
};
|
|
|
|
// ─── Quiz Matcher State ──────────────────────────────────────────────────
|
|
const [isQuizOpen, setIsQuizOpen] = useState(false);
|
|
const [matcherTarget, setMatcherTarget] = useState<'All' | 'Club' | 'Center'>('All');
|
|
const [quizStep, setQuizStep] = useState(0);
|
|
const [selectedAnswers, setSelectedAnswers] = useState<number[]>([]);
|
|
const [quizResults, setQuizResults] = useState<{ club: Club; score: number }[] | null>(null);
|
|
|
|
const handleSelectOption = (optionIdx: number) => {
|
|
const updated = [...selectedAnswers];
|
|
updated[quizStep] = optionIdx;
|
|
setSelectedAnswers(updated);
|
|
|
|
if (quizStep < QUIZ_QUESTIONS_ALL.length - 1) {
|
|
setQuizStep(quizStep + 1);
|
|
} else {
|
|
calculateQuizResults(updated);
|
|
}
|
|
};
|
|
|
|
const calculateQuizResults = (answers: number[]) => {
|
|
const scoreMap: Record<string, number> = {};
|
|
CLUBS_DATA.forEach((c) => (scoreMap[c.id] = 0));
|
|
|
|
answers.forEach((ansIdx, qIdx) => {
|
|
const option = QUIZ_QUESTIONS_ALL[qIdx].options[ansIdx];
|
|
if (option && option.clubIds) {
|
|
option.clubIds.forEach((clubId, idx) => {
|
|
scoreMap[clubId] = (scoreMap[clubId] || 0) + (5 - idx);
|
|
});
|
|
}
|
|
});
|
|
|
|
const pool = CLUBS_DATA.filter((c) => {
|
|
const isCenter =
|
|
c.type === 'Center' ||
|
|
c.category === 'Center of Excellence' ||
|
|
c.id.startsWith('center_') ||
|
|
c.id.includes('grover_center');
|
|
if (matcherTarget === 'Club') return !isCenter;
|
|
if (matcherTarget === 'Center') return isCenter;
|
|
return true;
|
|
});
|
|
|
|
const ranked = pool
|
|
.map((club) => ({
|
|
club,
|
|
score: scoreMap[club.id] || 0,
|
|
}))
|
|
.sort((a, b) => b.score - a.score);
|
|
|
|
setQuizResults(ranked.slice(0, 3));
|
|
};
|
|
|
|
const resetQuiz = () => {
|
|
setQuizStep(0);
|
|
setSelectedAnswers([]);
|
|
setQuizResults(null);
|
|
};
|
|
|
|
// ─── Filter Selection Handlers ───────────────────────────────────────────
|
|
const handleTypeSelect = (type: 'All' | 'Club' | 'Center') => {
|
|
setSelectedType(type);
|
|
setSelectedCategory('All');
|
|
};
|
|
|
|
const handleCategorySelect = (cat: string) => {
|
|
setSelectedCategory(cat);
|
|
if (cat === 'Center of Excellence') {
|
|
setSelectedType('Center');
|
|
} else if (cat !== 'All') {
|
|
setSelectedType('Club');
|
|
} else {
|
|
setSelectedType('All');
|
|
}
|
|
};
|
|
|
|
// ─── Robust Filter Logic ──────────────────────────────────────────────────
|
|
const filteredData = useMemo(() => {
|
|
return CLUBS_DATA.filter((item) => {
|
|
const isCenter =
|
|
item.type === 'Center' ||
|
|
item.category === 'Center of Excellence' ||
|
|
item.id.startsWith('center_') ||
|
|
item.id.includes('grover_center');
|
|
|
|
// 1. Type Filter check
|
|
if (selectedType === 'Club' && isCenter) return false;
|
|
if (selectedType === 'Center' && !isCenter) return false;
|
|
|
|
// 2. Category Filter check
|
|
if (selectedCategory !== 'All') {
|
|
if (selectedCategory === 'Center of Excellence' && !isCenter) return false;
|
|
if (selectedCategory !== 'Center of Excellence' && item.category !== selectedCategory) return false;
|
|
}
|
|
|
|
// 3. Search Query check
|
|
const q = searchQuery.toLowerCase().trim();
|
|
if (q) {
|
|
const matchesSearch =
|
|
item.name.toLowerCase().includes(q) ||
|
|
item.description.toLowerCase().includes(q) ||
|
|
(item.details && item.details.toLowerCase().includes(q)) ||
|
|
(item.presidentName && item.presidentName.toLowerCase().includes(q)) ||
|
|
(item.coordinatorName && item.coordinatorName.toLowerCase().includes(q));
|
|
if (!matchesSearch) return false;
|
|
}
|
|
|
|
return true;
|
|
});
|
|
}, [searchQuery, selectedCategory, selectedType]);
|
|
|
|
const categoriesList = ['All', 'Center of Excellence', 'Technical', 'Social', 'Creative'];
|
|
|
|
return (
|
|
<div className="min-h-screen bg-[#FAF9FC]">
|
|
{/* Header */}
|
|
<div className="bg-white border-b border-[#E9E5EE] py-10">
|
|
<div className="container-custom">
|
|
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-orange-50 border border-orange-200 text-[#F97316] text-xs font-bold uppercase tracking-wider mb-3">
|
|
<Building2 className="w-3.5 h-3.5" />
|
|
<span>RIT Official Directory</span>
|
|
</div>
|
|
<h1 className="text-3xl md:text-4xl font-bold text-[#1E293B] mb-2" style={{ fontFamily: 'Playfair Display, serif' }}>
|
|
Student Clubs &{' '}
|
|
<span style={{ background: 'linear-gradient(135deg, #F97316, #FB923C)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text' }}>
|
|
Centers of Excellence
|
|
</span>
|
|
</h1>
|
|
<p className="text-[#475569] max-w-3xl text-sm md:text-base" style={{ fontFamily: 'Inter, sans-serif' }}>
|
|
Explore official RIT student clubs, societies, and 15 Future Tech Centers of Excellence (CoEs), including faculty coordinators, research domains, and contact channels.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="container-custom pt-8 pb-20 md:pb-28">
|
|
|
|
{/* ─── Interactive Matcher Banner ─────────────────────────────────── */}
|
|
<AnimatedContainer className="mb-10">
|
|
<div
|
|
className="rounded-2xl p-6 md:p-8 text-white relative overflow-hidden border border-[#3A1968] flex flex-col md:flex-row items-center justify-between gap-6"
|
|
style={{ background: 'linear-gradient(135deg, #130924, #1E0C36)' }}
|
|
>
|
|
{/* Background Glow */}
|
|
<div
|
|
className="absolute top-0 right-0 w-80 h-80 rounded-full opacity-20 pointer-events-none"
|
|
style={{ background: 'radial-gradient(circle, #FF6B00, transparent)' }}
|
|
/>
|
|
|
|
<div className="relative z-10 max-w-xl">
|
|
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-orange-500/20 text-orange-400 text-xs font-semibold mb-3 border border-orange-500/30">
|
|
<Target className="w-3.5 h-3.5" />
|
|
<span>AI-Powered Matcher Quiz</span>
|
|
</div>
|
|
<h2 className="text-2xl md:text-3xl font-bold text-white mb-2" style={{ fontFamily: 'Playfair Display, serif' }}>
|
|
Find Your Ideal Club or Future Tech Center!
|
|
</h2>
|
|
<p className="text-slate-300 text-sm leading-relaxed" style={{ fontFamily: 'Inter, sans-serif' }}>
|
|
Take our 3-step Matcher quiz to discover which of the 18 Student Clubs or 15 Future Tech Centers best match your skills, technology interests, and career goals!
|
|
</p>
|
|
</div>
|
|
|
|
<div className="flex flex-col sm:flex-row items-center gap-3 shrink-0 relative z-10 w-full sm:w-auto">
|
|
<motion.button
|
|
whileHover={{ scale: 1.04 }}
|
|
whileTap={{ scale: 0.97 }}
|
|
onClick={() => { setMatcherTarget('Center'); resetQuiz(); setIsQuizOpen(true); }}
|
|
className="w-full sm:w-auto px-5 py-3 rounded-2xl bg-purple-600 hover:bg-purple-700 text-white font-semibold text-xs flex items-center justify-center gap-2 shadow-md cursor-pointer border border-purple-400/40"
|
|
style={{ fontFamily: 'Poppins, sans-serif' }}
|
|
>
|
|
<Cpu className="w-4 h-4" />
|
|
Match Centers (CoEs)
|
|
</motion.button>
|
|
<motion.button
|
|
whileHover={{ scale: 1.04 }}
|
|
whileTap={{ scale: 0.97 }}
|
|
onClick={() => { setMatcherTarget('All'); resetQuiz(); setIsQuizOpen(true); }}
|
|
className="w-full sm:w-auto px-5 py-3 rounded-2xl text-white font-semibold text-xs flex items-center justify-center gap-2 shadow-md cursor-pointer"
|
|
style={{ background: 'linear-gradient(135deg, #F97316, #FB923C)', fontFamily: 'Poppins, sans-serif' }}
|
|
>
|
|
<Sparkles className="w-4 h-4" />
|
|
Match All Directory
|
|
<ArrowRight className="w-4 h-4" />
|
|
</motion.button>
|
|
</div>
|
|
</div>
|
|
</AnimatedContainer>
|
|
|
|
{/* ─── Search & Category Filters Bar ───────────────────────────────── */}
|
|
<div className="mb-10 space-y-5">
|
|
<SectionTitle tag="Official Directory" title="Clubs &" highlight="Centers" subtitle="Browse or search 18 official RIT clubs and 15 Future Tech Centers of Excellence. Click any card for faculty lead and details." />
|
|
|
|
{/* Search & Type Toggle Controls */}
|
|
<div className="flex flex-col md:flex-row items-center justify-between gap-4 bg-white p-4 rounded-2xl border border-slate-200 shadow-xs">
|
|
{/* Search Input */}
|
|
<div className="relative w-full md:w-80">
|
|
<Search className="w-4 h-4 text-slate-400 absolute left-3.5 top-1/2 -translate-y-1/2" />
|
|
<input
|
|
type="text"
|
|
placeholder="Search name, faculty lead, domain..."
|
|
value={searchQuery}
|
|
onChange={(e) => setSearchQuery(e.target.value)}
|
|
className="w-full pl-10 pr-4 py-2.5 rounded-xl border border-slate-200 text-xs font-medium text-slate-800 focus:outline-none focus:border-[#F97316] transition-colors"
|
|
style={{ fontFamily: 'Inter, sans-serif' }}
|
|
/>
|
|
{searchQuery && (
|
|
<button onClick={() => setSearchQuery('')} className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600">
|
|
<X className="w-3.5 h-3.5" />
|
|
</button>
|
|
)}
|
|
</div>
|
|
|
|
{/* Type Pills Toggle (All / Clubs / Centers) */}
|
|
<div className="flex items-center gap-1.5 bg-slate-100 p-1 rounded-xl w-full md:w-auto overflow-x-auto">
|
|
{[
|
|
{ label: `All (${totalCount})`, value: 'All' },
|
|
{ label: `Clubs (${clubsCount})`, value: 'Club' },
|
|
{ label: `Centers of Excellence (${centersCount})`, value: 'Center' },
|
|
].map((t) => (
|
|
<button
|
|
key={t.value}
|
|
onClick={() => handleTypeSelect(t.value as any)}
|
|
className={`px-4 py-2 rounded-lg text-xs font-bold transition-all whitespace-nowrap cursor-pointer ${
|
|
selectedType === t.value
|
|
? 'bg-white text-[#1E293B] shadow-2xs border border-slate-200'
|
|
: 'text-slate-600 hover:text-slate-900'
|
|
}`}
|
|
style={{ fontFamily: 'Poppins, sans-serif' }}
|
|
>
|
|
{t.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Category Filter Tabs */}
|
|
<div className="flex items-center gap-2 overflow-x-auto pb-2 scrollbar-none">
|
|
<span className="text-xs font-semibold text-slate-400 flex items-center gap-1 shrink-0 pr-1">
|
|
<SlidersHorizontal className="w-3.5 h-3.5" /> Filter:
|
|
</span>
|
|
{categoriesList.map((cat) => (
|
|
<button
|
|
key={cat}
|
|
onClick={() => handleCategorySelect(cat)}
|
|
className={`px-3.5 py-1.5 rounded-xl text-xs font-semibold whitespace-nowrap transition-all cursor-pointer border ${
|
|
selectedCategory === cat
|
|
? 'bg-[#1E293B] text-white border-[#1E293B] shadow-xs'
|
|
: 'bg-white text-slate-600 border-slate-200 hover:border-slate-300 hover:bg-slate-50'
|
|
}`}
|
|
style={{ fontFamily: 'Poppins, sans-serif' }}
|
|
>
|
|
{cat}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* ─── Directory Grid ──────────────────────────────────────────────── */}
|
|
{filteredData.length === 0 ? (
|
|
<div className="bg-white rounded-3xl border border-slate-200 p-12 text-center my-8">
|
|
<Layers className="w-10 h-10 text-slate-300 mx-auto mb-3" />
|
|
<h3 className="text-lg font-bold text-slate-700">No matching items found</h3>
|
|
<p className="text-xs text-slate-400 mt-1 mb-4">Try adjusting your search terms or filter selections.</p>
|
|
<button
|
|
onClick={() => { setSearchQuery(''); setSelectedCategory('All'); setSelectedType('All'); }}
|
|
className="px-4 py-2 bg-orange-500 text-white rounded-xl text-xs font-bold hover:bg-orange-600 transition-colors cursor-pointer"
|
|
>
|
|
Reset Filters
|
|
</button>
|
|
</div>
|
|
) : (
|
|
<StaggerContainer className="pb-8">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-7">
|
|
{filteredData.map((club) => {
|
|
const IconComponent = (club.icon && CLUB_ICON_MAP[club.icon]) || Atom;
|
|
const isCenter =
|
|
club.type === 'Center' ||
|
|
club.category === 'Center of Excellence' ||
|
|
club.id.startsWith('center_') ||
|
|
club.id.includes('grover_center');
|
|
const categoryColor = CLUB_CATEGORY_COLORS[club.category] || (isCenter ? '#8B5CF6' : '#F97316');
|
|
const isLiked = likedClubs.has(club.id);
|
|
const likesCount = likesMap[club.id] || 0;
|
|
|
|
return (
|
|
<StaggerItem key={club.id} className="w-full h-full">
|
|
<motion.div
|
|
whileHover={{ y: -4 }}
|
|
onClick={() => setSelectedClub(club)}
|
|
className="bg-white rounded-2xl border border-[#E5E7EB] p-5 cursor-pointer hover:border-[#F97316] transition-all flex flex-col justify-between h-full group relative overflow-hidden"
|
|
style={{ boxShadow: '0 2px 15px -3px rgba(0,0,0,0.07)' }}
|
|
>
|
|
<div>
|
|
{/* Top Row: Icon/Logo + Badge + Heart Like Button */}
|
|
<div className="flex items-center justify-between mb-3">
|
|
{club.logoUrl ? (
|
|
<div className="w-12 h-12 rounded-full border border-slate-100 p-0.5 shadow-sm bg-white overflow-hidden shrink-0 transition-transform group-hover:scale-105">
|
|
<img src={club.logoUrl} alt={club.name} className="w-full h-full object-cover rounded-full" />
|
|
</div>
|
|
) : (
|
|
<div
|
|
className="w-11 h-11 rounded-full flex items-center justify-center text-white shadow-sm transition-transform group-hover:scale-105"
|
|
style={{
|
|
background: isCenter
|
|
? 'linear-gradient(135deg, #8B5CF6, #6366F1)'
|
|
: `linear-gradient(135deg, ${categoryColor}, ${categoryColor}DD)`,
|
|
}}
|
|
>
|
|
<IconComponent className="w-5 h-5 text-white" />
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex items-center gap-2">
|
|
{/* Type Badge */}
|
|
{isCenter ? (
|
|
<span className="px-2 py-0.5 rounded-full text-[10px] font-bold bg-purple-100 text-purple-700 border border-purple-200">
|
|
CENTER OF EXCELLENCE
|
|
</span>
|
|
) : (
|
|
<span className="px-2 py-0.5 rounded-full text-[10px] font-bold bg-blue-50 text-blue-600 border border-blue-100">
|
|
CLUB
|
|
</span>
|
|
)}
|
|
|
|
{/* Like Button */}
|
|
<motion.button
|
|
whileHover={{ scale: 1.08 }}
|
|
whileTap={{ scale: 0.85 }}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
toggleLike(club.id);
|
|
}}
|
|
className={`flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-semibold transition-all cursor-pointer border ${
|
|
isLiked
|
|
? 'bg-rose-50 border-rose-200 text-rose-600 shadow-2xs'
|
|
: 'bg-slate-50 border-slate-200 text-slate-500 hover:border-rose-300 hover:text-rose-500'
|
|
}`}
|
|
>
|
|
<Heart className={`w-3.5 h-3.5 ${isLiked ? 'fill-rose-500 text-rose-500' : ''}`} />
|
|
<span>{likesCount}</span>
|
|
</motion.button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Title & Description */}
|
|
<h3 className="font-semibold text-[#1E293B] mb-1 group-hover:text-[#F97316] transition-colors line-clamp-2 text-sm md:text-base" style={{ fontFamily: 'Poppins, sans-serif' }}>
|
|
{club.name}
|
|
</h3>
|
|
<p className="text-xs text-[#64748B] mb-3 line-clamp-2" style={{ fontFamily: 'Inter, sans-serif' }}>
|
|
{club.description}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Bottom Row: Category/Coordinator Tag & View Details Button */}
|
|
<div className="flex items-center justify-between mt-auto pt-3 border-t border-slate-100">
|
|
<span className="flex items-center gap-1 text-xs font-medium truncate max-w-[60%]" style={{ color: categoryColor }}>
|
|
{isCenter ? <GraduationCap className="w-3.5 h-3.5 shrink-0 text-purple-600" /> : <Tag className="w-3 h-3 shrink-0" />}
|
|
<span className="truncate">{isCenter && club.coordinatorName ? club.coordinatorName : club.category}</span>
|
|
</span>
|
|
<motion.button
|
|
whileHover={{ scale: 1.04 }}
|
|
className="px-3.5 py-1.5 rounded-lg text-xs font-semibold text-white flex items-center gap-1 cursor-pointer shrink-0"
|
|
style={{ fontFamily: 'Poppins, sans-serif', background: isCenter ? 'linear-gradient(135deg, #8B5CF6, #6366F1)' : 'linear-gradient(135deg, #F97316, #FB923C)' }}
|
|
>
|
|
View Details
|
|
</motion.button>
|
|
</div>
|
|
</motion.div>
|
|
</StaggerItem>
|
|
);
|
|
})}
|
|
</div>
|
|
</StaggerContainer>
|
|
)}
|
|
</div>
|
|
|
|
{/* ─── Matcher Quiz Modal ────────────────────────────────────────────── */}
|
|
<AnimatePresence>
|
|
{isQuizOpen && (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm">
|
|
<motion.div
|
|
initial={{ opacity: 0, scale: 0.95 }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
exit={{ opacity: 0, scale: 0.95 }}
|
|
className="bg-white rounded-3xl border border-[#E5E7EB] max-w-xl w-full p-6 md:p-8 relative shadow-2xl overflow-hidden"
|
|
>
|
|
{/* Close Button */}
|
|
<button
|
|
onClick={() => setIsQuizOpen(false)}
|
|
className="absolute top-5 right-5 w-9 h-9 rounded-full bg-slate-100 flex items-center justify-center text-slate-500 hover:bg-slate-200 transition-all cursor-pointer"
|
|
>
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
|
|
{!quizResults ? (
|
|
<div>
|
|
{/* Quiz Target Selector Header */}
|
|
<div className="flex items-center justify-between gap-2 mb-4">
|
|
<div className="flex items-center gap-2 text-[#F97316]">
|
|
<Compass className="w-5 h-5" />
|
|
<span className="text-xs font-bold uppercase tracking-wider">
|
|
{matcherTarget === 'Center' ? 'Future Tech Center Matcher' : matcherTarget === 'Club' ? 'Student Club Matcher' : 'Interactive Directory Matcher'}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Quiz Progress */}
|
|
<div className="flex items-center justify-between text-xs text-slate-500 mb-2 font-medium">
|
|
<span>Question {quizStep + 1} of {QUIZ_QUESTIONS_ALL.length}</span>
|
|
<span>Step {quizStep + 1} / {QUIZ_QUESTIONS_ALL.length}</span>
|
|
</div>
|
|
<div className="w-full h-1.5 bg-slate-100 rounded-full mb-6 overflow-hidden">
|
|
<div
|
|
className="h-full bg-[#F97316] transition-all duration-300 rounded-full"
|
|
style={{ width: `${((quizStep + 1) / QUIZ_QUESTIONS_ALL.length) * 100}%` }}
|
|
/>
|
|
</div>
|
|
|
|
{/* Question Header */}
|
|
<h3 className="text-xl font-bold text-[#1E293B] mb-5" style={{ fontFamily: 'Playfair Display, serif' }}>
|
|
{QUIZ_QUESTIONS_ALL[quizStep].title}
|
|
</h3>
|
|
|
|
{/* Options List */}
|
|
<div className="space-y-2.5 mb-6 max-h-[50vh] overflow-y-auto pr-1">
|
|
{QUIZ_QUESTIONS_ALL[quizStep].options.map((opt, idx) => (
|
|
<button
|
|
key={idx}
|
|
onClick={() => handleSelectOption(idx)}
|
|
className="w-full text-left p-3.5 rounded-2xl border border-slate-200 hover:border-[#F97316] hover:bg-orange-50/50 transition-all flex items-center justify-between text-xs sm:text-sm font-medium text-slate-700 cursor-pointer group"
|
|
>
|
|
<span>{opt.label}</span>
|
|
<ArrowRight className="w-4 h-4 text-slate-300 group-hover:text-[#F97316] group-hover:translate-x-1 transition-all shrink-0 ml-2" />
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
{quizStep > 0 && (
|
|
<button
|
|
onClick={() => setQuizStep(quizStep - 1)}
|
|
className="text-xs font-semibold text-slate-500 hover:text-slate-800 flex items-center gap-1 cursor-pointer"
|
|
>
|
|
← Previous Question
|
|
</button>
|
|
)}
|
|
</div>
|
|
) : (
|
|
/* Results Screen */
|
|
<div>
|
|
<div className="text-center mb-6">
|
|
<div className="w-14 h-14 rounded-2xl bg-orange-100 text-[#F97316] flex items-center justify-center mx-auto mb-3">
|
|
<CheckCircle2 className="w-8 h-8" />
|
|
</div>
|
|
<h3 className="text-2xl font-bold text-[#1E293B]" style={{ fontFamily: 'Playfair Display, serif' }}>
|
|
Your Recommended Matches!
|
|
</h3>
|
|
<p className="text-xs text-slate-500 mt-1">Based on your selections, here are your top recommended RIT entities:</p>
|
|
</div>
|
|
|
|
{/* Top 3 Matches */}
|
|
<div className="space-y-3 mb-6">
|
|
{quizResults.map((item, i) => {
|
|
const IconComponent = (item.club.icon && CLUB_ICON_MAP[item.club.icon]) || Atom;
|
|
const isCenter =
|
|
item.club.type === 'Center' ||
|
|
item.club.category === 'Center of Excellence' ||
|
|
item.club.id.startsWith('center_') ||
|
|
item.club.id.includes('grover_center');
|
|
const catColor = CLUB_CATEGORY_COLORS[item.club.category] || (isCenter ? '#8B5CF6' : '#F97316');
|
|
const matchPercent = i === 0 ? '98%' : i === 1 ? '92%' : '85%';
|
|
|
|
return (
|
|
<div
|
|
key={item.club.id}
|
|
onClick={() => {
|
|
setIsQuizOpen(false);
|
|
setSelectedClub(item.club);
|
|
}}
|
|
className="p-4 rounded-2xl border border-slate-200 hover:border-[#F97316] bg-slate-50 hover:bg-white cursor-pointer transition-all flex items-center justify-between gap-3"
|
|
>
|
|
<div className="flex items-center gap-3 min-w-0">
|
|
{item.club.logoUrl ? (
|
|
<div className="w-10 h-10 rounded-full border border-slate-100 p-0.5 shadow-sm bg-white overflow-hidden shrink-0">
|
|
<img src={item.club.logoUrl} alt={item.club.name} className="w-full h-full object-cover rounded-full" />
|
|
</div>
|
|
) : (
|
|
<div
|
|
className="w-10 h-10 rounded-full flex items-center justify-center text-white shrink-0"
|
|
style={{ background: isCenter ? 'linear-gradient(135deg, #8B5CF6, #6366F1)' : `linear-gradient(135deg, ${catColor}, ${catColor}DD)` }}
|
|
>
|
|
<IconComponent className="w-5 h-5 text-white" />
|
|
</div>
|
|
)}
|
|
<div className="min-w-0">
|
|
<div className="flex items-center gap-2">
|
|
<span className="font-bold text-xs sm:text-sm text-[#1E293B] truncate">{item.club.name}</span>
|
|
{i === 0 && <span className="px-2 py-0.5 rounded-full text-[9px] font-bold bg-amber-100 text-amber-700 shrink-0">Top Match 🏆</span>}
|
|
</div>
|
|
<span className="text-[11px] text-slate-500 truncate block">
|
|
{isCenter ? (item.club.coordinatorName ? `CoE Lead: ${item.club.coordinatorName}` : 'Center of Excellence') : `${item.club.category} Club`}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<span className="px-2.5 py-1 rounded-full text-xs font-bold bg-emerald-50 text-emerald-600 border border-emerald-200 shrink-0">
|
|
{matchPercent}
|
|
</span>
|
|
</div>
|
|
);
|
|
})}
|
|
</div>
|
|
|
|
<div className="flex gap-3">
|
|
<button
|
|
onClick={resetQuiz}
|
|
className="flex-1 py-3 rounded-xl border border-slate-300 text-slate-600 font-semibold text-xs flex items-center justify-center gap-1.5 hover:bg-slate-50 transition-all cursor-pointer"
|
|
>
|
|
<RotateCcw className="w-3.5 h-3.5" />
|
|
Retake Quiz
|
|
</button>
|
|
<button
|
|
onClick={() => setIsQuizOpen(false)}
|
|
className="flex-1 py-3 rounded-xl text-white font-semibold text-xs bg-[#F97316] hover:bg-[#EA580C] transition-all cursor-pointer"
|
|
>
|
|
Explore Directory
|
|
</button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</motion.div>
|
|
</div>
|
|
)}
|
|
</AnimatePresence>
|
|
|
|
{/* ─── Detailed View Modal ───────────────────────────────────────────── */}
|
|
<AnimatePresence>
|
|
{selectedClub && (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm">
|
|
<motion.div
|
|
initial={{ opacity: 0, scale: 0.95 }}
|
|
animate={{ opacity: 1, scale: 1 }}
|
|
exit={{ opacity: 0, scale: 0.95 }}
|
|
className="bg-white rounded-3xl border border-[#E5E7EB] max-w-xl w-full max-h-[90vh] overflow-y-auto p-6 md:p-8 relative"
|
|
style={{ boxShadow: '0 20px 50px rgba(0,0,0,0.2)' }}
|
|
>
|
|
{/* Close Button */}
|
|
<button
|
|
onClick={() => setSelectedClub(null)}
|
|
className="absolute top-5 right-5 w-9 h-9 rounded-full bg-slate-100 flex items-center justify-center text-slate-500 hover:bg-slate-200 transition-all cursor-pointer"
|
|
>
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
|
|
{/* Modal Header */}
|
|
{(() => {
|
|
const IconComponent = (selectedClub.icon && CLUB_ICON_MAP[selectedClub.icon]) || Atom;
|
|
const isCenter =
|
|
selectedClub.type === 'Center' ||
|
|
selectedClub.category === 'Center of Excellence' ||
|
|
selectedClub.id.startsWith('center_') ||
|
|
selectedClub.id.includes('grover_center');
|
|
const categoryColor = CLUB_CATEGORY_COLORS[selectedClub.category] || (isCenter ? '#8B5CF6' : '#F97316');
|
|
const isLiked = likedClubs.has(selectedClub.id);
|
|
const likesCount = likesMap[selectedClub.id] || 0;
|
|
|
|
return (
|
|
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4 mb-5 pb-4 border-b border-slate-100">
|
|
<div className="flex items-center gap-4">
|
|
{selectedClub.logoUrl ? (
|
|
<div className="w-16 h-16 rounded-full border-2 border-slate-100 p-1 shadow-md bg-white overflow-hidden shrink-0">
|
|
<img src={selectedClub.logoUrl} alt={selectedClub.name} className="w-full h-full object-cover rounded-full" />
|
|
</div>
|
|
) : (
|
|
<div
|
|
className="w-14 h-14 rounded-full flex items-center justify-center text-white font-bold text-2xl shadow-sm shrink-0"
|
|
style={{ background: isCenter ? 'linear-gradient(135deg, #8B5CF6, #6366F1)' : `linear-gradient(135deg, ${categoryColor}, ${categoryColor}DD)` }}
|
|
>
|
|
<IconComponent className="w-7 h-7 text-white" />
|
|
</div>
|
|
)}
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<span
|
|
className="px-2.5 py-0.5 rounded-full text-xs font-semibold"
|
|
style={{ backgroundColor: `${categoryColor}15`, color: categoryColor, fontFamily: 'Poppins, sans-serif' }}
|
|
>
|
|
{selectedClub.category}
|
|
</span>
|
|
{isCenter && (
|
|
<span className="px-2 py-0.5 rounded-full text-[10px] font-bold bg-purple-100 text-purple-700 border border-purple-200">
|
|
CENTER OF EXCELLENCE
|
|
</span>
|
|
)}
|
|
</div>
|
|
<h2 className="text-2xl font-bold text-[#1E293B]" style={{ fontFamily: 'Playfair Display, serif' }}>
|
|
{selectedClub.name}
|
|
</h2>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Interactive Like Button */}
|
|
<motion.button
|
|
whileHover={{ scale: 1.05 }}
|
|
whileTap={{ scale: 0.92 }}
|
|
onClick={() => toggleLike(selectedClub.id)}
|
|
className={`px-4 py-2 rounded-xl text-xs font-bold flex items-center gap-2 transition-all cursor-pointer shadow-xs border shrink-0 ${
|
|
isLiked
|
|
? 'bg-rose-500 text-white border-rose-600 shadow-rose-200'
|
|
: 'bg-rose-50 text-rose-600 border-rose-200 hover:bg-rose-100'
|
|
}`}
|
|
>
|
|
<Heart className={`w-4 h-4 ${isLiked ? 'fill-white' : 'text-rose-500'}`} />
|
|
<span>{isLiked ? 'Liked' : 'Like'} ({likesCount})</span>
|
|
</motion.button>
|
|
</div>
|
|
);
|
|
})()}
|
|
|
|
{/* Detailed Description */}
|
|
<div className="mb-5 bg-gradient-to-r from-orange-50/70 via-amber-50/40 to-slate-50 border border-orange-200/80 rounded-2xl p-4.5">
|
|
<div className="flex items-center gap-2 text-xs font-bold text-[#F97316] uppercase tracking-wider mb-2">
|
|
<Info className="w-4 h-4 text-[#F97316]" />
|
|
<span>About {selectedClub.type === 'Center' || selectedClub.category === 'Center of Excellence' ? 'the Center of Excellence' : 'the Club'}</span>
|
|
</div>
|
|
<p className="text-slate-700 text-sm leading-relaxed" style={{ fontFamily: 'Inter, sans-serif' }}>
|
|
{selectedClub.details || selectedClub.description}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Leadership & Contact Cards */}
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3.5 mb-6">
|
|
{/* Faculty Coordinator Card */}
|
|
{selectedClub.coordinatorName && (
|
|
<div className="bg-amber-50/80 border border-amber-100 hover:border-amber-300 transition-colors rounded-2xl p-3.5 flex items-center gap-3">
|
|
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-amber-500 to-amber-600 text-white flex items-center justify-center shadow-xs shadow-amber-200 shrink-0">
|
|
<GraduationCap className="w-5 h-5 text-white" />
|
|
</div>
|
|
<div>
|
|
<span className="text-[11px] text-amber-600 font-semibold block">
|
|
{selectedClub.type === 'Center' || selectedClub.category === 'Center of Excellence' ? 'Faculty Co-ordinator' : 'Faculty Coordinator'}
|
|
</span>
|
|
<span className="text-sm font-bold text-amber-950">{selectedClub.coordinatorName}</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* President / Student Lead Card */}
|
|
{selectedClub.presidentName && (
|
|
<div className="bg-indigo-50/80 border border-indigo-100 hover:border-indigo-300 transition-colors rounded-2xl p-3.5 flex items-center gap-3">
|
|
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-indigo-500 to-indigo-600 text-white flex items-center justify-center shadow-xs shadow-indigo-200 shrink-0">
|
|
<UserCheck className="w-5 h-5 text-white" />
|
|
</div>
|
|
<div>
|
|
<span className="text-[11px] text-indigo-500 font-semibold block">
|
|
{selectedClub.type === 'Center' || selectedClub.category === 'Center of Excellence' ? 'Research / Student Lead' : 'President / Student Lead'}
|
|
</span>
|
|
<span className="text-sm font-bold text-indigo-950">{selectedClub.presidentName}</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Vice President Card */}
|
|
{selectedClub.vicePresidentName && (
|
|
<div className="bg-violet-50/80 border border-violet-100 hover:border-violet-300 transition-colors rounded-2xl p-3.5 flex items-center gap-3">
|
|
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-violet-500 to-violet-600 text-white flex items-center justify-center shadow-xs shadow-violet-200 shrink-0">
|
|
<Users className="w-5 h-5 text-white" />
|
|
</div>
|
|
<div>
|
|
<span className="text-[11px] text-violet-500 font-semibold block">Vice President</span>
|
|
<span className="text-sm font-bold text-violet-950">{selectedClub.vicePresidentName}</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Contact Email */}
|
|
{selectedClub.contactEmail && (
|
|
<div className="bg-emerald-50/80 border border-emerald-100 hover:border-emerald-300 transition-colors rounded-2xl p-3.5 flex items-center gap-3 col-span-1 sm:col-span-2">
|
|
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-emerald-500 to-emerald-600 text-white flex items-center justify-center shadow-xs shadow-emerald-200 shrink-0">
|
|
<Mail className="w-5 h-5 text-white" />
|
|
</div>
|
|
<div className="min-w-0 flex-1">
|
|
<span className="text-[11px] text-emerald-500 font-semibold block">Contact Email</span>
|
|
<a href={`mailto:${selectedClub.contactEmail}`} className="text-sm font-bold text-emerald-700 hover:text-emerald-800 hover:underline truncate block">
|
|
{selectedClub.contactEmail}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Social & Community Links */}
|
|
{Boolean(
|
|
selectedClub.socialLinks?.instagram ||
|
|
selectedClub.socialLinks?.linkedin ||
|
|
selectedClub.socialLinks?.whatsapp ||
|
|
selectedClub.socialLinks?.youtube
|
|
) && (
|
|
<div className="mb-6 bg-orange-50/60 border border-orange-200/80 rounded-2xl p-4">
|
|
<div className="flex items-center justify-between mb-3">
|
|
<div className="flex items-center gap-2 text-xs font-bold text-[#F97316] uppercase tracking-wider">
|
|
<ExternalLink className="w-3.5 h-3.5" />
|
|
<span>Social & Community Links</span>
|
|
</div>
|
|
<span className="text-[10px] text-emerald-600 font-medium">✓ Verified RIT Entity</span>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 gap-2.5">
|
|
|
|
{selectedClub.socialLinks?.instagram && (
|
|
<a
|
|
href={selectedClub.socialLinks.instagram}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center gap-2 p-2.5 rounded-xl bg-white border border-slate-200 hover:border-pink-500 hover:text-pink-600 transition-all text-xs font-medium text-slate-700"
|
|
>
|
|
<InstagramIcon className="w-4 h-4 text-pink-500 shrink-0" />
|
|
<span className="truncate">Instagram</span>
|
|
</a>
|
|
)}
|
|
|
|
{selectedClub.socialLinks?.linkedin && (
|
|
<a
|
|
href={selectedClub.socialLinks.linkedin}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center gap-2 p-2.5 rounded-xl bg-white border border-slate-200 hover:border-blue-600 hover:text-blue-600 transition-all text-xs font-medium text-slate-700"
|
|
>
|
|
<LinkedinIcon className="w-4 h-4 text-blue-600 shrink-0" />
|
|
<span className="truncate">LinkedIn</span>
|
|
</a>
|
|
)}
|
|
|
|
{selectedClub.socialLinks?.whatsapp && (
|
|
<a
|
|
href={selectedClub.socialLinks.whatsapp}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center gap-2 p-2.5 rounded-xl bg-white border border-slate-200 hover:border-emerald-500 hover:text-emerald-600 transition-all text-xs font-medium text-slate-700"
|
|
>
|
|
<MessageCircle className="w-4 h-4 text-emerald-500 shrink-0" />
|
|
<span className="truncate">WhatsApp Group</span>
|
|
</a>
|
|
)}
|
|
|
|
{selectedClub.socialLinks?.youtube && (
|
|
<a
|
|
href={selectedClub.socialLinks.youtube}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center gap-2 p-2.5 rounded-xl bg-white border border-slate-200 hover:border-red-600 hover:text-red-600 transition-all text-xs font-medium text-slate-700"
|
|
>
|
|
<YoutubeIcon className="w-4 h-4 text-red-600 shrink-0" />
|
|
<span className="truncate">YouTube Channel</span>
|
|
</a>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Close Button */}
|
|
<div>
|
|
<button
|
|
onClick={() => setSelectedClub(null)}
|
|
className="w-full py-3 rounded-xl border border-slate-300 text-slate-700 font-semibold text-sm hover:bg-slate-100 transition-all cursor-pointer"
|
|
style={{ fontFamily: 'Poppins, sans-serif' }}
|
|
>
|
|
Close
|
|
</button>
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
)}
|
|
</AnimatePresence>
|
|
</div>
|
|
);
|
|
}
|