Skip to content

Conversation

@gaurav123-4
Copy link

@gaurav123-4 gaurav123-4 commented Jul 28, 2025

Related Issue

  • Closes: #

Description


How Has This Been Tested?


Screenshots (if applicable)


Type of Change

  • Bug fix
  • New feature
  • Code style update
  • Breaking change
  • Documentation update

Summary by CodeRabbit

  • New Features

    • Added GitHub authentication to the navigation bar, displaying user-specific options such as profile access, edit profile, and logout.
    • Enabled persistent login state across sessions.
    • Introduced the ability for authenticated users to edit their bio directly from their profile page.
  • Enhancements

    • Improved user profile page with a larger avatar, bio editing controls, character count, and animated loading spinner.
    • Redesigned pull request list with a card grid layout and visual enhancements for better readability.
  • Bug Fixes

    • Ensured menus and dropdowns close correctly on navigation or logout for a smoother user experience.

@netlify
Copy link

netlify bot commented Jul 28, 2025

Deploy Preview for github-spy failed.

Name Link
🔨 Latest commit 474b4a0
🔍 Latest deploy log https://app.netlify.com/projects/github-spy/deploys/6888f94628feb900089a34ac

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 28, 2025

Walkthrough

The changes introduce GitHub authentication state management and user-specific UI elements to the Navbar, persist authentication data using localStorage in a custom hook, and enable authenticated users to edit their bio on the UserProfile page. The UserProfile UI is updated with improved styling, editing controls, and enhanced pull request displays.

Changes

Cohort / File(s) Change Summary
Navbar GitHub Auth Integration
src/components/Navbar.tsx
Enhanced Navbar to display GitHub authentication state, user avatar, username, and a dropdown menu with profile and logout options; integrated useGitHubAuth for state and logout, and managed dropdown visibility for desktop/mobile.
GitHub Auth Hook Persistence
src/hooks/useGitHubAuth.ts
Modified hook to persist username and token in localStorage, updated setters to sync with localStorage, and added a logout function that clears both state and storage; exposed logout in the returned hook object.
UserProfile Bio Editing & UI Update
src/pages/UserProfile/UserProfile.tsx
Enabled authenticated users to edit their bio, added edit/save/cancel controls, improved avatar and PR list styling, and handled bio updates via GitHub API; included conditional rendering for own profile and edit mode.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Navbar
    participant useGitHubAuth
    participant UserProfile
    participant GitHubAPI

    User->>Navbar: Loads page
    Navbar->>useGitHubAuth: Get username, token
    useGitHubAuth-->>Navbar: Returns auth state
    alt User clicks Logout
        Navbar->>useGitHubAuth: logout()
        useGitHubAuth-->>Navbar: Clears state & localStorage
        Navbar->>User: Navigates to login
    end

    User->>UserProfile: Navigates to profile page
    UserProfile->>useGitHubAuth: Get username, token
    useGitHubAuth-->>UserProfile: Returns auth state
    alt User edits own profile
        User->>UserProfile: Clicks Edit
        UserProfile->>User: Shows textarea
        User->>UserProfile: Clicks Save
        UserProfile->>GitHubAPI: PATCH user bio with token
        GitHubAPI-->>UserProfile: Returns updated bio
        UserProfile->>User: Updates UI
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

level2

Poem

A bunny hops through code anew,
With avatars, bios, and dropdowns too!
GitHub logins now persist with care,
Edit your bio—show you’re rare!
PRs in cards, a spinner spins bright,
This fluffy release feels just right.
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c048806 and 474b4a0.

📒 Files selected for processing (3)
  • src/components/Navbar.tsx (7 hunks)
  • src/hooks/useGitHubAuth.ts (2 hunks)
  • src/pages/UserProfile/UserProfile.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/hooks/useGitHubAuth.ts
🧰 Additional context used
🪛 Biome (2.1.2)
src/pages/UserProfile/UserProfile.tsx

[error] 3-3: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 31-31: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 78-78: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 104-105: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 105-105: expected ) but instead found gsoc

Remove gsoc

(parse)


[error] 105-106: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


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

An explicit or implicit semicolon is expected here...

...Which is required to end this statement

(parse)


[error] 107-107: expected , but instead found &&

Remove &&

(parse)


[error] 108-108: expected , but instead found <

Remove <

(parse)


[error] 108-108: expected , but instead found className

Remove className

(parse)


[error] 109-109: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 109-109: expected , but instead found className

Remove className

(parse)


[error] 110-110: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 111-111: expected , but instead found src

Remove src

(parse)


[error] 111-111: ';' expected'

An explicit or implicit semicolon is expected here...

(parse)


[error] 112-112: expected , but instead found alt

Remove alt

(parse)


[error] 113-113: expected , but instead found className

Remove className

(parse)


[error] 114-114: expected , but instead found /

Remove /

(parse)


[error] 114-115: Expected an expression but instead found '>'.

Expected an expression here.

(parse)


[error] 115-115: expected , but instead found &&

Remove &&

(parse)


[error] 116-116: expected , but instead found <

Remove <

(parse)


[error] 116-116: expected , but instead found className

Remove className

(parse)


[error] 116-116: expected , but instead found title

