Skip to content

implement Meeting Repository & History Dashboard with component refactoring#81

Merged
imuniqueshiv merged 1 commit into
imuniqueshiv:mainfrom
mrunmayeekokitkar:building
Jul 7, 2026
Merged

implement Meeting Repository & History Dashboard with component refactoring#81
imuniqueshiv merged 1 commit into
imuniqueshiv:mainfrom
mrunmayeekokitkar:building

Conversation

@mrunmayeekokitkar

@mrunmayeekokitkar mrunmayeekokitkar commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Pull Request

Description

Implements the complete Meeting Repository & History Dashboard, introducing a dedicated meeting management experience with reusable components, advanced search, filtering, pagination, and meeting actions. The implementation also refactors existing meeting pages into smaller, maintainable components while preserving all current functionality, including AI transcription, summarization, and authentication.

Type of Change

  • New Feature
  • Bug Fix
  • Documentation Update
  • Refactor
  • Performance Improvement
  • Security Improvement
  • Other

Related Issue

Closes #72

Changes

Meeting Repository

  • Created a dedicated MeetingRepository component for browsing, searching, filtering, and managing meetings.
  • Displays uploaded meetings in a clean, responsive grid layout.
  • Includes loading, error, and empty states.
  • Fully responsive across desktop, tablet, and mobile devices.
  • Designed to match the existing MeetOnMemory design language.

Reusable Components

Extracted reusable meeting components:

  • ScheduleMeeting
  • LiveMeeting
  • SessionCards

Created new reusable components:

  • MeetingCard
  • MeetingSearch
  • MeetingFilters
  • Pagination
  • EmptyState

These components improve maintainability, readability, and future extensibility.

MeetingCard

Added an individual meeting card component featuring quick actions:

  • View meeting details
  • Download meeting
  • Rename meeting
  • Delete meeting

MeetingSearch

Implemented real-time search functionality without requiring page refresh.

Supports searching across:

  • Meeting title
  • AI summary
  • Keywords
  • Transcript content

MeetingFilters

Added filtering and sorting capabilities, including:

  • Meeting status
  • Meeting type
  • Date range
  • Multiple sorting options

Pagination

Created a reusable pagination component for efficiently browsing large meeting collections.

Empty States

Added dedicated empty-state experiences for:

  • No meetings available
  • No search results

Backend

Updated the backend to support meeting renaming.

Added:

  • updateMeeting controller
  • PUT /api/meetings/:id endpoint

Existing functionality remains unchanged, including:

  • Authentication
  • AI transcription
  • AI summarization

Refactoring

MeetingListPage.jsx

  • Replaced placeholder meeting cards with the new MeetingRepository component.

CreateMeeting.jsx

  • Refactored to use extracted reusable components.
  • Reduced component size from approximately 1100 lines to approximately 60 lines, significantly improving maintainability.

Features Implemented

  • Browse uploaded meetings in a responsive dashboard
  • Real-time search
  • Status filtering
  • Meeting type filtering
  • Date range filtering
  • Sorting options
  • Pagination
  • View meeting details
  • Download meetings
  • Rename meetings
  • Delete meetings
  • Loading states
  • Error states
  • Empty state for no meetings
  • Empty state for no search results
  • Responsive design across desktop, tablet, and mobile
  • Consistent MeetOnMemory design language
  • Reusable architecture for future enhancements

Implementation Summary

Components Created

  • MeetingRepository.jsx – Main dashboard component with meeting display, search, filters, and pagination.
  • MeetingCard.jsx – Individual meeting card with quick actions (view, download, rename, delete).
  • MeetingSearch.jsx – Real-time search by title, summary, keywords, and transcript.
  • MeetingFilters.jsx – Filter by status, meeting type, date range, and sorting options.
  • Pagination.jsx – Pagination component for handling large meeting lists.
  • EmptyState.jsx – Empty-state displays for no meetings and no search results.
  • ScheduleMeeting.jsx – Extracted scheduling workflow.
  • LiveMeeting.jsx – Extracted live meeting workflow.
  • SessionCards.jsx – Extracted session card component.

Backend Updates

  • Added updateMeeting controller function for meeting renaming.
  • Added PUT /api/meetings/:id route.
  • Preserved AI transcription, AI summarization, and authentication functionality.

Refactoring

  • MeetingListPage.jsx now uses MeetingRepository.
  • CreateMeeting.jsx refactored into reusable components, reducing complexity from approximately 1100 lines to around 60 lines.

Testing

  • Tested locally
  • Existing functionality verified
  • No new warnings or errors

Verification

  • ESLint passes with no errors.
  • Code formatted using Prettier.
  • Production build completes successfully.
  • Existing meeting workflows verified after refactoring.
  • Changes committed and pushed to the repository.
  • All acceptance criteria from the issue have been completed.

Screenshots

N/A

Checklist

  • Code follows project conventions
  • Documentation updated where required
  • No unnecessary files included
  • Changes have been tested
  • Ready for review

Summary by CodeRabbit

  • New Features

    • Added a full meetings list experience with search, filters, pagination, and empty states.
    • Meetings can now be renamed, deleted, and downloaded from each card.
    • Added an option to edit meeting details for authorized users.
  • Bug Fixes

    • Improved meeting status, date, and duration display.
    • Search and filters now update results more reliably and reset pagination when needed.
  • Chores

    • Added request rate limiting across meeting-related actions.

@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown

@mrunmayeekokitkar is attempting to deploy a commit to the Shiv Raj Singh's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR implements a Meeting Repository dashboard with new components (EmptyState, MeetingSearch, MeetingFilters, MeetingCard, Pagination, MeetingRepository) supporting search, filtering, sorting, pagination, and meeting actions. It adds a backend updateMeeting endpoint and rate-limiting middleware applied to meeting routes.

Changes

Meeting Repository feature and backend support

