Skip to content

feat: Builds an Alumni Mentorship Matching Module allowing alumni to opt-in as mentors with defined capacity limits and expertise tags - #3148

Merged
krushit1307 merged 1 commit into
krushit1307:mainfrom
Aakif-Kohari:feat/alumni-mentorship-module
Aug 12, 2026
Merged

feat: Builds an Alumni Mentorship Matching Module allowing alumni to opt-in as mentors with defined capacity limits and expertise tags#3148
krushit1307 merged 1 commit into
krushit1307:mainfrom
Aakif-Kohari:feat/alumni-mentorship-module

Conversation

@Aakif-Kohari

@Aakif-Kohari Aakif-Kohari commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Pull Request

Description

Builds an Alumni Mentorship Matching Module allowing alumni to opt-in as mentors with defined capacity limits and expertise tags. Current students can browse the directory, filter by industry/company, and send introductory requests. Includes a Postgres trigger that automatically marks mentors as "Full" and hides them from the available pool once they hit their max_mentees limit.

Type of Change

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

Related Issue

Closes #2963

Testing

Describe the testing performed.

  • Tested locally
  • Existing functionality verified
  • No new warnings or errors
    Verified mentor profiles display correctly with capacity bars. Tested the request flow and confirmed the database trigger accurately updates is_accepting when max_mentees is reached.

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 an alumni mentor directory with search, industry, company, and availability filters.
    • Added mentor profile cards showing expertise, capacity, and request availability.
    • Added mentorship request forms with message validation, progress feedback, error handling, and success confirmation.
    • Added capacity tracking and access controls for mentor profiles and mentorship requests.

@github-actions github-actions Bot added ECSoC26 Elite Coders Summer Of Code'26 - Open Source Program feature frontend fullstack hard social labels Aug 12, 2026
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds an alumni mentorship module with Supabase tables, capacity automation, access policies, a filterable mentor directory, profile cards, and a request submission modal.

Changes

Alumni mentorship network

Layer / File(s) Summary
Mentorship schema and access control
supabase/migrations/20260825000002_alumni_mentorship.sql
Adds mentor_profiles and mentorship_requests, capacity triggers, indexes, and RLS policies for profile and request access.
Directory data and filters
src/hooks/useMentorshipDirectory.ts
Adds MentorProfile, MentorshipFilters, and useMentorshipDirectory. The hook fetches mentors, applies filters, derives options, and tracks loading and error state.
Mentor directory and profile cards
src/components/mentorship/MentorDirectory.tsx, src/components/mentorship/MentorProfileCard.tsx
Adds search, industry, company, and availability filters. The directory renders loading, error, empty, and populated states. Cards display mentor details and capacity status.
Mentorship request modal
src/components/mentorship/RequestMentorshipModal.tsx
Adds introductory-message validation, Supabase request insertion, duplicate-request handling, submission progress, success feedback, and automatic closing.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Student
  participant MentorDirectory
  participant useMentorshipDirectory
  participant Supabase
  participant RequestMentorshipModal
  participant mentorship_requests

  Student->>MentorDirectory: Enter search or filter values
  MentorDirectory->>useMentorshipDirectory: Update directory filters
  useMentorshipDirectory->>Supabase: Query mentor profiles
  Supabase-->>useMentorshipDirectory: Return filtered mentors
  useMentorshipDirectory-->>MentorDirectory: Return directory state
  Student->>MentorDirectory: Select an available mentor
  MentorDirectory->>RequestMentorshipModal: Open selected mentor
  Student->>RequestMentorshipModal: Submit introductory message
  RequestMentorshipModal->>Supabase: Insert pending request
  Supabase->>mentorship_requests: Store mentorship request
  mentorship_requests-->>RequestMentorshipModal: Return submission result
Loading

Possibly related PRs

