Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 119 additions & 1 deletion src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
gsoc-2025Gaurav
import { Link, useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { useGitHubAuth } from '../hooks/useGitHubAuth';

const Navbar: React.FC = () => {
const [isOpen, setIsOpen] = useState<boolean>(false);
const [dropdownOpen, setDropdownOpen] = useState(false);
const { username, logout } = useGitHubAuth();
const navigate = useNavigate();

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

import { Link } from "react-router-dom";
import { useState, useContext } from "react";
import { ThemeContext } from "../context/ThemeContext";
Expand All @@ -8,6 +24,7 @@ const Navbar: React.FC = () => {
if (!themeContext) return null;

const { toggleTheme, mode } = themeContext;
main

return (
<nav className="bg-white text-black dark:bg-gray-800 dark:text-white shadow-lg">
Expand All @@ -22,7 +39,7 @@ const Navbar: React.FC = () => {
</Link>

{/* Desktop Links */}
<div className="hidden md:flex space-x-6">
<div className="hidden md:flex space-x-6 items-center">
<Link
to="/"
className="text-lg font-medium hover:text-gray-300 transition-all px-2 py-1 border border-transparent hover:border-gray-400 rounded"
Expand All @@ -47,6 +64,55 @@ const Navbar: React.FC = () => {
>
Contributors
</Link>
gsoc-2025Gaurav
{!username ? (
<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>
) : (
<div className="relative">
<button
className="flex items-center space-x-2 focus:outline-none"
onClick={() => setDropdownOpen((v) => !v)}
>
<img
src={`https://github.com/${username}.png`}
alt="avatar"
className="w-8 h-8 rounded-full border-2 border-white"
/>
<span className="font-medium">{username}</span>
<svg className="w-4 h-4 ml-1" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M19 9l-7 7-7-7" />
</svg>
</button>
{dropdownOpen && (
<div className="absolute right-0 mt-2 w-48 bg-white text-gray-800 rounded-lg shadow-lg z-50">
<Link
to={`/user/${username}`}
className="block px-4 py-2 hover:bg-gray-100"
onClick={() => setDropdownOpen(false)}
>
View Profile
</Link>
<Link
to={`/user/${username}?edit=1`}
className="block px-4 py-2 hover:bg-gray-100"
onClick={() => setDropdownOpen(false)}
>
Edit Profile
</Link>
<button
className="block w-full text-left px-4 py-2 hover:bg-gray-100"
onClick={handleLogout}
>
Logout
</button>
</div>
)}
</div>
)}

<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"
Expand All @@ -59,6 +125,7 @@ const Navbar: React.FC = () => {
>
{mode === "dark" ? "🌞 Light" : "🌙 Dark"}
</button>
main
</div>

{/* Mobile Menu Button */}
Expand Down Expand Up @@ -118,6 +185,56 @@ const Navbar: React.FC = () => {
>
Contributors
</Link>
gsoc-2025Gaurav
{!username ? (
<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>
) : (
<div className="relative">
<button
className="flex items-center space-x-2 focus:outline-none w-full px-2 py-1"
onClick={() => setDropdownOpen((v) => !v)}
>
<img
src={`https://github.com/${username}.png`}
alt="avatar"
className="w-8 h-8 rounded-full border-2 border-white"
/>
<span className="font-medium">{username}</span>
<svg className="w-4 h-4 ml-1" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" d="M19 9l-7 7-7-7" />
</svg>
</button>
{dropdownOpen && (
<div className="absolute right-0 mt-2 w-48 bg-white text-gray-800 rounded-lg shadow-lg z-50">
<Link
to={`/user/${username}`}
className="block px-4 py-2 hover:bg-gray-100"
onClick={() => { setDropdownOpen(false); setIsOpen(false); }}
>
View Profile
</Link>
<Link
to={`/user/${username}?edit=1`}
className="block px-4 py-2 hover:bg-gray-100"
onClick={() => { setDropdownOpen(false); setIsOpen(false); }}
>
Edit Profile
</Link>
<button
className="block w-full text-left px-4 py-2 hover:bg-gray-100"
onClick={() => { handleLogout(); setIsOpen(false); }}
>
Logout
</button>
</div>
)}
</div>
)}

<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"
Expand All @@ -134,6 +251,7 @@ const Navbar: React.FC = () => {
>
{mode === "dark" ? "🌞 Light" : "🌙 Dark"}
</button>
main
</div>
</div>
)}
Expand Down
20 changes: 18 additions & 2 deletions src/hooks/useGitHubAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,25 @@ import { useState } from 'react';
import { Octokit } from '@octokit/core';

export const useGitHubAuth = () => {
const [username, setUsername] = useState('');
const [token, setToken] = useState('');
const [username, setUsernameState] = useState(() => localStorage.getItem('username') || '');
const [token, setTokenState] = useState(() => localStorage.getItem('token') || '');
const [error, setError] = useState('');

const setUsername = (name: string) => {
setUsernameState(name);
localStorage.setItem('username', name);
};
const setToken = (tok: string) => {
setTokenState(tok);
localStorage.setItem('token', tok);
};
const logout = () => {
setUsernameState('');
setTokenState('');
localStorage.removeItem('username');
localStorage.removeItem('token');
};

const getOctokit = () => {
if (!username || !token) return null;
return new Octokit({ auth: token });
Expand All @@ -19,5 +34,6 @@ export const useGitHubAuth = () => {
error,
setError,
getOctokit,
logout,
};
};
142 changes: 138 additions & 4 deletions src/pages/UserProfile/UserProfile.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { useParams } from "react-router-dom";
import { useParams, useLocation } from "react-router-dom";
import { useEffect, useState } from "react";
gsoc-2025Gaurav
import { useGitHubAuth } from "../../hooks/useGitHubAuth";

import toast from "react-hot-toast";
main

type PR = {
title: string;
Expand All @@ -9,13 +13,32 @@ type PR = {
};

export default function UserProfile() {
const { username } = useParams();
const { username: paramUsername } = useParams();
const location = useLocation();
const { username: loggedInUsername, token } = useGitHubAuth();
const [profile, setProfile] = useState<any>(null);
const [prs, setPRs] = useState<PR[]>([]);
const [loading, setLoading] = useState(true);
const [editBio, setEditBio] = useState("");
const [saving, setSaving] = useState(false);
const [editMode, setEditMode] = useState(false);
const isEdit = new URLSearchParams(location.search).get("edit") === "1";
const isOwnProfile = paramUsername === loggedInUsername;
const maxBioLength = 160;

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;

try {
Expand All @@ -31,22 +54,132 @@ export default function UserProfile() {
} finally {
setLoading(false);
}
main
}

fetchData();
}, [username]);
}, [paramUsername]);

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}`;
};

gsoc-2025Gaurav
const handleCancel = () => {
setEditBio(profile.bio || "");
setEditMode(false);
};

if (loading) return (
<div className="flex justify-center items-center min-h-[60vh]">
<svg className="animate-spin h-10 w-10 text-blue-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</div>
);

const handleCopyLink = () => {
navigator.clipboard.writeText(window.location.href);
toast.success("🔗 Shareable link copied to clipboard!");
};

if (loading) return <div className="text-center mt-10">Loading...</div>;
main

if (!profile) return <div className="text-center mt-10 text-red-600">User not found.</div>;

return (
gsoc-2025Gaurav
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`}>
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.

<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>

Comment on lines +105 to +178
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.

<div className="max-w-3xl mx-auto mt-10 p-4 bg-white shadow-xl rounded-xl">

<div className="max-w-3xl mx-auto mt-2 mb-2 p-4 bg-white dark:bg-gray-800 dark:text-white shadow-xl rounded-xl">
main
<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>
Expand Down Expand Up @@ -81,6 +214,7 @@ export default function UserProfile() {
) : (
<p className="text-gray-600">No pull requests found for this user.</p>
)}
main
</div>
);
}