Remove title

(parse)


[error] 116-116: expected , but instead found onClick

Remove onClick

(parse)


[error] 116-116: ';' expected'

An explicit or implicit semicolon is expected here...

(parse)


[error] 116-116: expected , but instead found ?

Remove ?

(parse)


[error] 116-116: expected , but instead found edit

Remove edit

(parse)


[error] 116-116: expected , but instead found ```

Remove `

(parse)


[error] 117-117: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 117-117: expected , but instead found className

Remove className

(parse)


[error] 117-117: expected , but instead found fill

Remove fill

(parse)


[error] 117-117: expected , but instead found stroke

Remove stroke

(parse)


[error] 117-117: expected , but instead found strokeWidth

Remove strokeWidth

(parse)


[error] 117-117: expected , but instead found viewBox

Remove viewBox

(parse)


[error] 118-118: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 118-118: expected , but instead found strokeLinecap

Remove strokeLinecap

(parse)


[error] 118-118: expected , but instead found strokeLinejoin

Remove strokeLinejoin

(parse)


[error] 118-118: expected , but instead found d

Remove d

(parse)


[error] 118-118: expected , but instead found /

Remove /

(parse)


[error] 119-119: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 119-119: Expected a type parameter but instead found '/'.

Expected a type parameter here.

(parse)


[error] 119-119: expected , but instead found svg

Remove svg

(parse)


[error] 120-120: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 120-120: Expected a type parameter but instead found '/'.

Expected a type parameter here.

(parse)


[error] 120-120: expected , but instead found span

Remove span

(parse)


[error] 121-121: Expected a parenthesis '(' but instead found ')'.

Expected a parenthesis '(' here.

(parse)


[error] 122-122: Expected an expression but instead found '<'.

Expected an expression here.

(parse)


[error] 123-124: Expected an expression but instead found ''.

Expected an expression here.

(parse)


[error] 158-158: Expected an expression but instead found '<'.

Expected an expression here.

(parse)


[error] 177-177: Expected an expression but instead found '<'.

Expected an expression here.

(parse)

src/components/Navbar.tsx

[error] 1-1: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)

🔇 Additional comments (2)
src/pages/UserProfile/UserProfile.tsx (2)

124-157: Excellent bio editing interface implementation.

The bio editing UI provides a great user experience with character counting, proper validation, and clear save/cancel actions.

The implementation correctly:

  • Shows character count with limit enforcement
  • Provides proper form controls with disabled states during saving
  • Uses conditional rendering for edit mode
  • Includes proper placeholder text and styling

160-177: Great improvement to pull requests display.

The enhanced PR display with card layout, repository names, and visual icons significantly improves the user experience over the basic list format.

Key improvements include:

  • Card-based layout with proper spacing and shadows
  • Repository name extraction and display
  • Visual icons for better recognition
  • Hover effects for interactivity
  • Fallback message when no PRs are found
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (4)
src/hooks/useGitHubAuth.ts (1)

17-22: LGTM! Consider adding error handling for localStorage operations.

The logout implementation correctly clears both state and storage. For robustness:

 const logout = () => {
   setUsernameState('');
   setTokenState('');
-  localStorage.removeItem('username');
-  localStorage.removeItem('token');
+  try {
+    localStorage.removeItem('username');
+    localStorage.removeItem('token');
+  } catch (error) {
+    console.error('Failed to clear localStorage:', error);
+  }
 };
src/components/Navbar.tsx (2)

54-100: Consider adding click-outside handler for dropdown.

The dropdown implementation is functional but could benefit from closing when clicking outside:

// Add this after the imports
import { useEffect, useRef } from 'react';

// Inside the component, add:
const dropdownRef = useRef<HTMLDivElement>(null);

useEffect(() => {
  const handleClickOutside = (event: MouseEvent) => {
    if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
      setDropdownOpen(false);
    }
  };
  
  if (dropdownOpen) {
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }
}, [dropdownOpen]);

// Update the dropdown container div:
<div className="relative" ref={dropdownRef}>

160-207: Consider extracting the user menu to reduce duplication.

The mobile implementation works well, but the user dropdown logic is duplicated. Consider extracting it into a separate component:

Would you like me to create a UserDropdown component to eliminate the duplication between desktop and mobile views?

src/pages/UserProfile/UserProfile.tsx (1)

89-122: Well-implemented bio editing UI.

The editing interface is user-friendly with character count and proper form controls. Consider adding visual feedback for save errors based on the earlier error handling suggestion.

Consider adding aria-label attributes for better accessibility:

 <textarea
   className="w-full border-2 border-blue-200 rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-blue-400 text-gray-800 text-base resize-none shadow"
   rows={3}
   maxLength={maxBioLength}
   value={editBio}
   onChange={e => setEditBio(e.target.value)}
   placeholder="Edit your bio"
+  aria-label="Bio text"
 />
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61dc8a2 and 155d0f5.

