diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 2599148..9509fbc 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,7 +1,11 @@ # ─── DATABASE CONNECTION CONFIGURATION ─── spring.datasource.url=jdbc:postgresql://localhost:5432/rit_freshers_hub?sslmode=disable spring.datasource.username=postgres +<<<<<<< Updated upstream spring.datasource.password=your_local_postgres_password_here +======= +spring.datasource.password=${DB_PASSWORD:Amudiesh22@.} +>>>>>>> Stashed changes # ─── JPA / HIBERNATE SETTINGS ─── spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect diff --git a/public/clubs/artist_league.png b/public/clubs/artist_league.png new file mode 100644 index 0000000..39e387b Binary files /dev/null and b/public/clubs/artist_league.png differ diff --git a/public/clubs/fusion.png b/public/clubs/fusion.png new file mode 100644 index 0000000..2c83a27 Binary files /dev/null and b/public/clubs/fusion.png differ diff --git a/public/clubs/helios.png b/public/clubs/helios.png new file mode 100644 index 0000000..0b55eef Binary files /dev/null and b/public/clubs/helios.png differ diff --git a/public/clubs/infinitus.png b/public/clubs/infinitus.png new file mode 100644 index 0000000..88530d8 Binary files /dev/null and b/public/clubs/infinitus.png differ diff --git a/public/clubs/mediastic.png b/public/clubs/mediastic.png new file mode 100644 index 0000000..c487799 Binary files /dev/null and b/public/clubs/mediastic.png differ diff --git a/public/clubs/nippon.png b/public/clubs/nippon.png new file mode 100644 index 0000000..c0ae165 Binary files /dev/null and b/public/clubs/nippon.png differ diff --git a/public/clubs/nss.png b/public/clubs/nss.png new file mode 100644 index 0000000..2800780 Binary files /dev/null and b/public/clubs/nss.png differ diff --git a/public/clubs/podx.png b/public/clubs/podx.png new file mode 100644 index 0000000..80cf510 Binary files /dev/null and b/public/clubs/podx.png differ diff --git a/public/clubs/rotaract.png b/public/clubs/rotaract.png new file mode 100644 index 0000000..c0d199c Binary files /dev/null and b/public/clubs/rotaract.png differ diff --git a/public/clubs/steam.png b/public/clubs/steam.png new file mode 100644 index 0000000..5d2313d Binary files /dev/null and b/public/clubs/steam.png differ diff --git a/public/clubs/stellar_space_tech.png b/public/clubs/stellar_space_tech.png new file mode 100644 index 0000000..d5e96f6 Binary files /dev/null and b/public/clubs/stellar_space_tech.png differ diff --git a/public/clubs/techspark.png b/public/clubs/techspark.png new file mode 100644 index 0000000..c7df579 Binary files /dev/null and b/public/clubs/techspark.png differ diff --git a/public/clubs/unnat_bharat.png b/public/clubs/unnat_bharat.png new file mode 100644 index 0000000..604b250 Binary files /dev/null and b/public/clubs/unnat_bharat.png differ diff --git a/public/clubs/vaarithi.png b/public/clubs/vaarithi.png new file mode 100644 index 0000000..733b8a0 Binary files /dev/null and b/public/clubs/vaarithi.png differ diff --git a/public/clubs/wec.png b/public/clubs/wec.png new file mode 100644 index 0000000..b723172 Binary files /dev/null and b/public/clubs/wec.png differ diff --git a/public/clubs/wistem.png b/public/clubs/wistem.png new file mode 100644 index 0000000..e890e88 Binary files /dev/null and b/public/clubs/wistem.png differ diff --git a/public/clubs/yuva.png b/public/clubs/yuva.png new file mode 100644 index 0000000..d782f77 Binary files /dev/null and b/public/clubs/yuva.png differ diff --git a/public/images.jpg b/public/images.jpg new file mode 100644 index 0000000..59cf058 Binary files /dev/null and b/public/images.jpg differ diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000..40bcff7 Binary files /dev/null and b/public/logo.png differ diff --git a/public/video/RIT Video.mp4 b/public/video/RIT Video.mp4 new file mode 100644 index 0000000..fdd0fde Binary files /dev/null and b/public/video/RIT Video.mp4 differ diff --git a/src/App.tsx b/src/App.tsx index 2af09b6..8782fbe 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,5 @@ -import { BrowserRouter, Routes, Route } from 'react-router-dom'; +import { useEffect } from 'react'; +import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import MainLayout from '@/layouts/MainLayout'; import Home from '@/pages/Home/Home'; @@ -18,10 +19,21 @@ const queryClient = new QueryClient({ }, }); +function ScrollToTop() { + const { pathname } = useLocation(); + + useEffect(() => { + window.scrollTo(0, 0); + }, [pathname]); + + return null; +} + function App() { return ( + }> } /> diff --git a/src/assets/campus.mp4 b/src/assets/campus.mp4 new file mode 100644 index 0000000..e69de29 diff --git a/src/components/FacultyCard/FacultyCard.tsx b/src/components/FacultyCard/FacultyCard.tsx index e29767e..d804758 100644 --- a/src/components/FacultyCard/FacultyCard.tsx +++ b/src/components/FacultyCard/FacultyCard.tsx @@ -1,5 +1,7 @@ -import { motion } from 'framer-motion'; -import { Mail, Phone, Building2, User } from 'lucide-react'; +import { useState } from 'react'; +import { createPortal } from 'react-dom'; +import { motion, AnimatePresence } from 'framer-motion'; +import { Mail, Phone, Building2, User, X, BookOpen, ChevronRight, Monitor, Command, GraduationCap, Briefcase, Microscope, Clock } from 'lucide-react'; import type { Faculty } from '@/types'; interface FacultyCardProps { @@ -16,6 +18,9 @@ const AVATAR_COLORS = [ ]; export default function FacultyCard({ faculty }: FacultyCardProps) { + const [showModal, setShowModal] = useState(false); + const [showEmailOptions, setShowEmailOptions] = useState(false); + const colorIndex = parseInt(faculty.id) % AVATAR_COLORS.length; const [from, to] = AVATAR_COLORS[colorIndex]; const initials = faculty.name @@ -24,73 +29,359 @@ export default function FacultyCard({ faculty }: FacultyCardProps) { .map((n) => n[0]) .join(''); + const mailOptions = [ + { name: 'Default Mail App', url: `mailto:${faculty.email}`, icon: Monitor, color: 'text-gray-700', bg: 'bg-gray-100' }, + { name: 'Gmail', url: `https://mail.google.com/mail/?view=cm&fs=1&to=${faculty.email}`, icon: Mail, color: 'text-red-500', bg: 'bg-red-50' }, + { name: 'Outlook', url: `https://outlook.office.com/mail/deeplink/compose?to=${faculty.email}`, icon: Mail, color: 'text-blue-600', bg: 'bg-blue-50' }, + { name: 'Yahoo Mail', url: `https://compose.mail.yahoo.com/?to=${faculty.email}`, icon: Mail, color: 'text-purple-600', bg: 'bg-purple-50' }, + ]; + return ( - - {/* Avatar + Name */} -
-
- {initials} + <> + + {/* Avatar + Name */} +
+
+
+ {initials} +
+ {/* Online Indicator */} +
+
+
+

+ {faculty.name} +

+

+ {faculty.designation} +

+
-
-

- {faculty.name} -

-

- {faculty.designation} -