Layer / File(s) Summary
EmptyState, Search, and Pagination components
client/src/components/meetings/EmptyState.jsx, client/src/components/meetings/MeetingSearch.jsx, client/src/components/meetings/Pagination.jsx
New empty-state variants keyed by type, a controlled search input with clear button, and a simplified page-number pagination control.
MeetingFilters component
client/src/components/meetings/MeetingFilters.jsx
New dropdown filter panel for status, meeting type, date range, and sort, with active-filter badge and clear-all action.
MeetingCard component
client/src/components/meetings/MeetingCard.jsx
New meeting card with status pill, inline rename, actions menu (Rename/Download/Delete), tags, and a download CTA.
MeetingRepository orchestration
client/src/components/meetings/MeetingRepository.jsx
Fetches meetings, applies search/filter/sort, paginates results, and wires rename/download/delete handlers with loading/error/empty states.
MeetingListPage integration
client/src/pages/MeetingListPage.jsx
Replaces the static meetings grid with the MeetingRepository component and updates page copy/icons.
Backend updateMeeting endpoint
server/controllers/meetingController.js, server/routes/meetingRoutes.js
Adds an ownership-checked updateMeeting controller with re-indexing and a PUT /:id route.
Rate limiting middleware and route wiring
server/middleware/rateLimiter.js, server/routes/meetingRoutes.js
Adds apiLimiter, writeLimiter, and uploadLimiter and applies them across meeting routes.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant MeetingRepository
  participant Server
  participant MeetingCard
  User->>MeetingRepository: load page
  MeetingRepository->>Server: GET /api/meetings/all
  Server-->>MeetingRepository: meetings list
  MeetingRepository->>MeetingRepository: filter, search, sort, paginate
  MeetingRepository->>MeetingCard: render paginated meetings
  User->>MeetingCard: rename/delete/download
  MeetingCard->>MeetingRepository: invoke handler
  MeetingRepository->>Server: PUT/DELETE meeting
  Server-->>MeetingRepository: updated result
  MeetingRepository->>MeetingRepository: refresh list
Loading

Possibly related issues

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The repository is built, but required organization/recently-uploaded filters, full sort modes, a true View Details action, and the requested component splits aren't evident. Add the missing organization and sort filters, restore a distinct View Details action, and confirm the ScheduleMeeting/LiveMeeting/SessionCards refactor.
Out of Scope Changes check ⚠️ Warning The PR introduces router-wide and route-specific rate limiting, which is outside the repository/dashboard scope and changes unrelated behavior. Move rate limiting to a separate change or restrict it to only the routes needed by the repository feature.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: the new meeting repository and component refactor.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Comment thread server/routes/meetingRoutes.js Fixed
Comment thread server/routes/meetingRoutes.js Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 15

Caution

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

⚠️ Outside diff range comments (1)
client/src/pages/EmailVerify.jsx (1)

27-35: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make the OTP paste handler replace the whole code.

handlePaste writes into the refs but never cancels the native paste, so the focused cell can still keep the browser’s pasted text and the six inputs can drift out of sync. That can submit a malformed OTP.