📒 Files selected for processing (3)
  • src/components/Navbar.tsx (3 hunks)
  • src/hooks/useGitHubAuth.ts (2 hunks)
  • src/pages/UserProfile/UserProfile.tsx (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/components/Navbar.tsx (1)
src/hooks/useGitHubAuth.ts (1)
  • useGitHubAuth (4-39)
🔇 Additional comments (5)
src/hooks/useGitHubAuth.ts (1)

37-37: LGTM!

The logout function is correctly exposed in the hook's API.

src/components/Navbar.tsx (2)

1-14: LGTM! Clean integration of authentication state.

The authentication hook integration and logout handling are well implemented.


77-97: LGTM! Well-structured dropdown menu.

The menu items are properly implemented with appropriate navigation and state management.

src/pages/UserProfile/UserProfile.tsx (2)

12-23: LGTM! Clear state management and ownership logic.

Good use of descriptive variable names and proper separation of concerns between viewing and editing states.


61-68: LGTM! Nice loading spinner implementation.

The animated SVG spinner provides good visual feedback during data loading.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🔭 Outside diff range comments (5)
src/components/Navbar.tsx (3)

6-26: Remove duplicate component definitions and imports.

The component has duplicate imports and initialization logic due to unresolved merge conflicts. The ThemeContext import and usage are missing in the first version.

Properly merge the authentication and theme functionality:

+import { Link, useNavigate } from 'react-router-dom';
+import { useState, useContext } from 'react';
+import { useGitHubAuth } from '../hooks/useGitHubAuth';
+import { ThemeContext } from "../ThemeContext";

const Navbar: React.FC = () => {
  const [isOpen, setIsOpen] = useState<boolean>(false);
  const [dropdownOpen, setDropdownOpen] = useState(false);
  const { username, logout } = useGitHubAuth();
  const navigate = useNavigate();
+  const themeContext = useContext(ThemeContext);
+  if (!themeContext) return null;
+  const { toggleTheme, mode } = themeContext;

  const handleLogout = () => {
    logout();
    navigate('/login');
  };

67-128: Remove duplicate authentication UI and Login link.

There's duplicate authentication logic and a redundant Login link that appears even when the user is authenticated.

Remove the duplicate Login link (lines 116-121) since authentication is already handled conditionally above:

          )}

-          <Link
-            to="/login"
-            className="text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
-          >
-            Login
-          </Link>
          <button
            onClick={toggleTheme}
            className="text-sm font-semibold px-3 py-1 rounded border border-gray-500 hover:text-gray-300 hover:border-gray-300 transition duration-200"
          >
            {mode === "dark" ? "🌞 Light" : "🌙 Dark"}
          </button>

237-254: Remove duplicate Login link in mobile menu.

Similar to the desktop menu, there's a duplicate Login link in the mobile menu.

Remove the duplicate Login link in mobile menu:

            )}

-            <Link
-              to="/login"
-              className="block text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
-              onClick={() => setIsOpen(false)}
-            >
-              Login
-            </Link>
            <button
              onClick={() => {
                toggleTheme();
                setIsOpen(false);
              }}
              className="text-sm font-semibold px-3 py-1 rounded border border-gray-500 hover:text-gray-300 hover:border-gray-300 transition duration-200 w-full text-left"
            >
              {mode === "dark" ? "🌞 Light" : "🌙 Dark"}
            </button>
src/pages/UserProfile/UserProfile.tsx (2)

31-57: Remove duplicate fetchData logic and resolve merge conflicts.

The useEffect contains duplicate data fetching logic due to unresolved merge conflicts. The first version lacks error handling while the second has proper error handling.

Keep only the version with proper error handling and remove the duplicate:

  useEffect(() => {
    async function fetchData() {
-gsoc-2025Gaurav
-      if (!paramUsername) return;
-      const userRes = await fetch(`https://api.github.com/users/${paramUsername}`);
-      const userData = await userRes.json();
-      setProfile(userData);
-      setEditBio(userData.bio || "");
-      const prsRes = await fetch(`https://api.github.com/search/issues?q=author:${paramUsername}+type:pr`);
-      const prsData = await prsRes.json();
-      setPRs(prsData.items);
-      setLoading(false);
-
-      if (!username) return;
+      if (!paramUsername) return;

      try {
-        const userRes = await fetch(`https://api.github.com/users/${username}`);
+        const userRes = await fetch(`https://api.github.com/users/${paramUsername}`);
        const userData = await userRes.json();
        setProfile(userData);
+        setEditBio(userData.bio || "");

-        const prsRes = await fetch(`https://api.github.com/search/issues?q=author:${username}+type:pr`);
+        const prsRes = await fetch(`https://api.github.com/search/issues?q=author:${paramUsername}+type:pr`);
        const prsData = await prsRes.json();
        setPRs(prsData.items);
      } catch (error) {
        toast.error("Failed to fetch user data.");
      } finally {
        setLoading(false);
      }
-main
    }
    fetchData();
  }, [paramUsername]);

178-214: Remove duplicate profile display section.

There's a complete duplicate of the profile display section at the bottom of the component, which creates confusion and unnecessary code duplication.

Remove the duplicate profile section:

