Skip to content

Fix: Resolve dropdown conflicts between search and profile menus#4130

Open
samay871 wants to merge 6 commits into
anurag3407:mainfrom
samay871:main
Open

Fix: Resolve dropdown conflicts between search and profile menus#4130
samay871 wants to merge 6 commits into
anurag3407:mainfrom
samay871:main

Conversation

@samay871

@samay871 samay871 commented Jun 16, 2026

Copy link
Copy Markdown

Changes Made

  • Replaced single showDropdown state with searchDropdownOpen and profileDropdownOpen
  • Added mutual exclusion handlers to prevent both dropdowns opening simultaneously
  • Created useClickOutside custom hook for click-outside detection
  • Added Escape key support to close both dropdowns
  • Fixed race condition in search onBlur setTimeout

Testing

  • Search dropdown opens on focus, closes on blur/outside click
  • Profile dropdown opens on button click, closes on outside click
  • Opening one dropdown closes the other
  • Escape key closes both dropdowns

Summary by CodeRabbit

Release Notes

  • New Features

    • Added an email verification prompt for users, with options to resend the verification email and proceed after verification.
    • Enhanced navigation dropdowns with separate search and profile menus.
  • Improvements

    • Dropdowns now close reliably when clicking outside and can be dismissed with the Escape key.
    • Signup now triggers an email verification message before continuing.

samay871 added 2 commits June 16, 2026 10:45
- Replace single showDropdown state with searchDropdownOpen and profileDropdownOpen
- Add mutual exclusion to prevent both dropdowns opening simultaneously  
- Integrate useClickOutside hook for independent closing
- Add Escape key support to close both dropdowns
- Fix race condition in search onBlur setTimeout
… hook for detecting outside clicks

- Creates reusable hook for handling click outside elements
- Supports both mouse and touch events
- Used by Navbar for dropdown close functionality
@vercel

vercel Bot commented Jun 16, 2026

Copy link
Copy Markdown

@samay871 is attempting to deploy a commit to the Anurag Mishra's projects Team on Vercel.

A member of the Team first needs to authorize it.

@codeant-ai

codeant-ai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Skipping CodeAnt AI review — this PR is a back-merge between long-lived branches (mainmain). The diff here has already been reviewed when the underlying commits landed on the source branch, so re-running analysis would produce duplicate findings on already-reviewed code.

If you want to analyze this anyway (e.g. you resolved conflicts with new logic), comment @codeant-ai : review and CodeAnt will start a review.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@samay871, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 14 minutes and 11 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, 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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 76eed64e-0097-4822-b962-31d8028ec92c

📥 Commits

Reviewing files that changed from the base of the PR and between 50ece82 and 4c6e1c7.

📒 Files selected for processing (2)
  • frontend/src/App.jsx
  • frontend/src/components/Navbar.jsx
📝 Walkthrough

Walkthrough

A new useClickOutside hook registers mousedown/touchstart document listeners and fires a callback when clicks occur outside a referenced element. Navbar.jsx replaces the single shared showDropdown state with independent searchDropdownOpen and profileDropdownOpen states, wires the hook and an Escape-key handler to each, and enforces mutual exclusion between the two dropdowns. Separately, AuthProvider now sends email verification immediately after user account creation during signup, and a new EmailVerificationPrompt component provides UI for users to check their verification status and resend verification emails.

Changes

Navbar Decoupled Dropdown State