Suggested labels: backend, good-backend, roles, architecture

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements profiles, requests, directory filters, and capacity handling, but lacks club-affiliation filtering, direct-message provisioning, and reporting. Add club affiliation support, provision a secure direct-message channel when requests are accepted, and add reporting for inappropriate mentorship interactions.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the Alumni Mentorship Matching Module and its key capacity and expertise features.
Out of Scope Changes check ✅ Passed The changes are directly related to the Alumni Mentorship Matching Module objectives and do not introduce unrelated functionality.
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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.6)
src/components/mentorship/MentorProfileCard.tsx

File contains syntax errors that prevent linting: Line 3: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 4: unterminated string literal

src/components/mentorship/MentorDirectory.tsx

File contains syntax errors that prevent linting: Line 4: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 5: expected ( but instead found alumni; Line 5: expected ; but instead found mentors; Line 5: expected ; but instead found a; Line 5: expected ) but instead found sidebar; Line 5: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 5: expected ( but instead found filters; Line 5: expected ; but instead found and; Line 5: expected ; but instead found a; Line 5: expected ) but instead found grid; Line 6: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 9: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 9: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 9: Expected a semicolon or an implicit semicolon after a statement, but found none

src/components/mentorship/RequestMentorshipModal.tsx

File contains syntax errors that prevent linting: Line 3: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 4: expected ( but instead found students; Line 4: expected ; but instead found to; Line 4: expected ; but instead found send; Line 4: expected ) but instead found an; Line 4: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 4: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 4: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 4: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 5: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 5: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 5: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 5: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 5: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 5: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 5: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 8: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 8: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 8: Expected a semicolon or an implicit semicolon after a statement, but found none

  • 1 others
🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/components/mentorship/MentorDirectory.tsx

Parsing error: ';' expected.

src/components/mentorship/MentorProfileCard.tsx

Parsing error: ';' expected.

src/components/mentorship/RequestMentorshipModal.tsx

Parsing error: ';' expected.

  • 1 others

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.

@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: 16

🧹 Nitpick comments (10)
src/hooks/useMentorshipDirectory.ts (2)

103-105: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace err: any with a narrowed error type.

catch (err: any) disables type checking on the error path. Use unknown and narrow before you read message.