-    <div className="max-w-3xl mx-auto mt-10 p-4 bg-white shadow-xl rounded-xl">
-      <div className="text-center">
-        <img src={profile.avatar_url} alt="Avatar" className="w-24 h-24 mx-auto rounded-full" />
-        <h2 className="text-2xl font-bold mt-2">{profile.login}</h2>
-        <p className="text-gray-600">{profile.bio}</p>
-        <button
-          onClick={handleCopyLink}
-          className="mt-4 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition"
-        >
-          Copy Shareable Link
-        </button>
-      </div>
-
-      <h3 className="text-xl font-semibold mt-6 mb-2">Pull Requests</h3>
-      {prs.length > 0 ? (
-        <ul className="list-disc ml-6 space-y-2">
-          {prs.map((pr, i) => {
-            const repoName = pr.repository_url.split("/").slice(-2).join("/");
-            return (
-              <li key={i}>
-                <a
-                  href={pr.html_url}
-                  target="_blank"
-                  rel="noopener noreferrer"
-                  className="text-blue-600 hover:underline"
-                >
-                  [{repoName}] {pr.title}
-                </a>
-              </li>
-            );
-          })}
-        </ul>
-      ) : (
-        <p className="text-gray-600">No pull requests found for this user.</p>
-      )}
-main
-    </div>

If you need the "Copy Shareable Link" functionality, integrate it into the main profile section above.

♻️ Duplicate comments (2)
src/pages/UserProfile/UserProfile.tsx (2)

62-76: Add error handling and improve navigation.

The handleSave function still lacks error handling and uses window.location.href for navigation, which are issues flagged in previous reviews.

This was already identified in past review comments. Apply the suggested error handling and navigation improvements:

+import { useNavigate } from 'react-router-dom';

+const navigate = useNavigate();

const handleSave = async () => {
  if (!token) return;
  setSaving(true);
-  await fetch("https://api.github.com/user", {
-    method: "PATCH", 
-    headers: {
-      "Authorization": `token ${token}`,
-      "Accept": "application/vnd.github+json",
-      "Content-Type": "application/json",
-    },
-    body: JSON.stringify({ bio: editBio }),
-  });
-  setSaving(false);
-  window.location.href = `/user/${paramUsername}`;
+  try {
+    const response = await fetch("https://api.github.com/user", {
+      method: "PATCH",
+      headers: {
+        "Authorization": `token ${token}`,
+        "Accept": "application/vnd.github+json", 
+        "Content-Type": "application/json",
+      },
+      body: JSON.stringify({ bio: editBio }),
+    });
+    
+    if (!response.ok) {
+      throw new Error(`Failed to update bio: ${response.status}`);
+    }
+    
+    setProfile(prev => ({ ...prev, bio: editBio }));
+    navigate(`/user/${paramUsername}`, { replace: true });
+  } catch (error) {
+    console.error('Failed to save bio:', error);
+    toast.error("Failed to save bio. Please try again.");
+  } finally {
+    setSaving(false);
+  }
};

78-82: Fix handleCancel navigation and resolve merge conflict marker.

The handleCancel function has unused editMode state and contains merge conflict markers.

Remove merge conflict markers and improve navigation as suggested in past reviews:

+import { useNavigate } from 'react-router-dom';

+const navigate = useNavigate();

-gsoc-2025Gaurav
const handleCancel = () => {
  setEditBio(profile.bio || "");
-  setEditMode(false);
+  navigate(`/user/${paramUsername}`, { replace: true });
};
🧹 Nitpick comments (1)
src/components/Navbar.tsx (1)

114-114: Improve accessibility and user experience for dropdown.

The dropdown implementation could benefit from better accessibility and click-outside handling.

Consider adding click-outside handling and proper ARIA attributes:

+import { useEffect, useRef } from 'react';

+const dropdownRef = useRef<HTMLDivElement>(null);

+useEffect(() => {
+  const handleClickOutside = (event: MouseEvent) => {
+    if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
+      setDropdownOpen(false);
+    }
+  };
+  if (dropdownOpen) {
+    document.addEventListener('mousedown', handleClickOutside);
+    return () => document.removeEventListener('mousedown', handleClickOutside);
+  }
+}, [dropdownOpen]);

-            <div className="relative">
+            <div className="relative" ref={dropdownRef}>
              <button
                className="flex items-center space-x-2 focus:outline-none"
                onClick={() => setDropdownOpen((v) => !v)}
+                aria-expanded={dropdownOpen}
+                aria-haspopup="true"
              >
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 155d0f5 and c048806.

📒 Files selected for processing (2)
  • src/components/Navbar.tsx (7 hunks)
  • src/pages/UserProfile/UserProfile.tsx (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/components/Navbar.tsx (1)
src/hooks/useGitHubAuth.ts (1)
  • useGitHubAuth (4-39)
🪛 Biome (2.1.2)
src/pages/UserProfile/UserProfile.tsx

[error] 3-3: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 31-31: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 78-78: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 104-105: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 105-105: expected ) but instead found className

Remove className

(parse)


[error] 106-106: expected , but instead found &&

Remove &&

(parse)


[error] 107-107: expected , but instead found <

Remove <

(parse)


[error] 107-107: expected , but instead found className

Remove className

(parse)


[error] 108-108: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 108-108: expected , but instead found className

Remove className

(parse)


[error] 109-109: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 110-110: expected , but instead found src

Remove src

(parse)