Layer / File(s) Summary
useClickOutside hook
frontend/src/hooks/useClickOutside.js
New hook attaches mousedown and touchstart listeners to document, invokes the callback when the event target is outside ref.current, and removes both listeners on cleanup.
Dropdown state, refs, and effects
frontend/src/components/Navbar.jsx
Replaces showDropdown with searchDropdownOpen and profileDropdownOpen; adds searchRef/profileRef; wires useClickOutside to each; adds an Escape-key effect closing both; updates imports to include useRef and useClickOutside.
Search dropdown wiring
frontend/src/components/Navbar.jsx
Attaches searchRef to the search bar container; rewires focus to open and blur to schedule closure of searchDropdownOpen; gates suggestions rendering on searchDropdownOpen.
Profile dropdown trigger and menu items
frontend/src/components/Navbar.jsx
Switches the profile button to profileRef and openProfileDropdown; updates aria-expanded to profileDropdownOpen; renders the dropdown menu conditionally from profileDropdownOpen; closes dropdown explicitly on profile link, settings, and logout.
Mobile menu and file cleanup
frontend/src/components/Navbar.jsx
Removes an empty placeholder region before the mobile-menu user block and a redundant trailing blank line.

Email Verification Flow

Layer / File(s) Summary
Email verification during signup
frontend/src/context/AuthProvider.jsx
Adds sendEmailVerification to Firebase Auth imports and sends verification email to the user immediately after account creation, before display name updates.
Email verification prompt component
frontend/src/components/EmailVerificationPrompt.jsx
New component displays the user's email, provides a "Resend verification email" button that triggers sendEmailVerification with loading and error states, and a "I've verified, continue" button that reloads the user and navigates to /dashboard when emailVerified is true.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

  • anurag3407/career-pilot#1182: Modifies the same Navbar.jsx search suggestions and user/avatar dropdown interaction logic that this PR refactors.
  • anurag3407/career-pilot#2455: Also modifies Navbar.jsx scroll-driven styling logic; this PR retains the existing scroll listener while refactoring dropdown state management.

Suggested labels

type:bug, level:intermediate, size:L, quality:clean

Poem

🐇 Hop hop, the dropdowns once fought for one flag,
Now search has its own, and profile won't nag.
A click outside? Poof! The menus are gone.
Escape key pressed? Both vanish at dawn.
Two refs, two states — this rabbit's impressed!
Clean mutual exclusion, and emails verified. 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Fix: Resolve dropdown conflicts between search and profile menus' accurately summarizes the main change—decoupling dropdown states to prevent conflicts, which is the core objective of this changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ 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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@frontend/src/components/Navbar.jsx`:
- Around line 181-185: The onBlur handler schedules a delayed close of the
search dropdown, but if onFocus is triggered before that timeout completes, the
stale timeout will still fire and close the dropdown again, causing flicker.
Store the timeout ID returned by the setTimeout call (in the onBlur handler) in
a ref or state variable, then in the onFocus handler (before calling
openSearchDropdown), clear that stored timeout using clearTimeout. This prevents
the stale blur timer from closing a newly focused dropdown.
🪄 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: 66cb4b99-5a47-409b-b685-59709c1c5201

📥 Commits

Reviewing files that changed from the base of the PR and between 1c7ce5e and 4b7cdd5.

📒 Files selected for processing (2)
  • frontend/src/components/Navbar.jsx
  • frontend/src/hooks/useClickOutside.js

Comment thread frontend/src/components/Navbar.jsx Outdated
samay871 added 2 commits June 16, 2026 23:44
Add Firebase email verification trigger after successful email/password registration.

Changes:
- Import sendEmailVerification from Firebase Auth
- Send verification email after createUserWithEmailAndPassword
- Ensure newly registered accounts must verify email ownership

This prevents unverified email accounts from entering the application flow.
Create a verification screen for users who have not verified their email.

Features:
- Display verification instructions
- Show registered email address
- Add resend verification email action
- Add verification refresh action using user.reload()

