Skip to content

Implement Event Registration Functionality.#216

Merged
harshitap1305 merged 7 commits intoOpenLake:mainfrom
UtkarshUmap:event-registration
Jan 11, 2026
Merged

Implement Event Registration Functionality.#216
harshitap1305 merged 7 commits intoOpenLake:mainfrom
UtkarshUmap:event-registration

Conversation

@UtkarshUmap
Copy link
Copy Markdown
Contributor

@UtkarshUmap UtkarshUmap commented Jan 9, 2026


name: " Pull Request"
about: Create Register button for event on student dashboard.
title: "Implement Event Registration Functionality."

Related Issue


Changes Introduced

  • Added: Backend Endpoint for registration and Frontend Dynamic Registration UI.

Why This Change?

  • Problem: Student were unable to Register for the Event from their Dashboard.
  • Solution: Implement Register workflow for event on Student Dashboard.
  • Impact: Students are able to register in Events.

Summary by CodeRabbit

  • New Features

    • Students can register for events via a confirmation dialog; event tiles show a Register button that updates to "Registered" and disables when enrolled.
    • Registrations update the UI immediately to reflect new participants.
  • Bug Fixes / Validation

    • Server enforces event existence, registration window and capacity rules, and prevents duplicate enrollments with clear error responses.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented Jan 9, 2026

@UtkarshUmap is attempting to deploy a commit to the openlake's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 9, 2026

Warning

Rate limit exceeded

@UtkarshUmap has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 35 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 2f76b3e and 8e2f648.

📒 Files selected for processing (2)
  • backend/routes/events.js
  • frontend/src/Components/Events/EventTile.jsx

Walkthrough

Adds student event registration: backend POST /api/events/:eventId/register with authentication and validations; frontend adds confirmation modal, Register button, and client-side state updates to reflect registrations.

Changes

Cohort / File(s) Summary
Backend: Event registration route
backend/routes/events.js
Added POST '/:eventId/register' protected route using isAuthenticated and authorizeRole(ROLES.STUDENT). Validates event existence and completion status, registration window (registration.start/end) and max_participants when present, and duplicate registration. Uses $addToSet to add participant and returns 404/400/409/500 as appropriate.
Frontend: Event list & registration flow
frontend/src/Components/Events/EventList.jsx
Imported API util; added currentUserId, selectedEvent, showConfirm, and isRegistering state. Implemented handleRegister to open confirmation modal and confirmRegistration to POST /api/events/{eventId}/register, updating local event participants on success and surfacing errors.
Frontend: Event tile UI
frontend/src/Components/Events/EventTile.jsx
Added currentUserId and onRegister props; computes isRegistered from event.participants. Replaced static form link with a Register/Registered button that invokes onRegister(event), disables when registered, and updates label/styling.

Sequence Diagram(s)

sequenceDiagram
    participant Student (UI)
    participant Frontend App
    participant Backend API
    participant Database
    participant Auth Service

    Student ->> Frontend App: Click "Register" on EventTile
    Frontend App ->> Frontend App: show confirmation modal
    Student ->> Frontend App: Confirm registration
    Frontend App ->> Backend API: POST /api/events/:eventId/register (auth token)
    Backend API ->> Auth Service: validate token / get userId
    Auth Service -->> Backend API: userId
    Backend API ->> Database: find event by eventId
    Database -->> Backend API: event document
    Backend API ->> Database: update $addToSet participants (with registration window & capacity checks)
    Database -->> Backend API: updated event / error
    Backend API -->> Frontend App: 200 OK or error (404/400/409/500)
    Frontend App ->> Frontend App: update local event.participants / button state
    Frontend App -->> Student: show success or error feedback
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰
I hopped to the list with a curious nose,
Clicked "Register" — a tiny modal arose.
A POST, a check, and my name in the hat,
Now I'm on the list — imagine that!
Cheers from a rabbit, done neat and fast.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Description check ❓ Inconclusive The PR description covers key sections (Related Issue, Changes Introduced, Why This Change) but lacks detailed implementation details, testing information, and deployment notes required by the template. Expand description with specific details about backend/frontend changes, add Testing section with test cases, and clarify deployment requirements.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: implementing event registration functionality that enables students to register for events.
Linked Issues check ✅ Passed The implementation addresses all frontend and backend objectives: backend endpoint with validation, frontend confirmation modal, button state updates, and participant array management using MongoDB $addToSet.
Out of Scope Changes check ✅ Passed All code changes are directly related to implementing event registration functionality as specified in issue #110, with no unrelated or extraneous modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/src/Components/Events/EventTile.jsx (1)