Suggested fix
 const handlePaste = (e) => {
+  e.preventDefault();
   const paste = e.clipboardData.getData("text");
-  const pasteArray = paste.split("");
-  pasteArray.forEach((char, index) => {
-    if (inputRefs.current[index]) {
-      inputRefs.current[index].value = char;
-    }
+  const pasteArray = paste.slice(0, 6).split("");
+  inputRefs.current.forEach((input, index) => {
+    if (input) input.value = pasteArray[index] ?? "";
   });
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/pages/EmailVerify.jsx` around lines 27 - 35, The OTP paste logic
in handlePaste should fully replace the code instead of partially writing refs
while allowing the browser’s default paste behavior. In EmailVerify.jsx’s
handlePaste, prevent the native paste event, then clear all OTP inputs and
populate them from the pasted text so the six inputRefs stay synchronized. Keep
the update localized to handlePaste and the related OTP input state/ref handling
in EmailVerify.
🧹 Nitpick comments (9)
client/src/components/meetings/ScheduleMeeting.jsx (1)

340-349: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

onKeyPress is deprecated; prefer onKeyDown.

The keypress DOM event is deprecated (MDN recommends keydown/beforeinput), and this handler also mixes the comma operator into a JSX expression, which is easy to misread and can trip no-sequences-style lint rules — a plausible contributor to the reported npm run lint failure.

♻️ Proposed fix
-              onKeyPress={(e) =>
-                e.key === "Enter" && (e.preventDefault(), addAgendaItem())
-              }
+              onKeyDown={(e) => {
+                if (e.key === "Enter") {
+                  e.preventDefault();
+                  addAgendaItem();
+                }
+              }}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/meetings/ScheduleMeeting.jsx` around lines 340 - 349,
The agenda input in ScheduleMeeting uses the deprecated onKeyPress handler and a
comma-operator expression that can trip linting; update the input’s enter-key
logic to use onKeyDown instead and keep the behavior in the same Add agenda flow
by calling preventDefault and addAgendaItem() from the existing input handler.

Source: Pipeline failures

client/src/components/meetings/Pagination.jsx (1)

107-113: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Icon-only buttons lack accessible labels.

Prev/Next buttons render only ChevronLeft/ChevronRight icons with no aria-label, hurting screen-reader usability.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/meetings/Pagination.jsx` around lines 107 - 113, The
Prev/Next icon-only buttons in Pagination.jsx need accessible labels. Update the
button elements around handlePrev and handleNext to include clear aria-label
values (for example, “Previous page” and “Next page”) while keeping the
ChevronLeft and ChevronRight icons as-is so screen readers can identify their
purpose.
server/controllers/meetingController.js (2)

656-666: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Response omits several updated fields.

The handler can update time, duration, location, venue, and tags, but the response only echoes back _id, title, description, meetingType, date. Callers relying on this response to refresh local state (beyond a simple rename) would see stale values for the other fields.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/controllers/meetingController.js` around lines 656 - 666, The update
response in the meetingController handler is omitting several fields that the
update path can modify. In the response builder near the final
res.status(200).json call, include the updated values for time, duration,
location, venue, and tags alongside the existing meeting fields so callers can
refresh local state from the returned meeting object.

667-670: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Generic 500 for all errors, including validation/cast failures.

Mongoose ValidationError (e.g., invalid meetingType enum) or CastError (malformed req.params.id) would be swallowed into a generic 500 here, hiding client-fixable input problems behind a server-error status.

♻️ Proposed fix
   } catch (error) {
     console.error("❌ updateMeeting Error:", error.message);
-    return res.status(500).json({ success: false, message: "Failed to update meeting" });
+    if (error.name === "ValidationError" || error.name === "CastError") {
+      return res.status(400).json({ success: false, message: error.message });
+    }
+    return res.status(500).json({ success: false, message: "Failed to update meeting" });
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/controllers/meetingController.js` around lines 667 - 670, The
updateMeeting error handling is treating all failures as 500, including
client-side Mongoose ValidationError and CastError cases. Update the catch block
in updateMeeting to detect those specific Mongoose errors and return a 400-level
response with a validation/input-focused message, while reserving 500 for
unexpected server failures. Use the existing updateMeeting controller flow and
the caught error object to branch on error.name/error.kind so malformed
req.params.id and invalid meetingType are surfaced correctly.
client/src/components/meetings/EmptyState.jsx (1)

44-51: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider react-router's Link instead of <a> for internal navigation.

actionLink values (/upload-meeting, /create-meeting) look like internal SPA routes; using a plain anchor triggers a full page reload/remount instead of client-side navigation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/meetings/EmptyState.jsx` around lines 44 - 51, The
EmptyState component is using a plain anchor for internal SPA navigation, which
causes full page reloads. Update the link in EmptyState.jsx to use
react-router’s Link component for currentContent.actionLink values like
/upload-meeting and /create-meeting, and keep the same styling and icon
rendering while switching the navigation element.
server/routes/meetingRoutes.js (1)

43-45: 🩺 Stability & Availability | 🔵 Trivial

Missing rate limiting on authenticated mutation route.

CodeQL flags this route (authorization + DB write) as lacking rate limiting, which could allow abuse (e.g., brute-forcing meeting IDs against ownership checks, or spamming updates/re-index calls).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/routes/meetingRoutes.js` around lines 43 - 45, The authenticated
mutation route in router.put("/:id", userAuth, updateMeeting) is missing rate
limiting, which can be abused for repeated write attempts and ownership probing.
Add an appropriate rate-limiting middleware to this update path, using the
existing route setup in meetingRoutes and keeping the auth check intact. If
there is a shared limiter for protected write operations, apply it here;
otherwise create one consistent with the other mutation routes before
updateMeeting runs.

Source: Linters/SAST tools

client/src/components/meetings/MeetingCard.jsx (1)

173-189: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Avoid array index as React key for tags.

♻️ Proposed fix
-            {meeting.tags.slice(0, 3).map((tag, index) => (
-              <span
-                key={index}
+            {meeting.tags.slice(0, 3).map((tag) => (
+              <span
+                key={tag}
                 className="px-2 py-1 bg-purple-50 text-purple-700 text-xs rounded-full"
               >
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/meetings/MeetingCard.jsx` around lines 173 - 189, The
tags list in MeetingCard.jsx is using the array index as the React key in the
meeting.tags map, which should be avoided. Update the tags rendering inside
MeetingCard so each tag span uses a stable unique identifier derived from the
tag value (or another deterministic field if available) instead of index, while
keeping the rest of the slice(0, 3) and overflow count behavior unchanged.
client/src/components/meetings/MeetingRepository.jsx (2)

33-35: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

useEffect missing fetchMeetings dependency.

Wrap fetchMeetings in useCallback (or move fetch logic inside the effect) rather than just satisfying the linter with an empty array, to avoid stale-closure surprises if backendUrl ever changes.

♻️ Suggested approach
-  const fetchMeetings = async () => {
+  const fetchMeetings = useCallback(async () => {
     setLoading(true);
     ...
-  };
+  }, [backendUrl]);

   useEffect(() => {
     fetchMeetings();
-  }, []);
+  }, [fetchMeetings]);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/meetings/MeetingRepository.jsx` around lines 33 - 35,
The MeetingRepository component’s useEffect is calling fetchMeetings with an
empty dependency array, which can capture stale values if backendUrl changes.
Update the fetchMeetings function in MeetingRepository.jsx to be stable with
useCallback and include its dependencies, or move the fetch logic directly into
the effect so the effect depends on the actual inputs instead of an empty array.

Source: Linters/SAST tools


169-200: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Native prompt()/confirm() for rename/delete.

These block the main thread and don't match the rest of the styled UI (no input validation beyond trim, no length limit on new title). Consider a proper modal component consistent with the rest of the repository's design.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/meetings/MeetingRepository.jsx` around lines 169 - 200,
The rename/delete flow in MeetingRepository uses native prompt() and confirm(),
which blocks the UI and bypasses the app’s styled interaction patterns. Replace
handleRenameMeeting and handleDeleteMeeting with the repository’s modal/dialog
pattern so MeetingRepository.jsx uses a consistent, non-blocking UI for editing
and confirmation. While wiring the rename modal, add basic validation such as a
title length limit and trim checks before calling the existing axios.put and
axios.delete actions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@client/src/components/meetings/EmptyState.jsx`:
- Around line 14-21: The search empty state in EmptyState should render the
"Clear Search" action instead of gating entirely on a non-null actionLink.
Update EmptyState to support a click handler or action callback for the search
variant (using currentContent.actionText/actionLink or a new prop) and make sure
the action is rendered when type is "search" even though MeetingRepository only
passes type today. Wire the caller in MeetingRepository to provide the
clear-search behavior, and keep the existing conditional logic in EmptyState
consistent with the other variants.

In `@client/src/components/meetings/LiveMeeting.jsx`:
- Around line 45-61: The LiveMeeting.handleRecordingChoice flow is leaking
participant PII by JSON-stringifying liveParticipants into the /meeting-room
URL. Change this to pass only a short opaque session/token id in the query
string and store the participant payload in sessionStorage or a server-created
session before opening the meeting room. Update the MeetingRoom consumer to
resolve participants from that id instead of reading them from the URL, and keep
the existing recording flag in the URL if needed.

In `@client/src/components/meetings/MeetingFilters.jsx`:
- Around line 46-62: The active-filter detection in MeetingFilters is
incorrectly counting the default sortBy value as a user-applied filter, so the
UI always shows filters as active. Update hasActiveFilters to ignore sortBy
unless it differs from its default value, and ensure the active-filters chip
rendering logic only treats actual user-selected filters as active. Check the
filter state handling in MeetingFilters and the related active-filter
display/clear logic around the sections that build the filter chips and “Clear
All Filters” button.
- Around line 4-9: The `availableOrganizations` prop is currently unused in
`MeetingFilters`, and the organization filter is missing from the rendered
`filterOptions`, which is causing the lint failure and leaving the feature
incomplete. Update `MeetingFilters` to actually use `availableOrganizations`
when building the options list and add the organization filter UI, then thread
the prop from `MeetingRepository` into `MeetingFilters`. Also initialize the
`organization: "all"` entry in the filters state within `MeetingRepository` so
the new filter has a default value and stays in sync with
`onFilterChange`/`onClearFilters`.

In `@client/src/components/meetings/MeetingRepository.jsx`:
- Around line 89-115: The dateRange switch in MeetingRepository filters triggers
no-case-declarations because weekAgo, monthAgo, and yearAgo are declared
directly in case clauses. Update the switch inside the filtered =
filtered.filter callback to wrap each non-trivial case body in its own block, or
hoist the date boundary variables above the switch, so the declarations are
scoped correctly while preserving the existing today/week/month/year filtering
logic.
- Around line 117-129: The title sort in MeetingRepository’s sorting logic can
fail when a meeting has no title. Update the sort branch in the filtered.sort
callback to use the same fallback as the card renderer for missing titles, so
untitled meetings are handled safely and the grid doesn’t break. Keep the fix
localized to the sortBy === "title" path and preserve the existing
createdAt/date sorting behavior.

In `@client/src/components/meetings/Pagination.jsx`:
- Around line 23-56: The pagination list in Pagination.jsx is using index-based
keys for items returned by getPageNumbers(), which can collide when the array
includes duplicate "..." placeholders and trigger the list-component-no-index
lint failure. Update the render path that maps over getPageNumbers() to give
each entry a stable unique key based on the page value plus its position or
type, and keep the key on the wrapping Fragment so the inner span/button
warnings are not treated as separate key requirements.

In `@client/src/components/meetings/ScheduleMeeting.jsx`:
- Around line 41-53: The participant add/remove logic in ScheduleMeeting is
duplicated with the matching handlers in LiveMeeting, so extract the shared
validation, toast, and state update behavior into a reusable hook or component.
Move the common behavior from addParticipant/removeParticipant and
addLiveParticipant/removeLiveParticipant into something like a useParticipants
hook (or shared ParticipantList logic), then have both ScheduleMeeting and
LiveMeeting consume it so the two components no longer maintain the same
participant logic separately.
- Line 34: The attachments state in ScheduleMeeting.jsx is currently collected
but never reaches the backend, so either wire true attachment support end-to-end
or remove the picker. Update the createMeeting flow behind /api/meetings/create
to accept multipart form data (with appropriate middleware) and persist/read
uploaded files in the controller, or if that is not intended, remove or hide the
attachment UI and related state from ScheduleMeeting.jsx so users cannot submit
unsupported files.

In `@client/src/main.jsx`:
- Around line 2-14: The main entry in main.jsx imports both React and StrictMode
but never uses them, so fix the unused import issue by either removing the
unused symbols from the import list or actually wrapping the rendered tree in
StrictMode; update the createRoot(...).render call and the surrounding
BrowserRouter/AppContextProvider/App composition accordingly so the imported
React/StrictMode symbols are no longer flagged by no-unused-vars.

In `@client/src/pages/AiSearch.jsx`:
- Around line 16-19: The modal header close control in AiSearch is currently an
empty button, so restore its visible close affordance and accessibility in the
same button element used with onClick/onClose. Update the button in the modal
header to render the missing icon/text content again and add an aria-label so
users can identify and dismiss the modal from the header.

In `@client/src/pages/CreateMeeting.jsx`:
- Around line 61-65: The tab switch logic in CreateMeeting is unmounting
ScheduleMeeting, LiveMeeting, and SessionCards via conditional rendering, which
wipes each component’s local useState form data when switching tabs. Update
CreateMeeting so all three components stay mounted and only their visibility is
toggled based on activeSection, preserving in-progress inputs like participants,
agenda items, and uploaded files. Use the existing activeSection switch and the
component symbols ScheduleMeeting, LiveMeeting, and SessionCards to implement
the visibility-based render instead of && mounting.

In `@client/src/pages/EmailVerify.jsx`:
- Around line 49-53: The email verification flow in EmailVerify.jsx redirects
immediately after calling getUserData(), which can leave the next page with
stale auth state. Update the success path in the email verification handler to
await the auth refresh before calling navigate("/"), following the same pattern
used in CreateOrganizationPage so the context update is applied first.

In `@client/src/pages/ResetPassword.jsx`:
- Around line 35-43: The ResetPassword.jsx paste handler still uses the
split-and-refs-only approach in handlePaste, so the focused OTP field can
receive a native paste and leave the inputs out of sync. Update handlePaste to
use the same atomic OTP paste flow as the existing OTP component: prevent the
default paste behavior, distribute the pasted characters through
inputRefs.current in one controlled update, and keep the focused field from
handling the browser’s default paste.

In `@server/controllers/meetingController.js`:
- Around line 635-645: In the meeting update flow inside meetingController’s
edit/update handler, the current date assignment can store an Invalid Date.
Validate the incoming date before setting meeting.date by parsing it and
rejecting or ignoring malformed values, and only assign when the parsed value is
a real date. Use the existing request fields destructuring and the meeting
object update block to add the check so invalid date strings never reach save().

---

Outside diff comments:
In `@client/src/pages/EmailVerify.jsx`:
- Around line 27-35: The OTP paste logic in handlePaste should fully replace the
code instead of partially writing refs while allowing the browser’s default
paste behavior. In EmailVerify.jsx’s handlePaste, prevent the native paste
event, then clear all OTP inputs and populate them from the pasted text so the
six inputRefs stay synchronized. Keep the update localized to handlePaste and
the related OTP input state/ref handling in EmailVerify.

---

Nitpick comments:
In `@client/src/components/meetings/EmptyState.jsx`:
- Around line 44-51: The EmptyState component is using a plain anchor for
internal SPA navigation, which causes full page reloads. Update the link in
EmptyState.jsx to use react-router’s Link component for
currentContent.actionLink values like /upload-meeting and /create-meeting, and
keep the same styling and icon rendering while switching the navigation element.

In `@client/src/components/meetings/MeetingCard.jsx`:
- Around line 173-189: The tags list in MeetingCard.jsx is using the array index
as the React key in the meeting.tags map, which should be avoided. Update the
tags rendering inside MeetingCard so each tag span uses a stable unique
identifier derived from the tag value (or another deterministic field if
available) instead of index, while keeping the rest of the slice(0, 3) and
overflow count behavior unchanged.

In `@client/src/components/meetings/MeetingRepository.jsx`:
- Around line 33-35: The MeetingRepository component’s useEffect is calling
fetchMeetings with an empty dependency array, which can capture stale values if
backendUrl changes. Update the fetchMeetings function in MeetingRepository.jsx
to be stable with useCallback and include its dependencies, or move the fetch
logic directly into the effect so the effect depends on the actual inputs
instead of an empty array.
- Around line 169-200: The rename/delete flow in MeetingRepository uses native
prompt() and confirm(), which blocks the UI and bypasses the app’s styled
interaction patterns. Replace handleRenameMeeting and handleDeleteMeeting with
the repository’s modal/dialog pattern so MeetingRepository.jsx uses a
consistent, non-blocking UI for editing and confirmation. While wiring the
rename modal, add basic validation such as a title length limit and trim checks
before calling the existing axios.put and axios.delete actions.

In `@client/src/components/meetings/Pagination.jsx`:
- Around line 107-113: The Prev/Next icon-only buttons in Pagination.jsx need
accessible labels. Update the button elements around handlePrev and handleNext
to include clear aria-label values (for example, “Previous page” and “Next
page”) while keeping the ChevronLeft and ChevronRight icons as-is so screen
readers can identify their purpose.

In `@client/src/components/meetings/ScheduleMeeting.jsx`:
- Around line 340-349: The agenda input in ScheduleMeeting uses the deprecated
onKeyPress handler and a comma-operator expression that can trip linting; update
the input’s enter-key logic to use onKeyDown instead and keep the behavior in
the same Add agenda flow by calling preventDefault and addAgendaItem() from the
existing input handler.

In `@server/controllers/meetingController.js`:
- Around line 656-666: The update response in the meetingController handler is
omitting several fields that the update path can modify. In the response builder
near the final res.status(200).json call, include the updated values for time,
duration, location, venue, and tags alongside the existing meeting fields so
callers can refresh local state from the returned meeting object.
- Around line 667-670: The updateMeeting error handling is treating all failures
as 500, including client-side Mongoose ValidationError and CastError cases.
Update the catch block in updateMeeting to detect those specific Mongoose errors
and return a 400-level response with a validation/input-focused message, while
reserving 500 for unexpected server failures. Use the existing updateMeeting
controller flow and the caught error object to branch on error.name/error.kind
so malformed req.params.id and invalid meetingType are surfaced correctly.

In `@server/routes/meetingRoutes.js`:
- Around line 43-45: The authenticated mutation route in router.put("/:id",
userAuth, updateMeeting) is missing rate limiting, which can be abused for
repeated write attempts and ownership probing. Add an appropriate rate-limiting
middleware to this update path, using the existing route setup in meetingRoutes
and keeping the auth check intact. If there is a shared limiter for protected
write operations, apply it here; otherwise create one consistent with the other
mutation routes before updateMeeting runs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5dbd0129-9f76-4fcf-a8d6-417352bdb147

📥 Commits

Reviewing files that changed from the base of the PR and between 9025f7a and 2a2e96d.

📒 Files selected for processing (35)
  • client/eslint.config.js
  • client/index.html
  • client/src/assets/assets.js
  • client/src/assets/emailTemplates.js
  • client/src/components/FAQ.jsx
  • client/src/components/Footer.jsx
  • client/src/components/Header.jsx
  • client/src/components/Hero.jsx
  • client/src/components/Navbar.jsx
  • client/src/components/meetings/EmptyState.jsx
  • client/src/components/meetings/LiveMeeting.jsx
  • client/src/components/meetings/MeetingCard.jsx
  • client/src/components/meetings/MeetingFilters.jsx
  • client/src/components/meetings/MeetingRepository.jsx
  • client/src/components/meetings/MeetingSearch.jsx
  • client/src/components/meetings/Pagination.jsx
  • client/src/components/meetings/ScheduleMeeting.jsx
  • client/src/components/meetings/SessionCards.jsx
  • client/src/context/AppContent.js
  • client/src/context/AppContext.jsx
  • client/src/index.css
  • client/src/main.jsx
  • client/src/pages/AiSearch.jsx
  • client/src/pages/CreateMeeting.jsx
  • client/src/pages/CreateOrganizationPage.jsx
  • client/src/pages/EmailVerify.jsx
  • client/src/pages/MeetingListPage.jsx
  • client/src/pages/MeetingRoom.jsx
  • client/src/pages/Reports.jsx
  • client/src/pages/ResetPassword.jsx
  • client/src/pages/SelectRolePage.jsx
  • client/src/pages/Summaries.jsx
  • client/vite.config.js
  • server/controllers/meetingController.js
  • server/routes/meetingRoutes.js

Comment thread client/src/components/meetings/EmptyState.jsx Outdated
Comment thread client/src/components/meetings/LiveMeeting.jsx Outdated
Comment thread client/src/components/meetings/MeetingFilters.jsx
Comment thread client/src/components/meetings/MeetingFilters.jsx Outdated
Comment thread client/src/components/meetings/MeetingRepository.jsx
Comment thread client/src/pages/AiSearch.jsx Outdated
Comment thread client/src/pages/CreateMeeting.jsx Outdated
Comment thread client/src/pages/EmailVerify.jsx
Comment thread client/src/pages/ResetPassword.jsx Outdated
Comment thread server/controllers/meetingController.js
Comment thread server/routes/meetingRoutes.js Fixed
Comment thread server/routes/meetingRoutes.js Fixed
Comment thread server/routes/meetingRoutes.js Fixed
Comment thread server/routes/meetingRoutes.js Fixed
Comment thread server/routes/meetingRoutes.js Fixed
Comment thread server/routes/meetingRoutes.js Fixed
Comment thread server/routes/meetingRoutes.js Fixed
Comment thread server/routes/meetingRoutes.js Fixed

@imuniqueshiv imuniqueshiv left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

@mrunmayeekokitkar Thank you for your contribution and for the tremendous effort you've put into this feature! 🚀 I can see you've invested a lot of time in building the Meeting Repository and refactoring the codebase. The overall direction, reusable component architecture, and functionality look very promising, and I truly appreciate your work.

Before I can merge this PR, I'd like to request one important change.

This issue is specifically about implementing the Meeting Repository & History Dashboard, but the current PR modifies 36 files with over 4,500 lines of changes. That makes it very difficult to perform a thorough and reliable review.

The PR currently includes many changes that appear to be outside the scope of this issue, including:

  • Footer
  • Header
  • Hero
  • Navbar
  • FAQ
  • ResetPassword
  • EmailVerify
  • Reports
  • Summaries
  • AppContext
  • Assets formatting
  • Email templates
  • ESLint config
  • Vite config
  • index.css
  • main.jsx
  • favicon

Most of these files are not required for implementing the Meeting Repository feature.

To keep the review manageable and maintain a clean project history, please limit this PR to only the files necessary for Issue #72 (Meeting Repository & History Dashboard), along with any minimal supporting backend changes required for that feature.

If any of the additional improvements are valuable, I'd be happy to review them as separate pull requests. Smaller, focused PRs are much easier to review, test, and maintain.

Your implementation looks very promising, and I'd be happy to merge it once the PR is focused on the scope of this issue.

Thank you again for your excellent effort and contribution! Looking forward to the updated PR. 🚀

@imuniqueshiv imuniqueshiv added enhancement New feature or request ECSoC26 Eligible for Elite Coders Summer of Code 2026 automated scoring. good-ui +25 XP advanced UI/UX frontend labels Jul 7, 2026
- Create MeetingRepository component for browsing, searching, and managing meetings
- Add MeetingCard component with quick actions (view, download, rename, delete)
- Implement MeetingSearch component for real-time search functionality
- Add MeetingFilters component with status, type, date range, and sorting options
- Create Pagination component for handling large meeting lists
- Add EmptyState component for no meetings and no search results scenarios
- Update MeetingListPage to use MeetingRepository component
- Add updateMeeting controller for renaming meetings
- Add PUT route for meeting updates
- Create rateLimiter middleware with three tiers (api, write, upload)
- Apply rate limiting to all meeting routes for security
@mrunmayeekokitkar

mrunmayeekokitkar commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Can you please review now? Also this issue had "good-backend" label, can you please add that too?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 7

♻️ Duplicate comments (5)
server/routes/meetingRoutes.js (1)

44-46: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

/search lacks a cost-appropriate limiter.

searchMeetingsByText can transcribe an audioUrl via AssemblyAI (upload + polling), the same expensive external-call pattern that /upload and /upload-audio guard with uploadLimiter. Here it only inherits the lenient apiLimiter (100 req/15 min), letting a client trigger far more transcription jobs than through the dedicated upload routes.

🛡️ Proposed fix
-router.post("/search", userAuth, searchMeetingsByText);
+router.post("/search", userAuth, uploadLimiter, searchMeetingsByText);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/routes/meetingRoutes.js` around lines 44 - 46, The /search route
currently only uses the generic apiLimiter, but searchMeetingsByText can trigger
the same expensive AssemblyAI upload/polling flow as the upload routes. Update
the route in router.post("/search", userAuth, searchMeetingsByText) to use the
same cost-appropriate limiter used by the transcription endpoints, and keep
searchMeetingsByText aligned with the upload-audio/upload behavior so
transcription jobs are throttled consistently.
client/src/components/meetings/MeetingRepository.jsx (1)

124-136: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Title sort still lacks a null-title fallback (unaddressed).

🐛 Proposed fix
         case "title":
-          comparison = a.title.localeCompare(b.title);
+          comparison = (a.title || "").localeCompare(b.title || "");
           break;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/meetings/MeetingRepository.jsx` around lines 124 - 136,
The title sort in MeetingRepository’s comparator still needs a null-safe
fallback. Update the "title" branch in the sort switch so it handles missing or
empty title values before calling localeCompare, using a stable fallback (for
example to an empty string or a secondary field) inside the compare logic. Keep
the fix localized to the sort comparator in MeetingRepository.
client/src/components/meetings/MeetingFilters.jsx (1)

4-56: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Organization filter is still missing — PR objective unmet.

The PR requires filtering by organization, but filterOptions has no organization entry, and the availableOrganizations prop that was previously flagged as unused has now been removed altogether rather than wired up. MeetingRepository.jsx's filters state (Lines 19-24) also has no organization key, so this needs to be threaded through both files together (fetch orgs, add organization: "all" to filters state, add the dropdown option here).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/meetings/MeetingFilters.jsx` around lines 4 - 56, The
meeting filters still do not support organization filtering, so wire
`availableOrganizations` through `MeetingFilters` and add an organization entry
to `filterOptions` alongside status/type/date/sort. Update `MeetingRepository`’s
filters state to include an `organization: "all"` default and ensure the
selected organization is passed through `onFilterChange`/`onClearFilters` so the
new dropdown actually drives filtering.
client/src/components/meetings/EmptyState.jsx (1)

4-27: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

"Clear Filters" CTA silently never renders (still unaddressed).

noResults.actionLink is null, so the {state.actionLink && (...)} guard skips rendering entirely — the "Clear Filters" text defined at Line 17 is dead code. MeetingRepository.jsx (Lines 320-322) only passes type with no onClearFilters-style callback, so there's currently no way to wire this even if rendered. This mirrors the previously flagged issue (then on the "search" type) which persists under the renamed "noResults" key.

🐛 Proposed fix
-const EmptyState = ({ type }) => {
+const EmptyState = ({ type, onClearFilters }) => {
   ...
-      {state.actionLink && (
+      {state.actionLink ? (
         <a href={state.actionLink} className="...">
           {state.actionText}
         </a>
-      )}
+      ) : (
+        type === "noResults" && (
+          <button onClick={onClearFilters} className="...">
+            {state.actionText}
+          </button>
+        )
+      )}

And in MeetingRepository.jsx: <EmptyState type={...} onClearFilters={handleClearFilters} />.

Also applies to: 36-43

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/meetings/EmptyState.jsx` around lines 4 - 27, The
EmptyState “Clear Filters” action is still unreachable because the noResults
state sets actionLink to null and the component only renders the CTA when a link
exists. Update EmptyState to accept and use an onClearFilters callback for the
noResults case instead of relying on actionLink, and wire MeetingRepository to
pass its handleClearFilters handler into EmptyState alongside type so the button
actually renders and works.
client/src/components/meetings/Pagination.jsx (1)

38-55: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Index-based key on React.Fragment still unresolved — likely still failing lint.

Still unaddressed from the prior review pass.

🐛 Proposed fix
           {getPageNumbers().map((page, index) => (
-            <React.Fragment key={index}>
+            <React.Fragment key={`${page}-${index}`}>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@client/src/components/meetings/Pagination.jsx` around lines 38 - 55, The
pagination render in Pagination.jsx still uses the array index as the key on
React.Fragment, which should be replaced with a stable value so the lint issue
is resolved. Update the map over getPageNumbers() to use the actual page value
as the fragment key for real page numbers, and for the "..." entries use a
deterministic unique key derived from the item itself and/or its position in the
page sequence. Keep the existing onPageChange and page rendering logic intact.

Source: Linters/SAST tools

🧹 Nitpick comments (1)
server/middleware/rateLimiter.js (1)

4-13: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

max is deprecated in favor of limit (v7+).

express-rate-limit v8.5.2 keeps max working as an alias, but it's documented as deprecated since v7 in favor of limit. Worth aligning with the current API surface.

♻️ Proposed rename
 export const apiLimiter = rateLimit({
   windowMs: 15 * 60 * 1000, // 15 minutes
-  max: 100, // Limit each IP to 100 requests per windowMs
+  limit: 100, // Limit each IP to 100 requests per windowMs
   ...
 export const writeLimiter = rateLimit({
   windowMs: 15 * 60 * 1000, // 15 minutes
-  max: 30, // Limit each IP to 30 write requests per windowMs
+  limit: 30, // Limit each IP to 30 write requests per windowMs
   ...
 export const uploadLimiter = rateLimit({
   windowMs: 15 * 60 * 1000, // 15 minutes
-  max: 10, // Limit each IP to 10 upload requests per windowMs
+  limit: 10, // Limit each IP to 10 upload requests per windowMs

Also applies to: 16-25, 28-37

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/middleware/rateLimiter.js` around lines 4 - 13, The rate limiter
configuration in apiLimiter still uses the deprecated max option instead of the
current limit API. Update the rateLimit() options in rateLimiter.js and the
other referenced limiter setups to use limit with the same numeric value,
keeping the existing message and header settings unchanged, so the middleware
matches the v7+ express-rate-limit surface.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@client/src/components/meetings/MeetingCard.jsx`:
- Around line 174-185: The MeetingCard footer action is mislabeled: the "View
Details" button currently reuses the download handler instead of opening a
meeting detail view. Update MeetingCard to accept and use a dedicated
onViewDetails prop (or equivalent navigation handler) for this button, and
thread that prop through MeetingRepository so the quick action is actually wired
up. Keep onDownload reserved for the download action and ensure the button
label/icon match the new detail-view behavior.
- Around line 83-89: The Download menu item in MeetingCard leaves the actions
dropdown open because its click handler only calls onDownload(meeting) and never
closes the menu. Update the Download button in MeetingCard to also call
setShowMenu(false) before or after onDownload(meeting), matching the behavior
used by the Rename and Delete actions so the menu closes after selection.
- Around line 6-16: The rename flow in MeetingCard can crash when meeting.title
is missing because newTitle is initialized from a falsy value and
handleRenameSubmit() calls trim() on it. Initialize newTitle to a safe string
fallback (for example the same Untitled Meeting default used in MeetingCard’s
header) and keep the input controlled, then make handleRenameSubmit() guard
against non-string values before trimming and submitting.

In `@client/src/components/meetings/MeetingFilters.jsx`:
- Around line 76-80: The active-filter badge in MeetingFilters is counting the
default sortBy value, which inflates the badge when only real filters should be
counted. Update the badge count logic near the hasActiveFilters render in
MeetingFilters.jsx so it excludes sortBy and only counts genuine active filter
fields from filters; use the existing filters object and the badge condition to
keep the displayed count aligned with actual active filters.

In `@client/src/components/meetings/MeetingRepository.jsx`:
- Around line 195-220: The handleDownload function in MeetingRepository.jsx can
crash when meeting.title is missing because it calls replace on a falsy value.
Update the download filename logic to use the same fallback used elsewhere, such
as “Untitled Meeting,” before sanitizing the title, so the Blob download path
always works for untitled meetings.
- Around line 62-71: `getAllMeetings` is returning too narrow a projection, so
`MeetingRepository` and `MeetingCard` receive undefined `transcript`, `tags`,
`duration`, and `participants` data. Update
`server/controllers/meetingController.js:getAllMeetings` to include the missing
`Meeting` fields needed by the client search and card rendering, especially the
existing `tags` field and any metadata used by `MeetingCard.jsx`. Keep the
change centered on the `getAllMeetings` query/projection so the returned
meetings contain everything `MeetingRepository.jsx` filters on and
`MeetingCard.jsx` displays.

In `@server/middleware/rateLimiter.js`:
- Around line 1-37: The rate limiters in rateLimiter.js will misidentify client
IPs unless Express is configured to trust the proxy. Update the app setup in
server.js to enable trust proxy before mounting apiLimiter, writeLimiter, and
uploadLimiter so express-rate-limit can read the real client IP when the app
runs behind a reverse proxy or load balancer.

---

Duplicate comments:
In `@client/src/components/meetings/EmptyState.jsx`:
- Around line 4-27: The EmptyState “Clear Filters” action is still unreachable
because the noResults state sets actionLink to null and the component only
renders the CTA when a link exists. Update EmptyState to accept and use an
onClearFilters callback for the noResults case instead of relying on actionLink,
and wire MeetingRepository to pass its handleClearFilters handler into
EmptyState alongside type so the button actually renders and works.

In `@client/src/components/meetings/MeetingFilters.jsx`:
- Around line 4-56: The meeting filters still do not support organization
filtering, so wire `availableOrganizations` through `MeetingFilters` and add an
organization entry to `filterOptions` alongside status/type/date/sort. Update
`MeetingRepository`’s filters state to include an `organization: "all"` default
and ensure the selected organization is passed through
`onFilterChange`/`onClearFilters` so the new dropdown actually drives filtering.

In `@client/src/components/meetings/MeetingRepository.jsx`:
- Around line 124-136: The title sort in MeetingRepository’s comparator still
needs a null-safe fallback. Update the "title" branch in the sort switch so it
handles missing or empty title values before calling localeCompare, using a
stable fallback (for example to an empty string or a secondary field) inside the
compare logic. Keep the fix localized to the sort comparator in
MeetingRepository.

In `@client/src/components/meetings/Pagination.jsx`:
- Around line 38-55: The pagination render in Pagination.jsx still uses the
array index as the key on React.Fragment, which should be replaced with a stable
value so the lint issue is resolved. Update the map over getPageNumbers() to use
the actual page value as the fragment key for real page numbers, and for the
"..." entries use a deterministic unique key derived from the item itself and/or
its position in the page sequence. Keep the existing onPageChange and page
rendering logic intact.

In `@server/routes/meetingRoutes.js`:
- Around line 44-46: The /search route currently only uses the generic
apiLimiter, but searchMeetingsByText can trigger the same expensive AssemblyAI
upload/polling flow as the upload routes. Update the route in
router.post("/search", userAuth, searchMeetingsByText) to use the same
cost-appropriate limiter used by the transcription endpoints, and keep
searchMeetingsByText aligned with the upload-audio/upload behavior so
transcription jobs are throttled consistently.

---

Nitpick comments:
In `@server/middleware/rateLimiter.js`:
- Around line 4-13: The rate limiter configuration in apiLimiter still uses the
deprecated max option instead of the current limit API. Update the rateLimit()
options in rateLimiter.js and the other referenced limiter setups to use limit
with the same numeric value, keeping the existing message and header settings
unchanged, so the middleware matches the v7+ express-rate-limit surface.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 650f0979-2688-44c1-acb4-5f051926c9fe

📥 Commits

Reviewing files that changed from the base of the PR and between 2a2e96d and 5ea14c7.

📒 Files selected for processing (10)
  • client/src/components/meetings/EmptyState.jsx
  • client/src/components/meetings/MeetingCard.jsx
  • client/src/components/meetings/MeetingFilters.jsx
  • client/src/components/meetings/MeetingRepository.jsx
  • client/src/components/meetings/MeetingSearch.jsx
  • client/src/components/meetings/Pagination.jsx
  • client/src/pages/MeetingListPage.jsx
  • server/controllers/meetingController.js
  • server/middleware/rateLimiter.js
  • server/routes/meetingRoutes.js
🚧 Files skipped from review as they are similar to previous changes (3)
  • client/src/components/meetings/MeetingSearch.jsx
  • server/controllers/meetingController.js
  • client/src/pages/MeetingListPage.jsx

Comment thread client/src/components/meetings/MeetingCard.jsx
Comment thread client/src/components/meetings/MeetingCard.jsx
Comment thread client/src/components/meetings/MeetingCard.jsx
Comment thread client/src/components/meetings/MeetingFilters.jsx
Comment thread client/src/components/meetings/MeetingRepository.jsx
Comment thread client/src/components/meetings/MeetingRepository.jsx
Comment thread server/middleware/rateLimiter.js
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
meetonmemory Ready Ready Preview, Comment Jul 7, 2026 4:44am

@imuniqueshiv imuniqueshiv merged commit f84163c into imuniqueshiv:main Jul 7, 2026
8 checks passed
@imuniqueshiv

Copy link
Copy Markdown
Owner

@mrunmayeekokitkar Thank you so much for your valuable contribution and for the effort you put into implementing the Meeting Repository & History Dashboard!

🚀 I really appreciate your responsiveness to the review feedback and your willingness to refine the PR to keep it focused. The reusable component architecture and overall implementation are a great addition to MeetOnMemory.

I'm happy to have merged your PR! 🎉 If you found MeetOnMemory helpful, please consider ⭐ starring the repository. Looking forward to your future contributions—happy coding! 💙

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

advanced backend ECSoC26-L3 ECSoC26 Eligible for Elite Coders Summer of Code 2026 automated scoring. enhancement New feature or request frontend good-backend +50 XP good-ui +25 XP UI/UX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

📂 Build Meeting Repository & History Dashboard

3 participants