[error] 110-110: ';' expected'

An explicit or implicit semicolon is expected here...

(parse)


[error] 111-111: expected , but instead found alt

Remove alt

(parse)


[error] 112-112: expected , but instead found className

Remove className

(parse)


[error] 113-113: expected , but instead found /

Remove /

(parse)


[error] 113-114: Expected an expression but instead found '>'.

Expected an expression here.

(parse)


[error] 114-114: expected , but instead found &&

Remove &&

(parse)


[error] 115-115: expected , but instead found <

Remove <

(parse)


[error] 115-115: expected , but instead found className

Remove className

(parse)


[error] 115-115: expected , but instead found title

Remove title

(parse)


[error] 115-115: expected , but instead found onClick

Remove onClick

(parse)


[error] 115-115: ';' expected'

An explicit or implicit semicolon is expected here...

(parse)


[error] 115-115: expected , but instead found ?

Remove ?

(parse)


[error] 115-115: expected , but instead found edit

Remove edit

(parse)


[error] 115-115: expected , but instead found ```

Remove `

(parse)


[error] 116-116: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 116-116: expected , but instead found className

Remove className

(parse)


[error] 116-116: expected , but instead found fill

Remove fill

(parse)


[error] 116-116: expected , but instead found stroke

Remove stroke

(parse)


[error] 116-116: expected , but instead found strokeWidth

Remove strokeWidth

(parse)


[error] 116-116: expected , but instead found viewBox

Remove viewBox

(parse)


[error] 117-117: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 117-117: expected , but instead found strokeLinecap

Remove strokeLinecap

(parse)


[error] 117-117: expected , but instead found strokeLinejoin

Remove strokeLinejoin

(parse)


[error] 117-117: expected , but instead found d

Remove d

(parse)


[error] 117-117: expected , but instead found /

Remove /

(parse)


[error] 118-118: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 118-118: Expected a type parameter but instead found '/'.

Expected a type parameter here.

(parse)


[error] 118-118: expected , but instead found svg

Remove svg

(parse)


[error] 119-119: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 119-119: Expected a type parameter but instead found '/'.

Expected a type parameter here.

(parse)


[error] 119-119: expected , but instead found span

Remove span

(parse)


[error] 120-120: Expected a parenthesis '(' but instead found ')'.

Expected a parenthesis '(' here.

(parse)


[error] 121-121: Expected an expression but instead found '<'.

Expected an expression here.

(parse)


[error] 122-123: Expected an expression but instead found ''.

Expected an expression here.

(parse)


[error] 157-157: Expected an expression but instead found '<'.

Expected an expression here.

(parse)


[error] 176-176: Expected an expression but instead found '<'.

Expected an expression here.

(parse)

src/components/Navbar.tsx

[error] 1-1: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)

Comment on lines +104 to +177
gsoc-2025Gaurav
<div className="flex flex-col items-center bg-gradient-to-br from-white to-gray-100 shadow-2xl rounded-2xl p-8 max-w-xl mx-auto mt-16">
{profile && (
<div className="flex flex-col items-center w-full">
<div className="relative group">
<img
src={profile.avatar_url}
alt="Avatar"
className="w-32 h-32 rounded-full border-4 border-blue-400 shadow-lg transition-transform group-hover:scale-105"
/>
{isOwnProfile && !isEdit && (
<span className="absolute bottom-2 right-2 bg-blue-600 text-white rounded-full p-1 shadow-lg cursor-pointer" title="Edit Profile" onClick={() => window.location.href = `/user/${paramUsername}?edit=1`}>
<svg className="w-5 h-5" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M15.232 5.232l3.536 3.536M9 13l6.586-6.586a2 2 0 112.828 2.828L11.828 15.828a2 2 0 01-2.828 0L9 13zm0 0V17h4" />
</svg>
</span>
)}
</div>
<h2 className="text-3xl font-bold mt-4">{profile.login}</h2>
{isEdit && isOwnProfile ? (
<div className="mt-4 w-full">
<div className="flex items-center mb-2">
<span className="font-semibold text-gray-700 mr-2">Bio</span>
<span className="text-xs text-gray-400">({editBio.length}/{maxBioLength})</span>
</div>
<textarea
className="w-full border-2 border-blue-200 rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-blue-400 text-gray-800 text-base resize-none shadow"
rows={3}
maxLength={maxBioLength}
value={editBio}
onChange={e => setEditBio(e.target.value)}
placeholder="Edit your bio"
/>
<div className="flex gap-3 mt-3">
<button
className="px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-full shadow transition"
onClick={handleSave}
disabled={saving}
>
{saving ? "Saving..." : "Save Bio"}
</button>
<button
className="px-6 py-2 bg-gray-300 hover:bg-gray-400 text-gray-800 rounded-full shadow transition"
onClick={handleCancel}
disabled={saving}
>
Cancel
</button>
</div>
</div>
) : (
<p className="text-lg text-gray-700 mt-4 text-center max-w-md">{profile.bio || <span className="italic text-gray-400">No bio provided.</span>}</p>
)}
</div>
)}
<h3 className="text-2xl font-semibold mt-10 mb-4 w-full text-left">Pull Requests</h3>
<div className="grid grid-cols-1 gap-4 w-full">
{prs.length === 0 && <div className="text-gray-400 italic">No pull requests found.</div>}
{prs.map((pr, i) => (
<div key={i} className="bg-white rounded-xl shadow flex flex-col md:flex-row items-start md:items-center p-4 border border-gray-100 hover:shadow-lg transition">
<div className="flex-1">
<a href={pr.html_url} target="_blank" rel="noopener noreferrer" className="text-blue-600 font-semibold hover:underline text-lg flex items-center">
<svg className="w-5 h-5 mr-2 text-blue-400" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3" />
</svg>
{pr.title}
</a>
<div className="text-sm text-gray-500 mt-1">{pr.repository_url.split("/").pop()}</div>
</div>
<span className="ml-0 md:ml-4 mt-2 md:mt-0 inline-block bg-green-100 text-green-700 text-xs font-semibold px-3 py-1 rounded-full">PR</span>
</div>
))}
</div>

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Resolve merge conflict markers in JSX.