-
-
- {/* Details */} -
-
- - {faculty.department} -
- {faculty.office && ( + {/* Details */} +
- - {faculty.office} + + {faculty.department}
- )} - {faculty.specialization && ( -
- {faculty.specialization} -
- )} -
+
- {/* Contact */} -
- - - Email - - {faculty.phone && ( - + + +
+
+ + {/* Profile Modal */} + {createPortal( + + {showModal && ( +
+ setShowModal(false)} + className="absolute inset-0 bg-[#0F172A]/40 backdrop-blur-sm" + /> + + + +
+ {/* LEFT PANEL */} +
+
+
+ {initials} +
+

+ {faculty.name} +

+

+ {faculty.designation} +

+

+ {faculty.department} +

+ +
+ +
+ + + {faculty.phone && ( + +
+ +
+
+

Phone Number

+

{faculty.phone}

+
+
+ )} +
+
+
+ + {/* RIGHT PANEL */} +
+ {/* Section 1: Professional Details */} +
+
+
+ +
+

Professional Details

+
+
+
+

Department

+

{faculty.department}

+
+
+

Specialization

+

{faculty.specialization || 'Not specified'}

+
+
+

Qualification

+

{faculty.qualification || 'Not specified'}

+
+
+

Experience

+

{faculty.experience || 'Not specified'}

+
+ {faculty.joinedInstitution && ( +
+

Joined Institution

+

{faculty.joinedInstitution}

+
+ )} +
+
+ + {/* Section 2: Academic Info */} +
+
+
+ +
+

Academic Information

+
+
+
+

Subjects Handling

+

{faculty.subjectsHandling || 'Not specified'}

+
+
+

Research Areas

+

{faculty.researchAreas || 'Not specified'}

+
+ {faculty.studentsGuided && ( +
+

Students Guided

+
+
+ {faculty.studentsGuided.ug} + UG +
+
+ {faculty.studentsGuided.pg} + PG +
+
+ {faculty.studentsGuided.phd} + Ph.D. +
+
+
+ )} +
+
+ + {/* Section 3: Achievements (Render only if present) */} + {(faculty.achievements || faculty.publications) && ( +
+
+
+ +
+

Achievements

+
+
+ {faculty.achievements && faculty.achievements.length > 0 && ( +
+

Awards & Certifications

+
    + {faculty.achievements.map((ach, i) => ( +
  • {ach}
  • + ))} +
+
+ )} + {faculty.publications && faculty.publications.length > 0 && ( +
+

Recent Publications

+
    + {faculty.publications.map((pub, i) => ( +
  • {pub}
  • + ))} +
+
+ )} +
+
+ )} + + {/* Section 4: Office Info */} +
+
+
+ +
+

Office Information

+
+
+
+ +
+

Office Hours

+

{faculty.officeHours || 'Not specified'}

+
+
+
+ +
+

Office Location

+

{faculty.office || 'Not specified'}

+
+
+
+
+
+
+
+
)} -
- + , + document.body + )} + + {/* Email Options Modal */} + {createPortal( + + {showEmailOptions && ( +
+ setShowEmailOptions(false)} + className="absolute inset-0 bg-[#0F172A]/40 backdrop-blur-sm" + /> + +
+
+

Choose Mail App

+

Compose email to {faculty.name}

+
+ +
+ + +
+
+ )} +
, + document.body + )} + ); } diff --git a/src/components/FeatureCard/FeatureCard.tsx b/src/components/FeatureCard/FeatureCard.tsx index 9f3a887..0867686 100644 --- a/src/components/FeatureCard/FeatureCard.tsx +++ b/src/components/FeatureCard/FeatureCard.tsx @@ -9,7 +9,7 @@ interface FeatureCardProps { } export default function FeatureCard({ feature }: FeatureCardProps) { - const IconComponent = (LucideIcons as Record>)[feature.icon]; + const IconComponent = (LucideIcons as unknown as Record>)[feature.icon]; return (
{/* Logo - RIT Event Hub Style */} - - {/* Blue Circular Tree Icon */} - + {/* Logo Image */} + - - {/* Minimalist Tree Branch Representation */} - - - - - - - - - - - - + src="/logo.png" + alt="RIT Logo" + className="w-10 h-10 object-contain rounded-full shrink-0" + />
- + rit -
-
+
+
RAJALAKSHMI INSTITUTE OF TECHNOLOGY
- + {/* Desktop Nav */}
@@ -85,14 +69,14 @@ export default function Navbar() { className="relative px-4 py-2 rounded-xl text-xs font-semibold uppercase tracking-wider transition-all duration-200" style={{ fontFamily: 'Poppins, sans-serif', - color: isActive ? '#F97316' : '#475569', + color: isActive ? '#FFFFFF' : '#CBD5E1', }} > {isActive && ( )} @@ -104,35 +88,11 @@ export default function Navbar() { {/* Right Side */}
- - - - - {/* Profile styled as an orange LOG OUT pill button from Reference Image */} - - - Profile - - - {/* Mobile Toggle */} setIsMobileOpen(!isMobileOpen)} - className="md:hidden w-9 h-9 rounded-xl flex items-center justify-center text-[#475569] hover:bg-gray-100 transition-all" + className="md:hidden w-9 h-9 rounded-xl flex items-center justify-center text-slate-300 hover:text-white hover:bg-white/10 transition-all" aria-label="Toggle menu" > {isMobileOpen ? : } @@ -150,7 +110,7 @@ export default function Navbar() { transition={{ duration: 0.25 }} className="overflow-hidden md:hidden" > -
+
{NAV_LINKS.map((link) => { const isActive = location.pathname === link.path; return ( @@ -160,8 +120,8 @@ export default function Navbar() { className="px-4 py-3 rounded-xl text-sm font-medium transition-all" style={{ fontFamily: 'Inter, sans-serif', - color: isActive ? '#F97316' : '#475569', - backgroundColor: isActive ? '#FFF7ED' : 'transparent', + color: isActive ? '#FFFFFF' : '#CBD5E1', + backgroundColor: isActive ? '#F97316' : 'transparent', }} > {link.label} diff --git a/src/constants/index.ts b/src/constants/index.ts index b032620..eb3d9d1 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -6,17 +6,17 @@ export const NAV_LINKS = [ { label: 'Notes', path: '/notes' }, { label: 'AI Assistant', path: '/ai-assistant' }, { label: 'Campus', path: '/campus' }, - { label: 'Events', path: '/events' }, + { label: 'Clubs', path: '/events' }, { label: 'Community', path: '/community' }, ]; // ─── Stats ──────────────────────────────────────────────────────────────────── export const STATS: Stat[] = [ - { value: 150, suffix: '+', label: 'PYQs', icon: 'FileText' }, - { value: 40, suffix: '+', label: 'Faculty', icon: 'Users' }, - { value: 25, suffix: '+', label: 'Clubs', icon: 'Star' }, + { value: 20, suffix: '+', label: 'Sports', icon: 'Trophy' }, + { value: 100, suffix: '+', label: 'Faculty', icon: 'Users' }, + { value: 18, suffix: '', label: 'Clubs', icon: 'Star' }, { value: 24, suffix: '/7', label: 'AI Assistant', icon: 'Bot' }, - { value: 1000, suffix: '+', label: 'Students', icon: 'GraduationCap' }, + { value: 5000, suffix: '+', label: 'Students', icon: 'GraduationCap' }, ]; // ─── Features ──────────────────────────────────────────────────────────────── @@ -77,9 +77,9 @@ export const FEATURES: Feature[] = [ }, { id: 'events', - icon: 'Calendar', - title: 'Clubs & Events', - description: 'Discover clubs, upcoming events, workshops, and cultural programs at RIT.', + icon: 'Users', + title: 'Student Clubs', + description: 'Discover official RIT student clubs, technology domains, leadership, and contacts.', path: '/events', color: '#EF4444', bgColor: '#FEF2F2', @@ -179,55 +179,302 @@ export const FACULTY_DATA: Faculty[] = [ name: 'Dr. S. Ramesh Kumar', designation: 'Professor & HOD', department: 'Computer Science & Engineering', - email: 'ramesh@rit.edu', office: 'CSE Block, Room 301', - specialization: 'Machine Learning, AI', + specialization: 'Machine Learning, Artificial Intelligence', + email: 'ramesh@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '18 Years', + subjectsHandling: 'Machine Learning, Artificial Intelligence, Data Mining', + researchAreas: 'AI, Deep Learning, Computer Vision', + officeHours: 'Mon–Fri, 10:00 AM–12:00 PM', + phone: '+91 98765 43001', }, { id: '2', - name: 'Dr. P. Mahalakshmi', - designation: 'Associate Professor', - department: 'Electronics & Communication', - email: 'mahalakshmi@rit.edu', - office: 'ECE Block, Room 205', - specialization: 'VLSI Design, Embedded Systems', - }, - { - id: '3', - name: 'Prof. R. Vijayakumar', - designation: 'Assistant Professor', - department: 'Mechanical Engineering', - email: 'vijay@rit.edu', - office: 'MECH Block, Room 102', - specialization: 'CAD/CAM, Robotics', - }, - { - id: '4', - name: 'Dr. K. Anitha', - designation: 'Professor', - department: 'Information Technology', - email: 'anitha@rit.edu', - office: 'IT Block, Room 401', - specialization: 'Data Science, Cloud Computing', - }, - { - id: '5', - name: 'Prof. M. Selvakumar', - designation: 'Associate Professor', - department: 'Civil Engineering', - email: 'selva@rit.edu', - office: 'CIVIL Block, Room 110', - specialization: 'Structural Engineering', - }, - { - id: '6', name: 'Dr. S. Priya', designation: 'Assistant Professor', department: 'Computer Science & Engineering', - email: 'priya@rit.edu', office: 'CSE Block, Room 205', - specialization: 'Cyber Security, Networks', + specialization: 'Cyber Security, Computer Networks', + email: 'priya@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '8 Years', + subjectsHandling: 'Network Security, Computer Networks, Ethical Hacking', + researchAreas: 'Cyber Security, IoT Security', + officeHours: 'Mon–Fri, 2:00 PM–4:00 PM', + phone: '+91 98765 43002', }, + { + id: '3', + name: 'Dr. K. Aravind', + designation: 'Associate Professor', + department: 'Computer Science & Engineering', + office: 'CSE Block, Room 212', + specialization: 'Cloud Computing, Distributed Systems', + email: 'aravind@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '11 Years', + subjectsHandling: 'Cloud Computing, Distributed Systems, Operating Systems', + researchAreas: 'Cloud Infrastructure, Edge Computing', + officeHours: 'Mon–Fri, 9:30 AM–11:30 AM', + phone: '+91 98765 43003', + }, + + { + id: '6', + name: 'Dr. P. Mahalakshmi', + designation: 'Associate Professor', + department: 'Electronics & Communication Engineering', + office: 'ECE Block, Room 205', + specialization: 'VLSI Design, Embedded Systems', + email: 'mahalakshmi@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '13 Years', + subjectsHandling: 'VLSI Design, Embedded Systems', + researchAreas: 'Chip Design, IoT Devices', + officeHours: 'Mon–Fri, 10:00 AM–12:00 PM', + phone: '+91 98765 43006', + }, + { + id: '7', + name: 'Dr. V. Prakash', + designation: 'Professor', + department: 'Electronics & Communication Engineering', + office: 'ECE Block, Room 310', + specialization: 'Digital Signal Processing, IoT', + email: 'prakash@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '17 Years', + subjectsHandling: 'DSP, IoT, Microprocessors', + researchAreas: 'Wireless Systems, Signal Processing', + officeHours: 'Mon–Fri, 2:00 PM–4:00 PM', + phone: '+91 98765 43007', + }, + { + id: '8', + name: 'Dr. A. Deepika', + designation: 'Assistant Professor', + department: 'Electronics & Communication Engineering', + office: 'ECE Block, Room 214', + specialization: 'Wireless Communication, 5G Networks', + email: 'deepika@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '6 Years', + subjectsHandling: 'Wireless Networks, Mobile Communication', + researchAreas: '5G, IoT Networks', + officeHours: 'Mon–Fri, 9:00 AM–11:00 AM', + phone: '+91 98765 43008', + }, + { + id: '9', + name: 'Prof. R. Vijayakumar', + designation: 'Assistant Professor', + department: 'Mechanical Engineering', + office: 'MECH Block, Room 102', + specialization: 'CAD/CAM, Robotics', + email: 'vijayakumar@rit.edu', + qualification: 'B.E., M.E.', + experience: '9 Years', + subjectsHandling: 'CAD/CAM, Robotics', + researchAreas: 'Industrial Automation', + officeHours: 'Mon–Fri, 11:00 AM–1:00 PM', + phone: '+91 98765 43009', + }, + { + id: '10', + name: 'Dr. S. Manikandan', + designation: 'Associate Professor', + department: 'Mechanical Engineering', + office: 'MECH Block, Room 118', + specialization: 'Thermal Engineering, Manufacturing', + email: 'manikandan@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '12 Years', + subjectsHandling: 'Manufacturing Technology, Thermal Engineering', + researchAreas: 'Renewable Energy, Thermal Systems', + officeHours: 'Mon–Fri, 1:00 PM–3:00 PM', + phone: '+91 98765 43010', + }, + { + id: '11', + name: 'Prof. M. Selvakumar', + designation: 'Associate Professor', + department: 'Civil Engineering', + office: 'CIVIL Block, Room 110', + specialization: 'Structural Engineering', + email: 'selvakumar@rit.edu', + qualification: 'B.E., M.E.', + experience: '14 Years', + subjectsHandling: 'Structural Analysis, RCC Design', + researchAreas: 'Earthquake Resistant Structures', + officeHours: 'Mon–Fri, 10:00 AM–12:00 PM', + phone: '+91 98765 43011', + }, + { + id: '12', + name: 'Dr. J. Revathi', + designation: 'Assistant Professor', + department: 'Civil Engineering', + office: 'CIVIL Block, Room 123', + specialization: 'Environmental Engineering, Surveying', + email: 'revathi@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '8 Years', + subjectsHandling: 'Surveying, Environmental Engineering', + researchAreas: 'Water Resource Management', + officeHours: 'Mon–Fri, 2:00 PM–4:00 PM', + phone: '+91 98765 43012', + }, + { + id: '13', + name: 'Dr. N. Hariharan', + designation: 'Professor & HOD', + department: 'Artificial Intelligence & Data Science', + office: 'AIDS Block, Room 501', + specialization: 'Deep Learning, Data Mining', + email: 'hariharan@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '19 Years', + subjectsHandling: 'Deep Learning, Data Mining, AI', + researchAreas: 'Artificial Intelligence, Predictive Analytics', + officeHours: 'Mon–Fri, 9:30 AM–11:30 AM', + phone: '+91 98765 43013', + }, + { + id: '14', + name: 'Dr. P. Divya', + designation: 'Assistant Professor', + department: 'Artificial Intelligence & Data Science', + office: 'AIDS Block, Room 505', + specialization: 'Natural Language Processing, Computer Vision', + email: 'divya@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '7 Years', + subjectsHandling: 'NLP, Computer Vision', + researchAreas: 'Generative AI, Image Processing', + officeHours: 'Mon–Fri, 1:00 PM–3:00 PM', + phone: '+91 98765 43014', + }, + { + id: '15', + name: 'Dr. L. Karthikeyan', + designation: 'Associate Professor', + department: 'Electrical & Electronics Engineering', + office: 'EEE Block, Room 303', + specialization: 'Power Systems, Renewable Energy', + email: 'karthikeyan@rit.edu', + qualification: 'B.E., M.E., Ph.D.', + experience: '15 Years', + subjectsHandling: 'Power Systems, Electrical Machines', + researchAreas: 'Smart Grid, Solar Energy', + officeHours: 'Mon–Fri, 10:00 AM–12:00 PM', + phone: '+91 98765 43015', + }, + { + id: '16', + name: 'Dr. M. Murugan', + designation: 'Associate Professor', + department: 'Computer Science & Engineering', + office: 'CSE Block, Room 218', + specialization: 'Artificial Intelligence, Machine Learning', + email: 'murugan@rit.edu', + qualification: 'B.E. (CSE), M.E. (Computer Science & Engineering), Ph.D. (Artificial Intelligence)', + experience: '13 Years', + subjectsHandling: 'Artificial Intelligence, Machine Learning, Python Programming, Data Mining', + researchAreas: 'Deep Learning, Computer Vision, Natural Language Processing, Explainable AI', + officeHours: 'Mon–Fri, 10:00 AM–12:00 PM', + phone: '+91 98765 43125', + }, + { + id: '17', + name: 'Dr. R. Balamurugan', + designation: 'Associate Professor', + department: 'Computer Science & Business Systems', + office: 'CSBS Block, Room 305', + specialization: 'Business Analytics, Data Science', + email: 'balamurugan@rit.edu', + qualification: 'B.E. (CSE), M.B.A., M.E. (Software Engineering), Ph.D. (Business Analytics)', + experience: '12 Years', + subjectsHandling: 'Business Analytics, Data Analytics, Database Management Systems, Python for Business Applications', + researchAreas: 'Business Intelligence, Data Analytics, Digital Transformation, Decision Support Systems', + officeHours: 'Mon–Fri, 9:30 AM–11:30 AM', + phone: '+91 98765 43221', + }, + { + id: '18', + name: 'Dr. K. Nandhini', + designation: 'Assistant Professor', + department: 'Artificial Intelligence & Machine Learning', + office: 'AIML Block, Room 412', + specialization: 'Artificial Intelligence, Machine Learning', + email: 'nandhini@rit.edu', + qualification: 'B.E. (CSE), M.Tech. (Artificial Intelligence), Ph.D. (Machine Learning)', + experience: '8 Years', + subjectsHandling: 'Artificial Intelligence, Machine Learning, Deep Learning, Python Programming', + researchAreas: 'Generative AI, Computer Vision, Explainable AI, Neural Networks', + officeHours: 'Mon–Fri, 2:00 PM–4:00 PM', + phone: '+91 98765 43222', + }, + { + id: '19', + name: 'Dr. S. Rajeshwari', + designation: 'Professor', + department: 'Computer Science & Business Systems', + office: 'CSBS Block, Room 302', + specialization: 'Business Intelligence, Enterprise Systems', + email: 'rajeshwari@rit.edu', + qualification: 'B.E. (CSE), M.E. (Computer Science), Ph.D. (Business Intelligence)', + experience: '16 Years', + subjectsHandling: 'Business Intelligence, Enterprise Systems, Software Engineering, Project Management', + researchAreas: 'Business Intelligence, Enterprise Computing, ERP Systems', + officeHours: 'Mon–Fri, 10:00 AM–12:00 PM', + phone: '+91 98765 43223', + }, + { + id: '20', + name: 'Dr. V. Pradeep Kumar', + designation: 'Assistant Professor', + department: 'Computer Science & Business Systems', + office: 'CSBS Block, Room 308', + specialization: 'FinTech, Cloud Computing', + email: 'pradeepkumar@rit.edu', + qualification: 'B.E. (IT), M.Tech. (Cloud Computing), Ph.D. (Financial Technology)', + experience: '7 Years', + subjectsHandling: 'Cloud Computing, FinTech Applications, Data Structures, Java Programming', + researchAreas: 'Cloud Security, Financial Analytics, Blockchain Technology', + officeHours: 'Mon–Fri, 1:00 PM–3:00 PM', + phone: '+91 98765 43224', + }, + { + id: '21', + name: 'Dr. P. Harini', + designation: 'Associate Professor', + department: 'Artificial Intelligence & Machine Learning', + office: 'AIML Block, Room 408', + specialization: 'Deep Learning, Computer Vision', + email: 'harini@rit.edu', + qualification: 'B.E. (CSE), M.Tech. (Artificial Intelligence), Ph.D. (Computer Vision)', + experience: '10 Years', + subjectsHandling: 'Deep Learning, Computer Vision, Image Processing, Python Programming', + researchAreas: 'Medical Image Analysis, Deep Neural Networks, AI in Healthcare', + officeHours: 'Mon–Fri, 9:00 AM–11:00 AM', + phone: '+91 98765 43225', + }, + { + id: '22', + name: 'Dr. A. Vignesh', + designation: 'Assistant Professor', + department: 'Artificial Intelligence & Machine Learning', + office: 'AIML Block, Room 415', + specialization: 'Natural Language Processing, Generative AI', + email: 'vignesh@rit.edu', + qualification: 'B.E. (CSE), M.E. (Artificial Intelligence), Ph.D. (Natural Language Processing)', + experience: '6 Years', + subjectsHandling: 'Natural Language Processing, Generative AI, Machine Learning, Data Science', + researchAreas: 'Large Language Models, Conversational AI, Explainable AI', + officeHours: 'Mon–Fri, 2:00 PM–4:00 PM', + phone: '+91 98765 43226', + } ]; // ─── Events ────────────────────────────────────────────────────────────────── @@ -280,12 +527,300 @@ export const EVENTS_DATA: Event[] = [ // ─── Clubs ─────────────────────────────────────────────────────────────────── export const CLUBS_DATA: Club[] = [ - { id: '1', name: 'Coding Club', description: 'For programming enthusiasts', category: 'Technical', members: 120 }, - { id: '2', name: 'Robotics Club', description: 'Build and code robots', category: 'Technical', members: 85 }, - { id: '3', name: 'Photography Club', description: 'Capture campus moments', category: 'Creative', members: 60 }, - { id: '4', name: 'Music Club', description: 'Classical and contemporary music', category: 'Cultural', members: 95 }, - { id: '5', name: 'Drama Club', description: 'Theatre and performing arts', category: 'Cultural', members: 45 }, - { id: '6', name: 'NSS', description: 'National Service Scheme', category: 'Social', members: 200 }, + { + id: 'stellar_space_tech', + name: 'STELLAR SPACE TECH CLUB', + description: 'Space technology, astronomy, satellite systems, and space science exploration at RIT.', + details: 'RIT Stellar Space Tech Club brings together space enthusiasts, students, and aspiring aerospace engineers to explore astronomy, satellite communication, rocketry, and cutting-edge space technology through workshops, observational sessions, and technical projects.', + category: 'Technical', + members: 94, + presidentName: 'Student Space Lead', + year: 'Senior Year', + contactEmail: 'spacetech@ritchennai.edu.in', + contactPhone: '+91 98765 43210', + icon: 'Rocket', + logoUrl: '/clubs/stellar_space_tech.png', + socialLinks: { + instagram: 'https://www.instagram.com/stellarspacetechclub/', + }, + }, + { + id: 'podx', + name: 'podX-RIT (PODCAST CLUB)', + description: 'Real talks. Raw feels. Because every story deserves to be heard. Official Podcast Club of RIT.', + details: 'podX-RIT is the official Podcast and Radio Club of Rajalakshmi Institute of Technology. Bringing student stories, Switcheroo interviews, RJ sessions, and inspiring student & faculty conversations to life.', + category: 'Creative', + members: 1097, + presidentName: 'Lead RJ / Podcaster', + year: 'Senior Year', + contactEmail: 'podx@ritchennai.edu.in', + contactPhone: '+91 98765 43211', + icon: 'Mic', + logoUrl: '/clubs/podx.png', + socialLinks: { + instagram: 'https://www.instagram.com/podxrit/', + website: 'https://linktr.ee/podxrit', + }, + }, + { + id: 'nss', + name: 'NSS OF RIT', + description: 'National Service Scheme – "Not Me, But You." Official Social Service Club of RIT.', + details: 'NSS of Rajalakshmi Institute of Technology engages students in community service, social awareness drives, blood donation camps, road safety campaigns, and nation-building initiatives.', + category: 'Social', + members: 1306, + presidentName: 'NSS Student Lead', + year: 'Final Year', + contactEmail: 'nss@ritchennai.edu.in', + contactPhone: '+91 98765 43212', + icon: 'HeartHandshake', + logoUrl: '/clubs/nss.png', + socialLinks: { + instagram: 'https://www.instagram.com/nss.rit/', + }, + }, + { + id: 'artist_league', + name: 'ARTIST LEAGUE (CULTURAL CELL)', + description: 'Official Cultural Cell of RIT covering Dance (R-Square), Band (Euphoria), Rap & Classical.', + details: 'Artist League is the umbrella cultural organization of RIT incorporating R-Square (Dance), Euphoria (Band), Raptology (Rap), and Classic Beat (Classical). It organizes cultural fests, talent shows, and 60 Seconds to Fame competitions.', + category: 'Creative', + members: 1093, + presidentName: 'Cultural Secretary', + year: 'Final Year', + contactEmail: 'artistleague@ritchennai.edu.in', + contactPhone: '+91 98765 43213', + icon: 'Sparkles', + logoUrl: '/clubs/artist_league.png', + socialLinks: { + instagram: 'https://www.instagram.com/artist_league_rit/', + }, + }, + { + id: 'infinitus', + name: 'INFINITUS CLUB (MATHS CLUB)', + description: 'Where Logic Meets Innovation. Mathematics workshops, PiDoku, GraphQuest & tech competitions.', + details: 'Infinitus Club is the official Mathematics & Aptitude Club of RIT, hosting Pi-Quest, PiDoku Decode π, GraphQuest, logic puzzles, speed calculations, and analytical problem-solving workshops.', + category: 'Technical', + members: 557, + presidentName: 'Mathematics Lead', + year: 'Third Year', + contactEmail: 'infinitus@ritchennai.edu.in', + contactPhone: '+91 98765 43214', + icon: 'Calculator', + logoUrl: '/clubs/infinitus.png', + socialLinks: { + instagram: 'https://www.instagram.com/infinitus_club.rit/', + whatsapp: 'https://chat.whatsapp.com/LeCKYtgzdzJ5E6sL0WjYIHf', + }, + }, + { + id: 'vaarithi', + name: 'VAARITHI TAMIL CLUB', + description: 'இராசலட்சுமி தொழில்நுட்பக் கல்லூரியின் மாணவர் தமிழ் மன்றம் (RIT Tamil Mandram).', + details: 'Vaarithi Muthamizh Mandram of RIT celebrates Tamil literature, poetry, debate (Tamizhsudar), Tamil New Year celebrations, and preserving rich Tamil culture and heritage.', + category: 'Creative', + members: 848, + presidentName: 'Tamil Mandram Lead', + year: 'Final Year', + contactEmail: 'vaarithi@ritchennai.edu.in', + contactPhone: '+91 98765 43215', + icon: 'BookOpen', + logoUrl: '/clubs/vaarithi.png', + socialLinks: { + instagram: 'https://www.instagram.com/vaarithi_rit/', + }, + }, + { + id: 'fusion', + name: 'FUSION CLUB (ENGLISH & LITERATURE)', + description: 'A platform to delve into the beauty of language, literature, essays, and power of words.', + details: 'Fusion Club of RIT is the English Literary Club organizing essay writing contests, Lips Don’t Lie games, Fusion Treasure Hunt, debates, and creative writing workshops.', + category: 'Creative', + members: 815, + presidentName: 'Literary President', + year: 'Third Year', + contactEmail: 'fusionclub@ritchennai.edu.in', + contactPhone: '+91 98765 43216', + icon: 'Languages', + logoUrl: '/clubs/fusion.png', + socialLinks: { + instagram: 'https://www.instagram.com/fusionclub_rit/', + }, + }, + { + id: 'nippon', + name: 'NIPPON CLUB (JAPANESE CULTURE)', + description: 'Celebrating Japanese culture, language, anime, movie review nights & vibrant community.', + details: 'Nippon Club of RIT brings Japanese language learning, Kizuna Canvas relay drawing, Koe Nashi voice challenge, anime screenings, and Japanese cultural immersion to RIT students.', + category: 'Creative', + members: 649, + presidentName: 'Nippon President', + year: 'Third Year', + contactEmail: 'nippon@ritchennai.edu.in', + contactPhone: '+91 98765 43217', + icon: 'Globe', + logoUrl: '/clubs/nippon.png', + socialLinks: { + instagram: 'https://www.instagram.com/nippon_rit/', + }, + }, + { + id: 'unnat_bharat', + name: 'RIT UNNAT BHARAT ABHIYAN (UBA)', + description: 'Unite, socialize, thrive together! Official Social Impact & Rural Development Club.', + details: 'RIT Unnat Bharat Abhiyan (UBA) club focuses on sustainable village development, plantation drives, environmental awareness, and impactful social initiatives across rural Tamil Nadu.', + category: 'Social', + members: 1153, + presidentName: 'UBA Core Lead', + year: 'Final Year', + contactEmail: 'uba@ritchennai.edu.in', + contactPhone: '+91 98765 43218', + icon: 'Users', + logoUrl: '/clubs/unnat_bharat.png', + socialLinks: { + instagram: 'https://www.instagram.com/ritunnatbharatabhiyan/', + }, + }, + { + id: 'mediastic', + name: 'MEDIASTIC HUB (SOCIAL MEDIA CLUB)', + description: 'Official Social Media & Digital Content Creation Club of Rajalakshmi Institute of Technology.', + details: 'Mediastic Hub handles official video production, campus media coverage, event highlights for RobochipX & Quant-a-thon, photography exhibitions, and RIT digital channels.', + category: 'Creative', + members: 1351, + presidentName: 'Media Hub Lead', + year: 'Final Year', + contactEmail: 'mediastichub@ritchennai.edu.in', + contactPhone: '+91 98765 43219', + icon: 'Camera', + logoUrl: '/clubs/mediastic.png', + socialLinks: { + instagram: 'https://www.instagram.com/mediastichub_rit/', + youtube: 'https://www.youtube.com/@rajalakshmiinstituteoftech444', + }, + }, + { + id: 'helios', + name: 'HELIOS RIT (PHOTOGRAPHY CLUB)', + description: 'Capturing Life\'s Moments, One Frame at a Time. Showcasing cinematic shots & campus stories.', + details: 'Helios RIT Official is the premier photography and filmmaking club of RIT, capturing campus events, hosting photography contests, guest lectures, and showcasing cinematic stories of RIT.', + category: 'Creative', + members: 2455, + presidentName: 'Photography Lead', + year: 'Final Year', + contactEmail: 'helios@ritchennai.edu.in', + contactPhone: '+91 98765 43220', + icon: 'Camera', + logoUrl: '/clubs/helios.png', + socialLinks: { + instagram: 'https://www.instagram.com/helios.rit/', + }, + }, + { + id: 'techspark', + name: 'TECHSPARK CLUB RIT', + description: 'Where Tech meets creativity, Sparks fly! Fostering innovation in every byte.', + details: 'TechSpark Club RIT is the technical innovation club driving Web3 Camp Meets AI, GirlScript hackathons, Spark Booths, coding competitions, and hands-on developer projects.', + category: 'Technical', + members: 672, + presidentName: 'TechSpark Lead', + year: 'Third Year', + contactEmail: 'techspark@ritchennai.edu.in', + contactPhone: '+91 98765 43221', + icon: 'Zap', + logoUrl: '/clubs/techspark.png', + socialLinks: { + instagram: 'https://www.instagram.com/techspark.rit/', + whatsapp: 'https://chat.whatsapp.com/I8B5Wdybrew2dYYDrE4PG', + }, + }, + { + id: 'wec', + name: 'WOMEN EMPOWERMENT CELL (WEC)', + description: 'Empower • Excel • Elevate. Supporting women in technology, leadership & coding.', + details: 'Women Empowerment Cell (WEC RIT) organizes She Shines @ Hexaware coding challenges, Women’s Empowerment Week, ZYRA Days, leadership seminars, and career development initiatives.', + category: 'Social', + members: 428, + presidentName: 'Pooja WYA', + year: 'Final Year', + contactEmail: 'wec@ritchennai.edu.in', + contactPhone: '+91 98765 43222', + icon: 'Sparkles', + logoUrl: '/clubs/wec.png', + socialLinks: { + instagram: 'https://www.instagram.com/wec.rit/', + }, + }, + { + id: 'rotaract', + name: 'ROTARACT CLUB OF RIT (RCRIT)', + description: 'Embrace the joy of giving. Official Rotaract organization for leadership & service.', + details: 'Rotaract Club of RIT (RCRIT) under Rotary International sponsors Bloom mental health seminars, Phoenix fests, RITARIQ 365, Ryla leadership camps, and community blood donation drives.', + category: 'Social', + members: 1813, + presidentName: 'Hari Balaji', + year: 'Final Year', + contactEmail: 'rotaract@ritchennai.edu.in', + contactPhone: '+91 98765 43223', + icon: 'HeartHandshake', + logoUrl: '/clubs/rotaract.png', + socialLinks: { + instagram: 'https://www.instagram.com/rcrit/', + }, + }, + { + id: 'yuva', + name: 'Yi-CH YUVA RIT', + description: 'Official Page of YUVA Club RIT under Young Indians (Yi). Inspiring youth leadership.', + details: 'Yi-CH YUVA RIT leads Chennai Get Talent, Safe Miles road safety awareness, Blogathons, Tree Plantation drives (500 Trees Mission), and youth leadership conventions.', + category: 'Social', + members: 1460, + presidentName: 'YUVA Student Chair', + year: 'Final Year', + contactEmail: 'yuva@ritchennai.edu.in', + contactPhone: '+91 98765 43224', + icon: 'Rocket', + logoUrl: '/clubs/yuva.png', + socialLinks: { + instagram: 'https://www.instagram.com/yuva_rit/', + }, + }, + { + id: 'wistem', + name: 'WiSTEM CLUB OF RIT', + description: 'Women in STEM Club. AI Quests, STEM Chronicles, CodeVsClick & maker empowering events.', + details: 'WiSTEM Club of RIT empowers women in Science, Technology, Engineering, and Mathematics through AI Quests, STEM Chronicles newsletter, CodeVsClick contests, and technical workshops.', + category: 'Technical', + members: 453, + presidentName: 'WiSTEM Lead', + year: 'Third Year', + contactEmail: 'wistem@ritchennai.edu.in', + contactPhone: '+91 98765 43225', + icon: 'Atom', + logoUrl: '/clubs/wistem.png', + socialLinks: { + instagram: 'https://www.instagram.com/wistem._.rit/', + website: 'https://www.rityatra.in/', + }, + }, + { + id: 'steam', + name: 'STEAM CLUB RIT', + description: 'Innovate - Collaborate - Elevate. Hands-on RobochipX, Quant-a-thon & AI/Chip design.', + details: 'STEAM Club RIT focuses on hands-on project creation, RobochipX 24-hour hackathons, Quant-a-thon quantum technology events, chip design, and robotics innovations.', + category: 'Technical', + members: 895, + presidentName: 'STEAM President', + year: 'Final Year', + contactEmail: 'steamclub@ritchennai.edu.in', + contactPhone: '+91 98765 43226', + icon: 'Printer', + logoUrl: '/clubs/steam.png', + socialLinks: { + instagram: 'https://www.instagram.com/steam_club.rit/', + }, + }, ]; // ─── Community Q&A ─────────────────────────────────────────────────────────── @@ -390,10 +925,11 @@ export const AI_SUGGESTED_PROMPTS = [ export const DEPARTMENTS = [ 'All Departments', 'Computer Science & Engineering', - 'Electronics & Communication', + 'Computer Science & Business Systems', + 'Artificial Intelligence & Machine Learning', + 'Electronics & Communication Engineering', 'Mechanical Engineering', 'Civil Engineering', - 'Information Technology', - 'Electrical & Electronics', 'Artificial Intelligence & Data Science', + 'Electrical & Electronics Engineering', ]; diff --git a/src/pages/AIAssistant/AIAssistant.tsx b/src/pages/AIAssistant/AIAssistant.tsx index fdddb85..423daef 100644 --- a/src/pages/AIAssistant/AIAssistant.tsx +++ b/src/pages/AIAssistant/AIAssistant.tsx @@ -157,7 +157,7 @@ export default function AIAssistant() { background: msg.role === 'user' ? 'linear-gradient(135deg, #F97316, #FB923C)' : '#F8FAFC', color: msg.role === 'user' ? 'white' : '#1E293B', borderRadius: msg.role === 'user' ? '20px 20px 4px 20px' : '20px 20px 20px 4px', - border: msg.role === 'ai' ? '1px solid #E5E7EB' : 'none', + border: msg.role === 'assistant' ? '1px solid #E5E7EB' : 'none', fontFamily: 'Inter, sans-serif', }} dangerouslySetInnerHTML={{ __html: formatContent(msg.content) }} diff --git a/src/pages/Campus/Campus.tsx b/src/pages/Campus/Campus.tsx index aeab0b1..db2c0d6 100644 --- a/src/pages/Campus/Campus.tsx +++ b/src/pages/Campus/Campus.tsx @@ -1,12 +1,13 @@ -import { useState } from 'react'; +import { useState, useMemo, useEffect } from 'react'; import { motion } from 'framer-motion'; -import { Search, ChevronRight, MapPin } from 'lucide-react'; +import { Search, ChevronRight, MapPin, Users, BookOpen, Filter, ArrowUpDown, Loader2 } from 'lucide-react'; import SectionTitle from '@/components/SectionTitle/SectionTitle'; import BusCard from '@/components/BusCard/BusCard'; import FacultyCard from '@/components/FacultyCard/FacultyCard'; import { StaggerContainer, StaggerItem } from '@/components/AnimatedContainer/AnimatedContainer'; -import { BUS_ROUTES, FACULTY_DATA, CAMPUS_LOCATIONS, DEPARTMENTS } from '@/constants'; +import { FACULTY_DATA, CAMPUS_LOCATIONS, DEPARTMENTS } from '@/constants'; import * as LucideIcons from 'lucide-react'; +import type { BusRoute } from '@/types'; type Tab = 'map' | 'bus' | 'faculty'; @@ -14,16 +15,52 @@ export default function Campus() { const [activeTab, setActiveTab] = useState('map'); const [searchFaculty, setSearchFaculty] = useState(''); const [selectedDept, setSelectedDept] = useState('All Departments'); + const [sortBy, setSortBy] = useState('Name A-Z'); const [busSearch, setBusSearch] = useState(''); + const [busRoutes, setBusRoutes] = useState([]); + const [loadingBus, setLoadingBus] = useState(true); - const filteredFaculty = FACULTY_DATA.filter((f) => { - const matchSearch = f.name.toLowerCase().includes(searchFaculty.toLowerCase()) || - f.department.toLowerCase().includes(searchFaculty.toLowerCase()); - const matchDept = selectedDept === 'All Departments' || f.department === selectedDept; - return matchSearch && matchDept; - }); + useEffect(() => { + if (activeTab === 'bus' && busRoutes.length === 0) { + setLoadingBus(true); + fetch('http://localhost:8080/api/bus-routes') + .then((res) => { + if (!res.ok) throw new Error('Failed to fetch'); + return res.json(); + }) + .then((data) => { + setBusRoutes(data); + setLoadingBus(false); + }) + .catch((err) => { + console.error('Error fetching bus routes:', err); + setLoadingBus(false); + }); + } + }, [activeTab, busRoutes.length]); - const filteredRoutes = BUS_ROUTES.filter((r) => + const filteredAndSortedFaculty = useMemo(() => { + const filtered = FACULTY_DATA.filter((f) => { + const searchLower = searchFaculty.trim().toLowerCase(); + const matchSearch = + f.name.toLowerCase().includes(searchLower) || + f.department.toLowerCase().includes(searchLower) || + f.designation.toLowerCase().includes(searchLower) || + (f.specialization && f.specialization.toLowerCase().includes(searchLower)); + + const matchDept = selectedDept === 'All Departments' || f.department === selectedDept; + return matchSearch && matchDept; + }); + + return filtered.sort((a, b) => { + if (sortBy === 'Name A-Z') return a.name.localeCompare(b.name); + if (sortBy === 'Department') return a.department.localeCompare(b.department); + if (sortBy === 'Designation') return a.designation.localeCompare(b.designation); + return 0; + }); + }, [searchFaculty, selectedDept, sortBy]); + + const filteredRoutes = busRoutes.filter((r) => r.name.toLowerCase().includes(busSearch.toLowerCase()) || r.from.toLowerCase().includes(busSearch.toLowerCase()) || r.number.toLowerCase().includes(busSearch.toLowerCase()) @@ -36,8 +73,18 @@ export default function Campus() { ]; return ( -
- {/* Header */} +
+ {/* Background decorations for Faculty tab */} + {activeTab === 'faculty' && ( +
+
+
+
+
+
+ )} +
+ {/* Header */}
@@ -61,7 +108,7 @@ export default function Campus() { {/* Tabs */}
{TABS.map((tab) => { - const Icon = (LucideIcons as Record>)[tab.icon]; + const Icon = (LucideIcons as unknown as Record>)[tab.icon]; return (
- - {filteredRoutes.map((route) => ( - - - - ))} - + + {loadingBus ? ( +
+ +

+ Loading live bus routes from RIT Transport... +

+
+ ) : filteredRoutes.length === 0 ? ( +
+

+ No bus routes found matching "{busSearch}" +

+
+ ) : ( + + {filteredRoutes.map((route) => ( + + + + ))} + + )} )} {/* Faculty Tab */} {activeTab === 'faculty' && ( - -
+ + {/* Faculty Hero Section */} +
+
+
+
+ +
+

+ Faculty Directory +

+

+ Browse and connect with experienced faculty members. Search by name, department, or specialization. +

+
+ +
+

Department Overview

+
+ {[ + { abrv: 'CSE', full: 'Computer Science & Engineering', color: 'blue' }, + { abrv: 'CSBS', full: 'Computer Science & Business Systems', color: 'indigo' }, + { abrv: 'AIML', full: 'Artificial Intelligence & Machine Learning', color: 'sky' }, + { abrv: 'ECE', full: 'Electronics & Communication Engineering', color: 'purple' }, + { abrv: 'MECH', full: 'Mechanical Engineering', color: 'orange' }, + { abrv: 'CIVIL', full: 'Civil Engineering', color: 'emerald' }, + { abrv: 'AI & DS', full: 'Artificial Intelligence & Data Science', color: 'pink' }, + { abrv: 'EEE', full: 'Electrical & Electronics Engineering', color: 'yellow' }, + ].map(d => { + const count = FACULTY_DATA.filter(f => f.department === d.full).length; + return ( +
+
+ {d.abrv} + +
+ {count} +
+ ); + })} +
+
+
+ + {/* Search Section */} +
- + setSearchFaculty(e.target.value)} - className="w-full pl-11 pr-4 py-3 rounded-xl border border-[#E5E7EB] bg-white text-sm text-[#1E293B] placeholder-[#94A3B8] focus:outline-none focus:border-[#F97316] transition-colors" + className="w-full pl-12 pr-4 py-3.5 rounded-2xl bg-[#F8FAFC] border-none text-sm text-[#1E293B] placeholder-[#94A3B8] focus:ring-2 focus:ring-[#FF7A00]/20 focus:outline-none transition-all" style={{ fontFamily: 'Inter, sans-serif' }} />
- +
+
+ + +
+
+ + +
+
+
+ + {/* Grid */} + {filteredAndSortedFaculty.length > 0 ? ( + + {filteredAndSortedFaculty.map((faculty) => ( + + + + ))} + + ) : ( +
+ +

No faculty found

+

Try adjusting your search or filters.

+
+ )} + + {/* Bottom Status */} +
+ + 👥 + + Showing {filteredAndSortedFaculty.length} Faculty Members + +
- - {filteredFaculty.map((faculty) => ( - - - - ))} - )}
+
); } diff --git a/src/pages/Community/Community.tsx b/src/pages/Community/Community.tsx index bcfc482..0d712ba 100644 --- a/src/pages/Community/Community.tsx +++ b/src/pages/Community/Community.tsx @@ -1,31 +1,157 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { MessageCircle, Heart, TrendingUp, ThumbsUp, Send, - Shield, Lock, Smile, ChevronRight, Search, Plus + Shield, Lock, Smile, ChevronRight, Search, Plus, User } from 'lucide-react'; import SectionTitle from '@/components/SectionTitle/SectionTitle'; import { StaggerContainer, StaggerItem } from '@/components/AnimatedContainer/AnimatedContainer'; import AnimatedContainer from '@/components/AnimatedContainer/AnimatedContainer'; import { QUESTIONS_DATA, CONFESSIONS_DATA } from '@/constants'; -import { formatDate } from '@/lib/utils'; type Tab = 'qa' | 'confession'; const TRENDING_TAGS = ['hostel', 'academics', 'clubs', 'campus', 'canteen', 'sports', 'placement', 'library']; +const AVATARS: Record = { + 'Priya S.': 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?auto=format&fit=crop&w=120&h=120&q=80', + 'Ravi K.': 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?auto=format&fit=crop&w=120&h=120&q=80', + 'Arun M.': 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?auto=format&fit=crop&w=120&h=120&q=80', +}; + +const getAvatar = (author: string) => { + return AVATARS[author] || `https://api.dicebear.com/7.x/initials/svg?seed=${encodeURIComponent(author)}`; +}; + +const getRelativeTime = (dateString: string) => { + if (!dateString) return 'just now'; + + // Normalize microsecond timestamps (e.g. 2026-07-22T13:28:18.174367) to standard millisecond precision + let normalized = dateString; + const dotIndex = dateString.indexOf('.'); + if (dotIndex !== -1) { + const mainPart = dateString.substring(0, dotIndex); + let msPart = dateString.substring(dotIndex + 1); + // Strip any trailing non-digits (like timezone offsets Z or +05:30) for truncation, then keep first 3 digits + const nonDigitMatch = msPart.match(/\D/); + let suffix = ''; + if (nonDigitMatch && nonDigitMatch.index !== undefined) { + suffix = msPart.substring(nonDigitMatch.index); + msPart = msPart.substring(0, nonDigitMatch.index); + } + normalized = `${mainPart}.${msPart.substring(0, 3)}${suffix}`; + } + + const now = new Date().getTime(); // Dynamic local time + const past = new Date(normalized).getTime(); + if (isNaN(past)) return 'just now'; + + const msPerMinute = 60 * 1000; + const msPerHour = msPerMinute * 60; + const msPerDay = msPerHour * 24; + const elapsed = now - past; + + if (elapsed < msPerMinute) { + return 'just now'; + } else if (elapsed < msPerHour) { + return Math.round(elapsed / msPerMinute) + 'm ago'; + } else if (elapsed < msPerDay) { + return Math.round(elapsed / msPerHour) + 'h ago'; + } else { + const days = Math.round(elapsed / msPerDay); + return days === 1 ? 'yesterday' : `${days}d ago`; + } +}; + export default function Community() { + const PAGE_SIZE = 5; + const [activeTab, setActiveTab] = useState('qa'); const [confessionText, setConfessionText] = useState(''); const [questionText, setQuestionText] = useState(''); + const [authorName, setAuthorName] = useState(''); const [confessionPosted, setConfessionPosted] = useState(false); const [searchQuery, setSearchQuery] = useState(''); const [likedIds, setLikedIds] = useState>(new Set()); + const [expandedQuestionIds, setExpandedQuestionIds] = useState>(new Set()); + // Server-side pagination + const [currentPage, setCurrentPage] = useState(0); + const [totalPages, setTotalPages] = useState(1); + const [questions, setQuestions] = useState([]); + const [loading, setLoading] = useState(false); + // Fallback static questions for when backend is unavailable + const [staticQuestions] = useState(QUESTIONS_DATA); - const filteredQuestions = QUESTIONS_DATA.filter((q) => - q.title.toLowerCase().includes(searchQuery.toLowerCase()) || - q.tags.some((t) => t.includes(searchQuery.toLowerCase())) - ); + const toggleAnswers = (id: string) => { + setExpandedQuestionIds((prev) => { + const next = new Set(prev); + if (next.has(id.toString())) { + next.delete(id.toString()); + } else { + next.add(id.toString()); + } + return next; + }); + }; + + const fetchQuestions = async (page = 0) => { + setLoading(true); + try { + const response = await fetch(`http://localhost:8080/api/questions/paged?page=${page}&size=${PAGE_SIZE}`); + if (response.ok) { + const data = await response.json(); + // Spring Page response: { content: [], totalPages, totalElements, number } + setQuestions(data.content || []); + setTotalPages(data.totalPages || 1); + setCurrentPage(data.number ?? page); + } else { + console.error("Failed to fetch questions from backend: HTTP status", response.status); + // Fallback: slice static questions + const start = page * PAGE_SIZE; + setQuestions(staticQuestions.slice(start, start + PAGE_SIZE)); + setTotalPages(Math.ceil(staticQuestions.length / PAGE_SIZE)); + setCurrentPage(page); + } + } catch (error) { + console.error('Backend not available. Falling back to local static questions data.', error); + const start = page * PAGE_SIZE; + setQuestions(staticQuestions.slice(start, start + PAGE_SIZE)); + setTotalPages(Math.ceil(staticQuestions.length / PAGE_SIZE)); + setCurrentPage(page); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchQuestions(0); + }, []); + + const getAnswersCount = (q: any) => { + if (Array.isArray(q.answers)) return q.answers.length; + if (typeof q.answers === 'number') return q.answers; + return 0; + }; + + const getVotesCount = (q: any) => { + const votesVal = typeof q.upvotes === 'number' ? q.upvotes : (typeof q.votes === 'number' ? q.votes : 0); + return votesVal; + }; + + // Client-side filter applied on top of current page (for search within page) + const filteredQuestions = questions.filter((q) => { + const titleVal = q.title || ""; + const tagsVal = q.tags || []; + return titleVal.toLowerCase().includes(searchQuery.toLowerCase()) || + tagsVal.some((t: string) => t.toLowerCase().includes(searchQuery.toLowerCase())); + }); + + const handlePageChange = (newPage: number) => { + setExpandedQuestionIds(new Set()); // collapse any open answers + fetchQuestions(newPage); + // Scroll back to the top of the questions list smoothly + document.getElementById('qa-questions-list')?.scrollIntoView({ behavior: 'smooth', block: 'start' }); + }; const handleConfess = () => { if (!confessionText.trim()) return; @@ -34,34 +160,90 @@ export default function Community() { setTimeout(() => setConfessionPosted(false), 3000); }; - const toggleLike = (id: string) => { + const toggleLike = async (id: string) => { setLikedIds((prev) => { const next = new Set(prev); if (next.has(id)) next.delete(id); else next.add(id); return next; }); + + try { + await fetch(`http://localhost:8080/api/questions/${id}/upvote`, { + method: 'POST' + }); + fetchQuestions(); + } catch (error) { + console.log('Backend not available for upvote sync.', error); + } + }; + + const handlePostQuestion = async () => { + if (!questionText.trim()) return; + + const displayAuthor = authorName.trim() || 'Anonymous'; + + const newQuestion = { + title: questionText.split('\n')[0].substring(0, 100) || "Q&A Question", + body: questionText, + author: displayAuthor, + tags: ['fresher', 'general'], + upvotes: 0, + isAnswered: false, + createdAt: new Date().toISOString(), + answers: [] + }; + + try { + const response = await fetch('http://localhost:8080/api/questions', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + title: newQuestion.title, + body: newQuestion.body, + author: newQuestion.author, + tags: newQuestion.tags + }) + }); + + if (response.ok) { + const saved = await response.json(); + setQuestions(prev => { + // Prepend saved question and filter out duplicate placeholders + const filtered = prev.filter(q => q.id.toString() !== saved.id.toString()); + return [saved, ...filtered]; + }); + setQuestionText(''); + setAuthorName(''); + } else { + setQuestions(prev => [{ ...newQuestion, id: String(Date.now()) }, ...prev]); + setQuestionText(''); + setAuthorName(''); + } + } catch (error) { + console.error("Error saving question:", error); + setQuestions(prev => [{ ...newQuestion, id: String(Date.now()) }, ...prev]); + setQuestionText(''); + setAuthorName(''); + } }; return ( -
+
{/* Header */} -
+
-

- RIT{' '} - - Community - +

+ RIT Community

-

+

Ask questions, share confessions, and connect with fellow RIT students.

-
+
{/* Tabs */} -
+
{[ { id: 'qa' as Tab, label: 'Freshers Q&A', icon: MessageCircle }, { id: 'confession' as Tab, label: 'Confessions', icon: Heart }, @@ -69,19 +251,18 @@ export default function Community() { @@ -93,33 +274,42 @@ export default function Community() { {activeTab === 'qa' && (
{/* Ask Question Box */} -
-

Ask a Question

+
+

Ask a Question