10-23: Guard registration state when currentUserId is missing (avoid enabling Register for unauthenticated/unknown user).

Right now String(currentUserId) with undefined/null will make isRegistered false and enable the Register button, which then fails later at the API layer.

Proposed patch
-  const isRegistered = event.participants?.some(
-    (p) => String(p?._id || p) === String(currentUserId),
-  );
+  const isRegistered =
+    !!currentUserId &&
+    event.participants?.some((p) => String(p?._id || p) === String(currentUserId));
frontend/src/Components/Events/EventList.jsx (1)

47-93: Fix optimistic update: prevent duplicate participants + avoid mixed participant shapes; add in-flight state.

Current code can (1) append the same user multiple times (double-click Confirm) and (2) mutate participants from “populated objects” into a mixed array ({_id: ...} objects + raw ids), which can break other UI that assumes a consistent shape.

Proposed patch
 const EventList = () => {
@@
   const [selectedEvent, setSelectedEvent] = useState(null);
   const [showConfirm, setShowConfirm] = useState(false);
+  const [isRegistering, setIsRegistering] = useState(false);
@@
   const confirmRegistration = async () => {
     try {
-      const response = await api.post(
-        `/api/events/${selectedEvent._id}/register`,
-      );
+      if (!selectedEvent?._id || !currentUserId || isRegistering) return;
+      setIsRegistering(true);
+
+      await api.post(`/api/events/${selectedEvent._id}/register`);
 
       // update local state so UI updates immediately
-      updateEvent({
-        ...selectedEvent,
-        participants: [...(selectedEvent.participants || []), currentUserId],
-      });
+      updateEvent((() => {
+        const prev = selectedEvent.participants || [];
+        const already = prev.some((p) => String(p?._id || p) === String(currentUserId));
+        if (already) return selectedEvent;
+        // keep shape compatible with "populated participants" usage
+        return { ...selectedEvent, participants: [...prev, { _id: currentUserId }] };
+      })());
 
       setShowConfirm(false);
     } catch (err) {
       const message = err.response?.data?.message || "Registration failed";
       alert(message);
+    } finally {
+      setIsRegistering(false);
     }
   };
🤖 Fix all issues with AI agents
In @backend/routes/events.js:
- Around line 208-236: The current non-atomic check reads
event.participants.length then calls Event.findByIdAndUpdate which can
oversubscribe under concurrent requests; replace the two-step logic with a
single conditional update such as using Event.findOneAndUpdate (or a
transaction) that includes a predicate enforcing capacity — e.g., include
event.registration.max_participants in the query (using $expr and $lt with $size
or compare participants array length) and perform the $addToSet in the same
operation so the insert only succeeds if participants.length <
event.registration.max_participants; update the code paths that currently
reference event.registration.max_participants, event.participants, and
Event.findByIdAndUpdate accordingly and handle the case where findOneAndUpdate
returns null as the registration-full response.
🧹 Nitpick comments (3)
frontend/src/Components/Events/EventTile.jsx (1)

52-69: Make the Register button safer (type="button", optional callback, and disable when currentUserId missing).

This prevents accidental form submission and avoids runtime errors if onRegister isn’t provided (or while auth state is still loading).

Proposed patch
                 <button
+                  type="button"
                   onClick={(e) => {
                     e.stopPropagation();
-                    onRegister(event);
+                    onRegister?.(event);
                   }}
-                  disabled={isRegistered}
+                  disabled={isRegistered || !currentUserId}
                   className={`inline-flex items-center px-3 py-1 rounded-full text-xs font-medium transition
                     ${
                       isRegistered
                         ? "bg-green-100 text-green-800 cursor-default"
                         : "bg-blue-100 text-blue-800 hover:bg-blue-200"
                     }`}
                 >
frontend/src/Components/Events/EventList.jsx (2)

110-116: Prefer a stable key (event._id) over array index for EventTile.

This avoids incorrect tile reuse when events are inserted/removed/re-sorted.

Proposed patch
-                <EventTile
-                  key={i}
+                <EventTile
+                  key={event._id}
                   index={i + 1}
                   event={event}
                   currentUserId={currentUserId}
                   onRegister={handleRegister}
                 />

136-161: Add minimal dialog semantics + disable actions while registering.

This improves accessibility and prevents interactions during an in-flight request.

Proposed patch
       {showConfirm && selectedEvent && (
-        <div className="fixed inset-0 bg-black/40 flex items-center justify-center z-50">
-          <div className="bg-white rounded-lg p-6 w-96">
+        <div className="fixed inset-0 bg-black/40 flex items-center justify-center z-50">
+          <div
+            className="bg-white rounded-lg p-6 w-96"
+            role="dialog"
+            aria-modal="true"
+            aria-label="Confirm registration"
+          >
@@
               <button
                 className="px-4 py-2 bg-gray-100 rounded"
                 onClick={() => setShowConfirm(false)}
+                disabled={isRegistering}
               >
                 Cancel
               </button>
               <button
                 className="px-4 py-2 bg-blue-600 text-white rounded"
                 onClick={confirmRegistration}
+                disabled={isRegistering}
               >
                 Confirm
               </button>
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7b2e33f and 5ea26d6.

📒 Files selected for processing (3)
  • backend/routes/events.js
  • frontend/src/Components/Events/EventList.jsx
  • frontend/src/Components/Events/EventTile.jsx
🧰 Additional context used
🧬 Code graph analysis (3)
backend/routes/events.js (2)
backend/models/schema.js (2)
  • User (634-634)
  • Event (639-639)
backend/utils/roles.js (1)
  • ROLES (1-9)
frontend/src/Components/Events/EventTile.jsx (3)
frontend/src/hooks/useSidebar.js (2)
  • useSidebar (39-47)
  • useSidebar (39-47)
frontend/src/utils/eventHelpers.js (2)
  • formatDate (1-5)
  • formatDate (1-5)
frontend/src/Components/Events/EventList.jsx (1)
  • currentUserId (47-47)
frontend/src/Components/Events/EventList.jsx (3)
frontend/src/utils/api.js (1)
  • api (2-5)
frontend/src/hooks/useEvents.js (1)
  • updateEvent (53-59)
frontend/src/Components/Events/EventTile.jsx (1)
  • EventTile (10-90)

Comment thread backend/routes/events.js
Comment thread backend/routes/events.js
Changes done as suggested by CodeRabbitAI .
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @frontend/src/Components/Events/EventTile.jsx:
- Around line 20-22: The error is caused by stray diff marker characters ('+')
at the start of the lines defining the isRegistered constant; remove those
leading '+' characters so the declaration reads as a normal JS/JSX statement.
Locate the isRegistered definition (uses currentUserId and
event.participants?.some((p) => String(p?._id || p) === String(currentUserId)))
and ensure there are no diff artifacts or extra characters before "const
isRegistered =" so the parser can compile correctly.
🧹 Nitpick comments (2)
frontend/src/Components/Events/EventTile.jsx (2)

14-15: Consider adding PropTypes validation for new props.

The new props currentUserId and onRegister are required for the registration flow but lack validation. Adding PropTypes (or TypeScript types) would help catch integration issues early.

🔍 Proposed PropTypes validation

Add this import at the top:

import PropTypes from 'prop-types';

Add this at the bottom of the file:

EventTile.propTypes = {
  event: PropTypes.object.isRequired,
  index: PropTypes.number.isRequired,
  compact: PropTypes.bool,
  currentUserId: PropTypes.string,
  onRegister: PropTypes.func,
};

54-68: Consider adding a loading state during registration.

The button implementation correctly prevents re-registration via disabled={isRegistered}, but doesn't account for the in-progress state during the async onRegister call. Users could potentially trigger multiple registration attempts if they click rapidly before the state updates.

💡 Optional enhancement with loading state

If EventList.jsx (the parent component) exposes a loading state, you could enhance the button:

disabled={isRegistered || isRegistering}
className={`inline-flex items-center px-3 py-1 rounded-full text-xs font-medium transition
  ${
    isRegistered
      ? "bg-green-100 text-green-800 cursor-default"
      : isRegistering
      ? "bg-gray-100 text-gray-600 cursor-wait"
      : "bg-blue-100 text-blue-800 hover:bg-blue-200"
  }`}
>
  {isRegistered ? "Registered" : isRegistering ? "Registering..." : "Register"}
</button>

This would require passing an isRegistering prop from the parent component.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5ea26d6 and 65b6e23.

📒 Files selected for processing (1)
  • frontend/src/Components/Events/EventTile.jsx
🧰 Additional context used
🪛 Biome (2.1.2)
frontend/src/Components/Events/EventTile.jsx

[error] 20-20: Expected a semicolon or an implicit semicolon after a statement, but found none

An explicit or implicit semicolon is expected here...

...Which is required to end this statement

(parse)

🔇 Additional comments (1)
frontend/src/Components/Events/EventTile.jsx (1)

20-22: Well-implemented registration status check.

The isRegistered logic correctly handles edge cases: missing currentUserId, undefined participants array, and participants stored as either populated objects (p._id) or plain ObjectId strings. The string conversion ensures reliable comparison across different data shapes.

Comment thread frontend/src/Components/Events/EventTile.jsx Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
backend/routes/events.js (1)

243-245: Inconsistent style and indentation issue.

  1. Line 243 uses optional chaining (error?.name), but the codebase elsewhere uses defensive checks for "lint/parse compatibility" (see comment at line 156). Line 370 also uses error.name without optional chaining.
  2. Line 244 has incorrect indentation (7 spaces instead of 8).
✨ Suggested fix
-      if (error?.name === "CastError") {
-       return res.status(400).json({ message: "Invalid event ID format." });
+      if (error && error.name === "CastError") {
+        return res.status(400).json({ message: "Invalid event ID format." });
       }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8fd2eb5 and 2f76b3e.

📒 Files selected for processing (1)
  • backend/routes/events.js
🧰 Additional context used
🧬 Code graph analysis (1)
backend/routes/events.js (2)
backend/models/schema.js (2)
  • User (634-634)
  • Event (639-639)
backend/utils/roles.js (1)
  • ROLES (1-9)
🔇 Additional comments (3)
backend/routes/events.js (3)

136-136: LGTM!

Minor spacing/formatting adjustment with no functional impact.


181-206: Good implementation of the protected registration endpoint.

The middleware chain correctly enforces authentication and student role. The use of .equals() for ObjectId comparison at line 202 is appropriate, and returning a 409 for duplicate registrations provides clear feedback to the frontend.


208-222: Registration window validation looks correct.

The conditional checks for registration.start and registration.end are properly handled, only enforced when registration.required is true, aligning with the schema design.

Comment thread backend/routes/events.js Outdated
@harshitap1305 harshitap1305 self-requested a review January 11, 2026 07:28
@harshitap1305 harshitap1305 merged commit 66559e7 into OpenLake:main Jan 11, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Implement Event Registration Functionality

2 participants