The JSX contains merge conflict markers that are causing multiple parse errors.

Remove all merge conflict markers throughout the JSX:

-gsoc-2025Gaurav
    <div className="flex flex-col items-center bg-gradient-to-br from-white to-gray-100 shadow-2xl rounded-2xl p-8 max-w-xl mx-auto mt-16">
📝 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
gsoc-2025Gaurav
<div className="flex flex-col items-center bg-gradient-to-br from-white to-gray-100 shadow-2xl rounded-2xl p-8 max-w-xl mx-auto mt-16">
{profile && (
<div className="flex flex-col items-center w-full">
<div className="relative group">
<img
src={profile.avatar_url}
alt="Avatar"
className="w-32 h-32 rounded-full border-4 border-blue-400 shadow-lg transition-transform group-hover:scale-105"
/>
{isOwnProfile && !isEdit && (
<span className="absolute bottom-2 right-2 bg-blue-600 text-white rounded-full p-1 shadow-lg cursor-pointer" title="Edit Profile" onClick={() => window.location.href = `/user/${paramUsername}?edit=1`}>
<svg className="w-5 h-5" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M15.232 5.232l3.536 3.536M9 13l6.586-6.586a2 2 0 112.828 2.828L11.828 15.828a2 2 0 01-2.828 0L9 13zm0 0V17h4" />
</svg>
</span>
)}
</div>
<h2 className="text-3xl font-bold mt-4">{profile.login}</h2>
{isEdit && isOwnProfile ? (
<div className="mt-4 w-full">
<div className="flex items-center mb-2">
<span className="font-semibold text-gray-700 mr-2">Bio</span>
<span className="text-xs text-gray-400">({editBio.length}/{maxBioLength})</span>
</div>
<textarea
className="w-full border-2 border-blue-200 rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-blue-400 text-gray-800 text-base resize-none shadow"
rows={3}
maxLength={maxBioLength}
value={editBio}
onChange={e => setEditBio(e.target.value)}
placeholder="Edit your bio"
/>
<div className="flex gap-3 mt-3">
<button
className="px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-full shadow transition"
onClick={handleSave}
disabled={saving}
>
{saving ? "Saving..." : "Save Bio"}
</button>
<button
className="px-6 py-2 bg-gray-300 hover:bg-gray-400 text-gray-800 rounded-full shadow transition"
onClick={handleCancel}
disabled={saving}
>
Cancel
</button>
</div>
</div>
) : (
<p className="text-lg text-gray-700 mt-4 text-center max-w-md">{profile.bio || <span className="italic text-gray-400">No bio provided.</span>}</p>
)}
</div>
)}
<h3 className="text-2xl font-semibold mt-10 mb-4 w-full text-left">Pull Requests</h3>
<div className="grid grid-cols-1 gap-4 w-full">
{prs.length === 0 && <div className="text-gray-400 italic">No pull requests found.</div>}
{prs.map((pr, i) => (
<div key={i} className="bg-white rounded-xl shadow flex flex-col md:flex-row items-start md:items-center p-4 border border-gray-100 hover:shadow-lg transition">
<div className="flex-1">
<a href={pr.html_url} target="_blank" rel="noopener noreferrer" className="text-blue-600 font-semibold hover:underline text-lg flex items-center">
<svg className="w-5 h-5 mr-2 text-blue-400" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3" />
</svg>
{pr.title}
</a>
<div className="text-sm text-gray-500 mt-1">{pr.repository_url.split("/").pop()}</div>
</div>
<span className="ml-0 md:ml-4 mt-2 md:mt-0 inline-block bg-green-100 text-green-700 text-xs font-semibold px-3 py-1 rounded-full">PR</span>
</div>
))}
</div>
<div className="flex flex-col items-center bg-gradient-to-br from-white to-gray-100 shadow-2xl rounded-2xl p-8 max-w-xl mx-auto mt-16">
{profile && (
<div className="flex flex-col items-center w-full">
<div className="relative group">
<img
src={profile.avatar_url}
alt="Avatar"
className="w-32 h-32 rounded-full border-4 border-blue-400 shadow-lg transition-transform group-hover:scale-105"
/>
{isOwnProfile && !isEdit && (
<span className="absolute bottom-2 right-2 bg-blue-600 text-white rounded-full p-1 shadow-lg cursor-pointer" title="Edit Profile" onClick={() => window.location.href = `/user/${paramUsername}?edit=1`}>
<svg className="w-5 h-5" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M15.232 5.232l3.536 3.536M9 13l6.586-6.586a2 2 0 112.828 2.828L11.828 15.828a2 2 0 01-2.828 0L9 13zm0 0V17h4" />
</svg>
</span>
)}
</div>
<h2 className="text-3xl font-bold mt-4">{profile.login}</h2>
{isEdit && isOwnProfile ? (
<div className="mt-4 w-full">
<div className="flex items-center mb-2">
<span className="font-semibold text-gray-700 mr-2">Bio</span>
<span className="text-xs text-gray-400">({editBio.length}/{maxBioLength})</span>
</div>
<textarea
className="w-full border-2 border-blue-200 rounded-lg p-3 focus:outline-none focus:ring-2 focus:ring-blue-400 text-gray-800 text-base resize-none shadow"
rows={3}
maxLength={maxBioLength}
value={editBio}
onChange={e => setEditBio(e.target.value)}
placeholder="Edit your bio"
/>
<div className="flex gap-3 mt-3">
<button
className="px-6 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-full shadow transition"
onClick={handleSave}
disabled={saving}
>
{saving ? "Saving..." : "Save Bio"}
</button>
<button
className="px-6 py-2 bg-gray-300 hover:bg-gray-400 text-gray-800 rounded-full shadow transition"
onClick={handleCancel}
disabled={saving}
>
Cancel
</button>
</div>
</div>
) : (
<p className="text-lg text-gray-700 mt-4 text-center max-w-md">{profile.bio || <span className="italic text-gray-400">No bio provided.</span>}</p>
)}
</div>
)}
<h3 className="text-2xl font-semibold mt-10 mb-4 w-full text-left">Pull Requests</h3>
<div className="grid grid-cols-1 gap-4 w-full">
{prs.length === 0 && <div className="text-gray-400 italic">No pull requests found.</div>}
{prs.map((pr, i) => (
<div key={i} className="bg-white rounded-xl shadow flex flex-col md:flex-row items-start md:items-center p-4 border border-gray-100 hover:shadow-lg transition">
<div className="flex-1">
<a href={pr.html_url} target="_blank" rel="noopener noreferrer" className="text-blue-600 font-semibold hover:underline text-lg flex items-center">
<svg className="w-5 h-5 mr-2 text-blue-400" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3" />
</svg>
{pr.title}
</a>
<div className="text-sm text-gray-500 mt-1">{pr.repository_url.split("/").pop()}</div>
</div>
<span className="ml-0 md:ml-4 mt-2 md:mt-0 inline-block bg-green-100 text-green-700 text-xs font-semibold px-3 py-1 rounded-full">PR</span>
</div>
))}
</div>
🧰 Tools
🪛 Biome (2.1.2)

