diff --git a/RIT-EMS-main/frontend/src/components/dashboard/FacultyEventManagement.tsx b/RIT-EMS-main/frontend/src/components/dashboard/FacultyEventManagement.tsx index 288c182..f09e72e 100644 --- a/RIT-EMS-main/frontend/src/components/dashboard/FacultyEventManagement.tsx +++ b/RIT-EMS-main/frontend/src/components/dashboard/FacultyEventManagement.tsx @@ -12,7 +12,8 @@ import { XCircle, Timer, ChevronLeft, - ChevronDown + ChevronDown, + Users } from 'lucide-react'; import { cn } from '../../lib/utils'; import { format } from 'date-fns'; @@ -26,6 +27,7 @@ interface Event { status: 'REQUESTED' | 'APPROVED' | 'COMPLETED' | 'CANCELLED' | 'PENDING_PR' | 'HOD_REJECTED' | 'PRINCIPAL_REJECTED'; rejectionReason?: string; category?: string; + currentParticipants?: number; } interface FacultyEventManagementProps { @@ -159,6 +161,12 @@ export const FacultyEventManagement: React.FC = ({ {event.location} +
+ + + {event.currentParticipants || 0} Registered + +
diff --git a/RIT-EMS-main/frontend/src/components/dashboard/StudentDashboard.tsx b/RIT-EMS-main/frontend/src/components/dashboard/StudentDashboard.tsx index 35d18eb..50fa99a 100644 --- a/RIT-EMS-main/frontend/src/components/dashboard/StudentDashboard.tsx +++ b/RIT-EMS-main/frontend/src/components/dashboard/StudentDashboard.tsx @@ -64,13 +64,45 @@ export const StudentDashboard: React.FC = () => { } }); + const mapDepartmentToDomain = (dept: string): string => { + if (!dept) return ''; + const d = dept.trim().toUpperCase(); + if (d === 'AI&DS' || d === 'AIDS' || d === 'AI & DS') return 'AIDS'; + if (d === 'AI&ML' || d === 'AIML' || d === 'AI & ML') return 'AIML'; + if (d === 'MECH' || d === 'MECHANICAL') return 'Mechanical'; + if (d === 'BIOTECH' || d === 'BIO-TECH') return 'Bio-tech'; + if (d === 'EE(VLSI)' || d === 'VLSI') return 'VLSI'; + return dept.trim(); + }; + + const mapCategoryToStudentCategory = (dbCat: string, dbType: string): 'TECHNICAL' | 'NON-TECHNICAL' | 'WORKSHOP' | 'CENTRE-ACTIVITY' => { + const cat = (dbCat || '').toUpperCase(); + if (cat === 'TECHNICAL' || cat === 'NON-TECHNICAL' || cat === 'WORKSHOP' || cat === 'CENTRE-ACTIVITY') { + return cat as any; + } + if (cat === 'CENTRE') { + return 'CENTRE-ACTIVITY'; + } + if (cat === 'ACADEMIC') { + return 'TECHNICAL'; + } + const type = (dbType || '').toLowerCase(); + if (type === 'workshop') { + return 'WORKSHOP'; + } + if (type === 'cultural event' || type === 'cultural') { + return 'NON-TECHNICAL'; + } + return 'TECHNICAL'; + }; + return { id: String(dbEvent.id), title: dbEvent.title || 'Untitled Event', location: dbEvent.location || dbEvent.venue || 'TBD', date: dbEvent.startDate || dbEvent.date || new Date().toISOString(), - category: dbEvent.category || 'TECHNICAL', - domain: dbEvent.domain || dbEvent.department || '', + category: mapCategoryToStudentCategory(dbEvent.category, dbEvent.eventType || dbEvent.type || ''), + domain: mapDepartmentToDomain(dbEvent.domain || dbEvent.department || ''), pricingType: dbEvent.hasRegistrationFee ? 'PAID' : 'FREE', coordinator: dbEvent.proposer?.fullName || dbEvent.coordinator || 'Faculty Coordinator', image: dbEvent.image || 'https://images.unsplash.com/photo-1517694712202-14dd9538aa97?auto=format&fit=crop&q=80&w=800', @@ -343,7 +375,12 @@ export const StudentDashboard: React.FC = () => { return ( <> - + = ({ children }) => { interface UpcomingEventsSliderProps { events: Event[]; + bookedEventIds?: string[]; + onToggleBooking?: (id: string) => void; + userRole?: string; } -const UpcomingEventsSlider: React.FC = ({ events }) => { +const UpcomingEventsSlider: React.FC = ({ + events, + bookedEventIds = [], + onToggleBooking, + userRole +}) => { const [selectedEvent, setSelectedEvent] = useState(null); const clubInfo = useMemo(() => selectedEvent ? CLUBS.find(c => c.name === selectedEvent.club) : null, [selectedEvent]); @@ -130,26 +138,60 @@ const UpcomingEventsSlider: React.FC = ({ events }) =
-
-
-

Summary

-
-
- -

- {selectedEvent.event_summary || "Details for this session will be provided soon."} -

-
-
+
+
+
+

Summary

+
+ {userRole === 'STUDENT' && bookedEventIds.includes(selectedEvent.id) && ( + + Registered + + )} +
+
+ +

+ {selectedEvent.event_summary || "Details for this session will be provided soon."} +

+
+ -
- -
+
+ {userRole === 'STUDENT' && onToggleBooking && ( + <> + {bookedEventIds.includes(selectedEvent.id) ? ( + + ) : ( + + )} + + )} + +
diff --git a/RIT-EMS-main/frontend/src/lib/firebaseBackend.ts b/RIT-EMS-main/frontend/src/lib/firebaseBackend.ts index 626f8fc..8d45b10 100644 --- a/RIT-EMS-main/frontend/src/lib/firebaseBackend.ts +++ b/RIT-EMS-main/frontend/src/lib/firebaseBackend.ts @@ -506,8 +506,15 @@ window.fetch = async function(input: RequestInfo | URL, init?: RequestInit): Pro const snap = await getDocs(collection(db, 'ems_events')); const events = snap.docs.map(d => d.data()); - // Populate conflicts + // Fetch all registrations to compute current participant counts dynamically + const regsSnap = await getDocs(collection(db, 'ems_registrations')); + const registrations = regsSnap.docs.map(d => d.data()); + + // Populate conflicts and currentParticipants for (const event of events) { + const count = registrations.filter(r => String(r.eventId || r.event_id) === String(event.id)).length; + event.currentParticipants = count; + if (!['APPROVED', 'COMPLETED', 'CANCELLED'].includes(event.status)) { const conflictMsg = await getConflictMessage(event); if (conflictMsg) { @@ -1049,6 +1056,11 @@ window.fetch = async function(input: RequestInfo | URL, init?: RequestInit): Pro }; await setDoc(regDocRef, newReg); + + // Update event's currentParticipants + const eventDocRef = doc(db, 'ems_events', String(eventId)); + await updateDoc(eventDocRef, { currentParticipants: currentParticipants + 1 }); + return jsonResponse(newReg); } @@ -1100,7 +1112,26 @@ window.fetch = async function(input: RequestInfo | URL, init?: RequestInit): Pro if (path.startsWith('/api/registrations/') && method === 'DELETE') { const parts = path.split('/'); const id = parts[parts.length - 1]; - await deleteDoc(doc(db, 'ems_registrations', String(id))); + const regRef = doc(db, 'ems_registrations', String(id)); + const regSnap = await getDoc(regRef); + + if (regSnap.exists()) { + const regData = regSnap.data(); + const eventId = regData.eventId || regData.event_id; + + await deleteDoc(regRef); + + if (eventId) { + const allRegsSnap = await getDocs(collection(db, 'ems_registrations')); + const eventRegs = allRegsSnap.docs.map(d => d.data()).filter(r => String(r.eventId || r.event_id) === String(eventId)); + const currentParticipants = eventRegs.length; + + await updateDoc(doc(db, 'ems_events', String(eventId)), { currentParticipants }); + } + } else { + await deleteDoc(regRef); + } + return jsonResponse({ message: "Registration deleted successfully" }); } diff --git a/image.png b/image.png index e138de1..d4615ea 100644 Binary files a/image.png and b/image.png differ