Allows users to continue after successful Firebase email verification.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@frontend/src/context/AuthProvider.jsx`:
- Around line 60-63: The sendEmailVerification call at line 62 is in the
hard-fail path and will cause the entire signup to fail if it throws an error,
even though the user account has already been successfully created at line 60 by
createUserWithEmailAndPassword. Wrap the sendEmailVerification call in a
try-catch block so that email verification failures are caught and logged
separately without causing the signup operation to fail. This allows the signup
process to complete successfully for the user even if the verification email
delivery fails due to network issues, rate limiting, or provider errors,
preventing confusing UX where users retry with the same email and encounter
"email already in use" errors.
🪄 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: 2a8f59c6-e8f7-4832-b7b6-0c479782bd28

📥 Commits

Reviewing files that changed from the base of the PR and between 4b7cdd5 and e3d2460.

📒 Files selected for processing (1)
  • frontend/src/context/AuthProvider.jsx

Comment on lines 60 to +63
const result = await createUserWithEmailAndPassword(auth, email, password)

await sendEmailVerification(result.user)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

For Firebase JS SDK v11 (firebase/auth), does sendEmailVerification(user)reject on transient/provider errors aftercreateUserWithEmailAndPassword succeeds, and what handling pattern is recommended to avoid treating account creation as failed?

💡 Result:

In the Firebase JS SDK, the sendEmailVerification(user) function is an independent asynchronous operation that is decoupled from the createUserWithEmailAndPassword call [1][2]. Consequently, sendEmailVerification can reject with errors (such as auth/too-many-requests or auth/network-request-failed) even after a successful account creation [3][4][5]. Because createUserWithEmailAndPassword automatically signs the user in [6][7][8], the account is already persisted in Firebase Authentication by the time you attempt to send the verification email [5][9]. If the verification email fails to send, the user's account remains active and the user is still considered logged in [6][8]. Recommended Handling Pattern: To avoid treating the entire sign-up flow as a failure when only the email delivery fails, implement a decoupled error-handling strategy: 1. Separate Concerns: Do not block the application flow or treat account creation as a failure if sendEmailVerification throws an error [9]. 2. User Feedback: Inform the user that their account was created successfully, but that the verification email could not be sent immediately. Provide a UI mechanism (e.g., a "Resend Verification Email" button) to allow the user to retry the operation later [3][4]. 3. Graceful Error Handling: Catch the error from sendEmailVerification specifically, log it, and update the UI to notify the user without affecting their authenticated state [3][5]. Example Pattern: const { user } = await createUserWithEmailAndPassword(auth, email, password); try { await sendEmailVerification(user); // Notify user: "Account created! Please check your email." } catch (error) { console.error("Verification email failed:", error); // Notify user: "Account created, but we couldn't send the verification email. You can request a new one later." // Do not log the user out or delete the account. } This approach ensures that the account is preserved and the user can continue using the application, while still allowing them to eventually verify their email address [4][8].

Citations:


🏁 Script executed:

# First, find the AuthProvider.jsx file
fd -type f -name "AuthProvider.jsx"

Repository: anurag3407/career-pilot

Length of output: 238


🏁 Script executed:

# Find the AuthProvider.jsx file
fd "AuthProvider.jsx"

Repository: anurag3407/career-pilot

Length of output: 105


🏁 Script executed:

# Read the AuthProvider.jsx file to see lines 60-63
cat -n frontend/src/context/AuthProvider.jsx | sed -n '50,75p'

Repository: anurag3407/career-pilot

Length of output: 1284


🏁 Script executed:

# Find and check Register.jsx to see how signup errors are handled
fd "Register.jsx" | head -5

Repository: anurag3407/career-pilot

Length of output: 99


🏁 Script executed:

# Read Register.jsx to see how signup is called and errors are handled
cat -n frontend/src/pages/Register.jsx | head -150

Repository: anurag3407/career-pilot

Length of output: 6024


Don't fail the whole signup on verification-email delivery failure.

At Line 62, sendEmailVerification is in the hard-fail path after account creation at Line 60. If that call throws (due to network issues, rate limiting, or provider errors), the caller sees signup failure even though the user already exists in Firebase, which creates a confusing UX where users retry with the same email and encounter "email already in use" errors.

Suggested fix
   const result = await createUserWithEmailAndPassword(auth, email, password)
-
-  await sendEmailVerification(result.user)
+  try {
+    await sendEmailVerification(result.user)
+  } catch (verificationError) {
+    // Account is already created; keep signup successful and handle notification separately.
+    console.warn('Failed to send verification email:', verificationError)
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const result = await createUserWithEmailAndPassword(auth, email, password)
await sendEmailVerification(result.user)
const result = await createUserWithEmailAndPassword(auth, email, password)
try {
await sendEmailVerification(result.user)
} catch (verificationError) {
// Account is already created; keep signup successful and handle notification separately.
console.warn('Failed to send verification email:', verificationError)
}
🤖 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 `@frontend/src/context/AuthProvider.jsx` around lines 60 - 63, The
sendEmailVerification call at line 62 is in the hard-fail path and will cause
the entire signup to fail if it throws an error, even though the user account
has already been successfully created at line 60 by
createUserWithEmailAndPassword. Wrap the sendEmailVerification call in a
try-catch block so that email verification failures are caught and logged
separately without causing the signup operation to fail. This allows the signup
process to complete successfully for the user even if the verification email
delivery fails due to network issues, rate limiting, or provider errors,
preventing confusing UX where users retry with the same email and encounter
"email already in use" errors.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@frontend/src/components/EmailVerificationPrompt.jsx`:
- Around line 28-41: The checkVerification function lacks in-flight state
tracking, allowing users to trigger overlapping reload() calls that can
interleave message updates and race conditions. Add a loading or in-flight state
variable (similar to what the resendEmail function implements) to guard the
checkVerification async function so it cannot execute while already in progress.
Set this state to true before calling user.reload(), and set it to false in both
the success path (after navigating or setting message) and the catch block.
Ensure the resendEmail function at lines 62-74 follows the same pattern to
prevent overlapping operations between both asynchronous flows.
- Around line 13-33: Add guard checks in the checkVerification function before
invoking user.reload() and accessing user.emailVerified to verify that the user
object is a Firebase User instance (checking for the presence of required
methods/properties) to prevent runtime errors when running with the AuthProvider
dev-mode fallback mock user. Additionally, add disabled={loading} to the check
button element to prevent concurrent invocations when a verification check is
already in progress.
🪄 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: 742688fe-d797-446b-949b-4e5afb2869c1