[error] 104-105: numbers cannot be followed by identifiers directly after

an identifier cannot appear here

(parse)


[error] 105-105: expected ) but instead found className

Remove className

(parse)


[error] 106-106: expected , but instead found &&

Remove &&

(parse)


[error] 107-107: expected , but instead found <

Remove <

(parse)


[error] 107-107: expected , but instead found className

Remove className

(parse)


[error] 108-108: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 108-108: expected , but instead found className

Remove className

(parse)


[error] 109-109: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 110-110: expected , but instead found src

Remove src

(parse)


[error] 110-110: ';' expected'

An explicit or implicit semicolon is expected here...

(parse)


[error] 111-111: expected , but instead found alt

Remove alt

(parse)


[error] 112-112: expected , but instead found className

Remove className

(parse)


[error] 113-113: expected , but instead found /

Remove /

(parse)


[error] 113-114: Expected an expression but instead found '>'.

Expected an expression here.

(parse)


[error] 114-114: expected , but instead found &&

Remove &&

(parse)


[error] 115-115: expected , but instead found <

Remove <

(parse)


[error] 115-115: expected , but instead found className

Remove className

(parse)


[error] 115-115: expected , but instead found title

Remove title

(parse)


[error] 115-115: expected , but instead found onClick

Remove onClick

(parse)


[error] 115-115: ';' expected'

An explicit or implicit semicolon is expected here...

(parse)


[error] 115-115: expected , but instead found ?

Remove ?

(parse)


[error] 115-115: expected , but instead found edit

Remove edit

(parse)


[error] 115-115: expected , but instead found ```

Remove `

(parse)


[error] 116-116: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 116-116: expected , but instead found className

Remove className

(parse)


[error] 116-116: expected , but instead found fill

Remove fill

(parse)


[error] 116-116: expected , but instead found stroke

Remove stroke

(parse)


[error] 116-116: expected , but instead found strokeWidth

Remove strokeWidth

(parse)


[error] 116-116: expected , but instead found viewBox

Remove viewBox

(parse)


[error] 117-117: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 117-117: expected , but instead found strokeLinecap

Remove strokeLinecap

(parse)


[error] 117-117: expected , but instead found strokeLinejoin