♻️ Proposed change
-        } catch (err: any) {
+        } catch (err: unknown) {
             console.error('[useMentorshipDirectory] Fetch failed:', err);
-            setError(err.message || 'Failed to load mentor directory.');
+            setError(err instanceof Error ? err.message : 'Failed to load mentor directory.');
🤖 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 `@src/hooks/useMentorshipDirectory.ts` around lines 103 - 105, Update the catch
clause in useMentorshipDirectory to use unknown instead of any, then narrow err
before accessing message; preserve the existing fallback error text and console
logging behavior.

62-63: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Debounce the search query and cancel stale responses.

fetchMentors depends on the whole filters object, and MentorDirectory.tsx Line 49 updates search on every keystroke. Each character sends a network request. Responses can also resolve out of order, so a slower earlier request can overwrite the newest result set.

Debounce the search term and discard results from superseded requests with a cancellation flag or an AbortController.

Also applies to: 90-93

🤖 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 `@src/hooks/useMentorshipDirectory.ts` around lines 62 - 63, Update
fetchMentors in useMentorshipDirectory to debounce requests triggered by search
changes and cancel or ignore superseded requests, using an AbortController or
cancellation flag so stale responses cannot update mentor results. Keep loading
and result updates tied only to the latest active request, and clean up the
debounce/cancellation state when dependencies change or the hook unmounts.
src/components/mentorship/MentorProfileCard.tsx (2)

71-85: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Expose the capacity bar to assistive technology.

The progress bar is a pair of styled div elements. Add role="progressbar" with aria-valuenow, aria-valuemin, and aria-valuemax so screen reader users receive the same capacity information that the visual bar conveys. The numeric text on Line 75 helps, but the bar itself carries the color state.

🤖 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 `@src/components/mentorship/MentorProfileCard.tsx` around lines 71 - 85, Add
progressbar accessibility attributes to the inner capacity-bar div in
MentorProfileCard: set role="progressbar", aria-valuenow to the current capacity
percentage, aria-valuemin to 0, and aria-valuemax to 100, while preserving the
existing styling and width calculation.

88-98: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Explain why the button is disabled.

A disabled button is removed from the tab order, so keyboard users cannot reach it to read the "Currently Full" label. Add aria-disabled with a visible explanation, or keep the label associated through aria-describedby on the capacity text.

🤖 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 `@src/components/mentorship/MentorProfileCard.tsx` around lines 88 - 98, Update
the mentorship request button in MentorProfileCard to expose why it is
unavailable to assistive technology while preserving the existing disabled
behavior and “Currently Full” label. Add an accessible explanation using
aria-disabled with descriptive text or associate the button with the capacity
message via aria-describedby, ensuring the full-state reason remains perceivable
to keyboard and screen-reader users.
src/components/mentorship/MentorDirectory.tsx (1)

119-124: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Announce the loading and error states to assistive technology.

The skeleton grid and the error panel change silently. Add role="status" with aria-live="polite" to the loading container and role="alert" to the error container. Screen reader users then learn that the directory finished loading or failed.

Also applies to: 125-136

🤖 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 `@src/components/mentorship/MentorDirectory.tsx` around lines 119 - 124, Update
the loading container in MentorDirectory’s isLoading branch to include
role="status" and aria-live="polite", and add role="alert" to the corresponding
error container covering the error state. Leave the existing loading and error
content unchanged.
supabase/migrations/20260825000002_alumni_mentorship.sql (3)

23-24: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

updated_at is never maintained on row updates.

Both tables default updated_at to NOW() on insert. The capacity trigger updates mentor_profiles.updated_at explicitly, but a direct profile update from the alumni UI leaves the value stale. mentorship_requests.updated_at is never refreshed on a status change. Add a BEFORE UPDATE timestamp trigger for both tables.

Also applies to: 38-39

🤖 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 `@supabase/migrations/20260825000002_alumni_mentorship.sql` around lines 23 -
24, Add BEFORE UPDATE timestamp triggers for both mentor_profiles and
mentorship_requests so updated_at is refreshed on every row update, including
direct profile edits and mentorship request status changes; retain the existing
capacity trigger behavior and use a shared trigger function if available.

93-96: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Prefer TO authenticated over auth.role().

The existing migrations grant access with a role clause, for example supabase/migrations/20260727080000_impossible_travel.sql Lines 36-38. auth.role() reads the JWT claim and behaves differently from the Postgres role. Align with the repository precedent.

♻️ Proposed change
 CREATE POLICY "Anyone can view mentor profiles"
-ON public.mentor_profiles FOR SELECT
-USING (auth.role() = 'authenticated');
+ON public.mentor_profiles FOR SELECT TO authenticated
+USING (true);
🤖 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 `@supabase/migrations/20260825000002_alumni_mentorship.sql` around lines 93 -
96, Update the "Anyone can view mentor profiles" policy to target the
authenticated Postgres role with a TO authenticated clause, and remove the
auth.role() condition from its USING expression. Follow the existing migration
convention while preserving the policy’s SELECT access for authenticated users.

19-19: 🗄️ Data Integrity & Integration | 🔵 Trivial | 🏗️ Heavy lift

Model mentor affiliations as a relational table.

club_affiliations is a bare UUID[] with no foreign key to public.clubs, and no code reads public.mentor_profiles.club_affiliations. If club filtering is required, add a join table with foreign keys to mentor_profiles.user_id and clubs.id, then query it from useMentorshipDirectory. Otherwise, remove this column until the feature is implemented.

🤖 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 `@supabase/migrations/20260825000002_alumni_mentorship.sql` at line 19, Remove
the unused club_affiliations UUID[] column from the mentor_profiles schema
unless the feature is being implemented now; if retained, replace it with a
mentor-club join table referenced by mentor_profiles.user_id and clubs.id, and
update useMentorshipDirectory to query that relationship.
src/components/mentorship/RequestMentorshipModal.tsx (2)

121-125: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Announce the error and narrow the caught type.

Add role="alert" to the error container on Lines 121-125 so assistive technology reports the submission failure. Replace catch (err: any) on Line 51 with catch (err: unknown) and narrow with err instanceof Error before you read message. The any type also lets a raw PostgREST error message reach the user interface, which can expose schema details.

Also applies to: 51-52

🤖 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 `@src/components/mentorship/RequestMentorshipModal.tsx` around lines 121 - 125,
Update the error container in RequestMentorshipModal to include role="alert" so
submission failures are announced to assistive technology. Change the submission
handler’s catch clause from err: any to err: unknown, narrow with err instanceof
Error before reading message, and use a safe generic fallback for non-Error
values instead of exposing raw PostgREST details.

49-55: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Clear the auto-close timer and skip the redundant state update.

Two problems exist on the success path:

  1. The setTimeout handle is never stored. If the parent unmounts the modal before the 2000 ms elapse, onClose still runs against a stale closure.
  2. setIsSubmitting(false) in the finally block runs after setSuccess(true). The success branch on Line 58 returns early, so the value is never read.

Track the timer in a ref and clear it in a cleanup effect.

🤖 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 `@src/components/mentorship/RequestMentorshipModal.tsx` around lines 49 - 55,
Update the success handling in RequestMentorshipModal to store the 2000 ms
setTimeout handle in a ref, and add a cleanup effect that clears the timer when
the modal unmounts. Remove the redundant setIsSubmitting(false) update from the
finally block on the successful early-return path while preserving
submission-state cleanup for failures.
🤖 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 `@src/components/mentorship/MentorDirectory.tsx`:
- Around line 42-52: Associate all three filter labels in MentorDirectory with
their controls by adding matching htmlFor values and unique id attributes: use
the proposed mentor-industry and mentor-company identifiers for the selects and
a corresponding stable identifier for the search input. Preserve the existing
filter behavior and styling.
- Around line 16-18: Replace the selectedMentorId state and mentors.find lookup
in MentorDirectory with selectedMentor state typed as MentorProfile | null,
importing MentorProfile from the hook. Update the card onRequest callback to
store the mentor object and the modal onClose handler to clear it, so the modal
remains mounted when refetching or filtering removes the mentor from mentors.

In `@src/components/mentorship/MentorProfileCard.tsx`:
- Around line 24-29: Update the avatar img in MentorProfileCard to always
provide a defined alt value by reusing the same fallback as the heading at line
37 when mentor.profiles.full_name is absent.

In `@src/components/mentorship/RequestMentorshipModal.tsx`:
- Around line 25-28: In RequestMentorshipModal, compute the trimmed message
length once and reuse it across validation, the character counter/hint, and the
submit-button disabled condition. Replace direct message.length checks with this
shared trimmed length so all UI states consistently enforce the 50-character
minimum.
- Around line 58-74: Update the success message in RequestMentorshipModal’s
success rendering to use the same “Alumni” fallback as MentorProfileCard when
mentor.profiles?.full_name is unavailable, including the corresponding
mentor-name rendering around the other referenced occurrence. Preserve the
existing name when present.
- Around line 34-47: Update the request submission flow in
RequestMentorshipModal to obtain the authenticated user via the existing
Supabase auth client, require a valid user id, and include it as mentee_id in
the mentorship_requests insert alongside mentor_id, message, and status.
- Around line 76-79: Update RequestMentorshipModal to use the existing Dialog or
Modal primitive for both the request form and “Request Sent!” states instead of
fixed overlay containers. Add accessible titles for “Request Mentorship” and
“Request Sent!”, preserve focus trapping and Escape-to-close behavior, and
ensure closing restores focus to the MentorProfileCard request trigger.

In `@src/hooks/useMentorshipDirectory.ts`:
- Around line 95-101: Move industry and company option loading out of the
filtered fetch flow: add a separate effect that retrieves distinct values once
without depending on filters, and populate industries and companies from that
unfiltered source. Remove the data-based option-building block and the
industries.length dependency from fetchMentors so option state does not freeze
on empty results or trigger redundant filtered queries.
- Around line 4-6: Convert the SQL-style header comments to valid TypeScript
comments in src/hooks/useMentorshipDirectory.ts lines 4-6,
src/components/mentorship/MentorDirectory.tsx lines 4-6,
src/components/mentorship/MentorProfileCard.tsx lines 3-6, and
src/components/mentorship/RequestMentorshipModal.tsx lines 3-5; remove the stray
indentation before the separator in useMentorshipDirectory.ts. Add a lint step
to the pipeline that prevents non-parsing modules from merging.
- Around line 69-72: Update src/hooks/useMentorshipDirectory.ts lines 69-72 to
select first_name, last_name, and avatar_url, and update its profiles type at
lines 21-24 accordingly; export a helper that composes the display name. Ensure
the mentor_profiles-to-profiles foreign-key relationship required by the embed
is declared. In src/components/mentorship/MentorProfileCard.tsx lines 27-37 and
src/components/mentorship/RequestMentorshipModal.tsx lines 69-92, replace each
full_name access with the shared display-name helper.
- Line 9: Update the Supabase import in useMentorshipDirectory.ts to reference
the existing ../lib/supabase/client module instead of the nonexistent
../../lib/supabaseClient path.
- Around line 77-79: Update the search-filter construction in
useMentorshipDirectory to escape filters.search before interpolating it into
query.or(). Escape backslashes and double quotes, then quote the company and
job_title scalar values and the expertise_tags cs array element so commas,
parentheses, and other PostgREST syntax remain literal.

In `@supabase/migrations/20260825000002_alumni_mentorship.sql`:
- Around line 51-52: Update the SECURITY DEFINER function
update_mentor_capacity() to declare an explicit, trusted search_path in its
function definition, including the schema containing mentor_profiles and any
required built-in schema, so object and function resolution cannot be shadowed
by attacker-controlled schemas.
- Around line 60-76: Update the accepted-to-non-accepted branch of the
mentorship status trigger to stop unconditionally setting is_accepting to TRUE.
Preserve a mentor’s manual opt-out; only reopen automatically when the existing
schema can distinguish that is_accepting was closed by the capacity rule,
otherwise leave the value unchanged. Keep the current_mentees decrement and
updated_at updates intact.
- Around line 12-25: Add a foreign key constraint on mentor_profiles.user_id
referencing public.profiles(id), while preserving the existing auth.users(id)
reference and cascade behavior. Ensure the declared relationship supports the
profiles:user_id embedding used by useMentorshipDirectory.
- Around line 41-42: Replace the unconditional UNIQUE(mentor_id, mentee_id)
constraint in the mentorship requests schema with a partial unique index on
mentor_id and mentee_id that applies only to active request statuses. Preserve
the one-active-request-per-pair rule while allowing new requests after rejected
or completed requests.

---

Nitpick comments:
In `@src/components/mentorship/MentorDirectory.tsx`:
- Around line 119-124: Update the loading container in MentorDirectory’s
isLoading branch to include role="status" and aria-live="polite", and add
role="alert" to the corresponding error container covering the error state.
Leave the existing loading and error content unchanged.

In `@src/components/mentorship/MentorProfileCard.tsx`:
- Around line 71-85: Add progressbar accessibility attributes to the inner
capacity-bar div in MentorProfileCard: set role="progressbar", aria-valuenow to
the current capacity percentage, aria-valuemin to 0, and aria-valuemax to 100,
while preserving the existing styling and width calculation.
- Around line 88-98: Update the mentorship request button in MentorProfileCard
to expose why it is unavailable to assistive technology while preserving the
existing disabled behavior and “Currently Full” label. Add an accessible
explanation using aria-disabled with descriptive text or associate the button
with the capacity message via aria-describedby, ensuring the full-state reason
remains perceivable to keyboard and screen-reader users.

In `@src/components/mentorship/RequestMentorshipModal.tsx`:
- Around line 121-125: Update the error container in RequestMentorshipModal to
include role="alert" so submission failures are announced to assistive
technology. Change the submission handler’s catch clause from err: any to err:
unknown, narrow with err instanceof Error before reading message, and use a safe
generic fallback for non-Error values instead of exposing raw PostgREST details.
- Around line 49-55: Update the success handling in RequestMentorshipModal to
store the 2000 ms setTimeout handle in a ref, and add a cleanup effect that
clears the timer when the modal unmounts. Remove the redundant
setIsSubmitting(false) update from the finally block on the successful
early-return path while preserving submission-state cleanup for failures.

In `@src/hooks/useMentorshipDirectory.ts`:
- Around line 103-105: Update the catch clause in useMentorshipDirectory to use
unknown instead of any, then narrow err before accessing message; preserve the
existing fallback error text and console logging behavior.
- Around line 62-63: Update fetchMentors in useMentorshipDirectory to debounce
requests triggered by search changes and cancel or ignore superseded requests,
using an AbortController or cancellation flag so stale responses cannot update
mentor results. Keep loading and result updates tied only to the latest active
request, and clean up the debounce/cancellation state when dependencies change
or the hook unmounts.

In `@supabase/migrations/20260825000002_alumni_mentorship.sql`:
- Around line 23-24: Add BEFORE UPDATE timestamp triggers for both
mentor_profiles and mentorship_requests so updated_at is refreshed on every row
update, including direct profile edits and mentorship request status changes;
retain the existing capacity trigger behavior and use a shared trigger function
if available.
- Around line 93-96: Update the "Anyone can view mentor profiles" policy to
target the authenticated Postgres role with a TO authenticated clause, and
remove the auth.role() condition from its USING expression. Follow the existing
migration convention while preserving the policy’s SELECT access for
authenticated users.
- Line 19: Remove the unused club_affiliations UUID[] column from the
mentor_profiles schema unless the feature is being implemented now; if retained,
replace it with a mentor-club join table referenced by mentor_profiles.user_id
and clubs.id, and update useMentorshipDirectory to query that relationship.
🪄 Autofix

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 Plus

Run ID: 1efe16cc-5ce6-4c51-b7d7-7278490b6554

📥 Commits

Reviewing files that changed from the base of the PR and between 4599ecd and 673afa9.

📒 Files selected for processing (5)
  • src/components/mentorship/MentorDirectory.tsx
  • src/components/mentorship/MentorProfileCard.tsx
  • src/components/mentorship/RequestMentorshipModal.tsx
  • src/hooks/useMentorshipDirectory.ts
  • supabase/migrations/20260825000002_alumni_mentorship.sql

Comment thread src/components/mentorship/MentorDirectory.tsx
Comment thread src/components/mentorship/MentorDirectory.tsx
Comment thread src/components/mentorship/MentorProfileCard.tsx
Comment thread src/components/mentorship/RequestMentorshipModal.tsx
Comment thread src/components/mentorship/RequestMentorshipModal.tsx
Comment thread src/hooks/useMentorshipDirectory.ts
Comment thread supabase/migrations/20260825000002_alumni_mentorship.sql
Comment thread supabase/migrations/20260825000002_alumni_mentorship.sql
Comment thread supabase/migrations/20260825000002_alumni_mentorship.sql
Comment thread supabase/migrations/20260825000002_alumni_mentorship.sql
@krushit1307
krushit1307 merged commit cda663b into krushit1307:main Aug 12, 2026
3 of 4 checks passed
@Aakif-Kohari
Aakif-Kohari deleted the feat/alumni-mentorship-module branch August 13, 2026 02:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ECSoC26-L3 ECSoC26 Elite Coders Summer Of Code'26 - Open Source Program feature frontend fullstack hard social

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Build an 'Alumni Mentorship' Matching Module

2 participants