📥 Commits

Reviewing files that changed from the base of the PR and between e3d2460 and 50ece82.

📒 Files selected for processing (1)
  • frontend/src/components/EmailVerificationPrompt.jsx

Comment on lines +13 to +33
const resendEmail = async () => {
try {
setLoading(true);

await sendEmailVerification(user);

setMessage("Verification email sent successfully.");
} catch (error) {
setMessage(error.message);
} finally {
setLoading(false);
}
};


const checkVerification = async () => {
try {
await user.reload();

if (user.emailVerified) {
navigate("/dashboard");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify where EmailVerificationPrompt is rendered and inspect user-shape contracts.
rg -n -C3 "EmailVerificationPrompt|verify.*email|/dashboard" frontend/src
rg -n -C3 "setUser\\(|dev-user-001|emailVerified|reload|getIdToken" frontend/src/context/AuthProvider.jsx

Repository: anurag3407/career-pilot

Length of output: 24364


🏁 Script executed:

cat -n frontend/src/components/EmailVerificationPrompt.jsx

Repository: anurag3407/career-pilot

Length of output: 2544


🏁 Script executed:

rg -n "sendEmailVerification" frontend/src --type jsx --type js -A2 | head -30

Repository: anurag3407/career-pilot

Length of output: 95


🏁 Script executed:

rg -n "sendEmailVerification" frontend/src --type js -B2 -A2

Repository: anurag3407/career-pilot

Length of output: 1560


🏁 Script executed:

# Check if there are any tests or other usages of EmailVerificationPrompt that might reveal expected behavior
rg -n "EmailVerificationPrompt" frontend/src --type jsx --type js

Repository: anurag3407/career-pilot

Length of output: 95


🏁 Script executed:

# Check AuthProvider's full context around setUser and mock user creation
sed -n '25,50p' frontend/src/context/AuthProvider.jsx

Repository: anurag3407/career-pilot

Length of output: 672


🏁 Script executed:

# Look for other components that use Firebase user methods safely
rg -n "user\.(reload|emailVerified)" frontend/src --type js

Repository: anurag3407/career-pilot

Length of output: 236


🏁 Script executed:

# Check if there are guards or utility functions for Firebase user checks elsewhere
rg -n "typeof.*function|reload.*function|emailVerified" frontend/src --type js -B2 -A1

Repository: anurag3407/career-pilot

Length of output: 1180


Guard Firebase-user API calls before invoking verification methods.

Lines 30 and 32 assume user is a Firebase User object with reload() method and emailVerified property. The AuthProvider dev-mode fallback creates a mock user without these members, causing runtime errors in local development. Additionally, line 71's check button lacks a loading disabled state, allowing concurrent invocations.

🤖 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 `@frontend/src/components/EmailVerificationPrompt.jsx` around lines 13 - 33,
Add guard checks in the checkVerification function before invoking user.reload()
and accessing user.emailVerified to verify that the user object is a Firebase
User instance (checking for the presence of required methods/properties) to
prevent runtime errors when running with the AuthProvider dev-mode fallback mock
user. Additionally, add disabled={loading} to the check button element to
prevent concurrent invocations when a verification check is already in progress.

Comment on lines +28 to +41
const checkVerification = async () => {
try {
await user.reload();

if (user.emailVerified) {
navigate("/dashboard");
} else {
setMessage("Email is still not verified.");
}

} catch (error) {
setMessage(error.message);
}
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Prevent overlapping async actions for resend/check flows.

checkVerification has no in-flight state while resendEmail does. On Line [71], users can trigger repeated reload() calls and interleave message updates with resend operations.

Suggested fix
   const [message, setMessage] = useState("");
   const [loading, setLoading] = useState(false);
+  const [checking, setChecking] = useState(false);
@@
   const checkVerification = async () => {
     try {
+      setChecking(true);
       await user.reload();
@@
     } catch (error) {
       setMessage(error.message);
+    } finally {
+      setChecking(false);
     }
   };
@@
           <button
             onClick={resendEmail}
-            disabled={loading || !canUseVerificationApis}
+            disabled={loading || checking || !canUseVerificationApis}
           >
             {loading ? "Sending..." : "Resend verification email"}
           </button>
@@
           <button
             onClick={checkVerification}
-            disabled={loading || !canUseVerificationApis}
+            disabled={loading || checking || !canUseVerificationApis}
           >
-            I've verified, continue
+            {checking ? "Checking..." : "I've verified, continue"}
           </button>

Also applies to: 62-74

🤖 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 `@frontend/src/components/EmailVerificationPrompt.jsx` around lines 28 - 41,
The checkVerification function lacks in-flight state tracking, allowing users to
trigger overlapping reload() calls that can interleave message updates and race
conditions. Add a loading or in-flight state variable (similar to what the
resendEmail function implements) to guard the checkVerification async function
so it cannot execute while already in progress. Set this state to true before
calling user.reload(), and set it to false in both the success path (after
navigating or setting message) and the catch block. Ensure the resendEmail
function at lines 62-74 follows the same pattern to prevent overlapping
operations between both asynchronous flows.

samay871 and others added 2 commits June 16, 2026 23:53
Add email verification protection to authenticated routes.

Changes:
- Add EmailVerificationPrompt integration
- Check user.emailVerified inside ProtectedRoute
- Prevent unverified users from accessing protected pages

Verified users continue to access the application normally.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
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.

1 participant