Remove strokeLinejoin

(parse)


[error] 117-117: expected , but instead found d

Remove d

(parse)


[error] 117-117: expected , but instead found /

Remove /

(parse)


[error] 118-118: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 118-118: Expected a type parameter but instead found '/'.

Expected a type parameter here.

(parse)


[error] 118-118: expected , but instead found svg

Remove svg

(parse)


[error] 119-119: Expected a parenthesis '(' but instead found '<'.

Expected a parenthesis '(' here.

(parse)


[error] 119-119: Expected a type parameter but instead found '/'.

Expected a type parameter here.

(parse)


[error] 119-119: expected , but instead found span

Remove span

(parse)


[error] 120-120: Expected a parenthesis '(' but instead found ')'.

Expected a parenthesis '(' here.

(parse)


[error] 121-121: Expected an expression but instead found '<'.

Expected an expression here.

(parse)


[error] 122-123: Expected an expression but instead found ''.

Expected an expression here.

(parse)


[error] 157-157: Expected an expression but instead found '<'.

Expected an expression here.

(parse)


[error] 176-176: Expected an expression but instead found '<'.

Expected an expression here.

(parse)

🤖 Prompt for AI Agents
In src/pages/UserProfile/UserProfile.tsx between lines 104 and 177, there are
unresolved merge conflict markers within the JSX code causing parse errors.
Locate and remove all conflict markers such as <<<<<<<, =======, and >>>>>>> to
clean up the JSX. Ensure the final JSX structure is syntactically correct and
consistent with the intended UI design.

className="w-32 h-32 rounded-full border-4 border-blue-400 shadow-lg transition-transform group-hover:scale-105"
/>
{isOwnProfile && !isEdit && (
<span className="absolute bottom-2 right-2 bg-blue-600 text-white rounded-full p-1 shadow-lg cursor-pointer" title="Edit Profile" onClick={() => window.location.href = `/user/${paramUsername}?edit=1`}>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve edit profile navigation.

Using window.location.href for navigation is inconsistent with React Router patterns.

Use React Router navigation:

+import { useNavigate } from 'react-router-dom';

+const navigate = useNavigate();

-            {isOwnProfile && !isEdit && (
-              <span className="absolute bottom-2 right-2 bg-blue-600 text-white rounded-full p-1 shadow-lg cursor-pointer" title="Edit Profile" onClick={() => window.location.href = `/user/${paramUsername}?edit=1`}>
+            {isOwnProfile && !isEdit && (
+              <span className="absolute bottom-2 right-2 bg-blue-600 text-white rounded-full p-1 shadow-lg cursor-pointer" title="Edit Profile" onClick={() => navigate(`/user/${paramUsername}?edit=1`)}>
📝 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
<span className="absolute bottom-2 right-2 bg-blue-600 text-white rounded-full p-1 shadow-lg cursor-pointer" title="Edit Profile" onClick={() => window.location.href = `/user/${paramUsername}?edit=1`}>
// src/pages/UserProfile/UserProfile.tsx
import React from 'react';
import { useParams } from 'react-router-dom';
+import { useNavigate } from 'react-router-dom';
const UserProfile: React.FC = () => {
const { paramUsername } = useParams<{ paramUsername: string }>();
+ const navigate = useNavigate();
// … other hooks/state
return (
<div>
{/* … other JSX */}
- {isOwnProfile && !isEdit && (
- <span
- className="absolute bottom-2 right-2 bg-blue-600 text-white rounded-full p-1 shadow-lg cursor-pointer"
- title="Edit Profile"
- onClick={() => window.location.href = `/user/${paramUsername}?edit=1`}
- >
+ {isOwnProfile && !isEdit && (
+ <span
+ className="absolute bottom-2 right-2 bg-blue-600 text-white rounded-full p-1 shadow-lg cursor-pointer"
+ title="Edit Profile"
+ onClick={() => navigate(`/user/${paramUsername}?edit=1`)}
+ >
{/* Edit Icon */}
</span>
)}
{/* … rest of JSX */}
</div>
);
};
export default UserProfile;
🧰 Tools
🪛 Biome (2.1.2)

[error] 115-115: expected , but instead found <

Remove <

(parse)


[error] 115-115: expected , but instead found className

Remove className

(parse)


[error] 115-115: expected , but instead found title

Remove title

(parse)


[error] 115-115: expected , but instead found onClick

Remove onClick

(parse)


[error] 115-115: ';' expected'

An explicit or implicit semicolon is expected here...

(parse)


[error] 115-115: expected , but instead found ?

Remove ?

(parse)


[error] 115-115: expected , but instead found edit

Remove edit

(parse)


[error] 115-115: expected , but instead found ```

Remove `

(parse)

🤖 Prompt for AI Agents
In src/pages/UserProfile/UserProfile.tsx at line 115, replace the use of
window.location.href for navigation with React Router's navigation method.
Import the useNavigate hook from react-router-dom, create a navigate function,
and use it in the onClick handler to programmatically navigate to the edit
profile URL, ensuring consistent routing behavior within the React app.

@mehul-m-prajapati
Copy link
Collaborator

@gaurav123-4 : please fix conflicts

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants