From 77c073cd12dcc3ad2b4cf86ad2ec645779229de2 Mon Sep 17 00:00:00 2001 From: Xenon010101 Date: Thu, 18 Jun 2026 20:14:10 +0530 Subject: [PATCH] feat: add Pinned Repositories section to developer profiles (#559) --- src/components/profile/PinnedRepos.jsx | 147 +++++++++++++++++++++++++ src/pages/Profile.jsx | 8 +- 2 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 src/components/profile/PinnedRepos.jsx diff --git a/src/components/profile/PinnedRepos.jsx b/src/components/profile/PinnedRepos.jsx new file mode 100644 index 0000000..507e444 --- /dev/null +++ b/src/components/profile/PinnedRepos.jsx @@ -0,0 +1,147 @@ +import React, { useState, useEffect } from "react"; +import { Star, GitFork } from "lucide-react"; +import Loader from "../ui/Loader"; + +const GITHUB_GRAPHQL_API = "https://api.github.com/graphql"; + +const PINNED_REPOS_QUERY = ` + query($username: String!) { + user(login: $username) { + pinnedItems(first: 6, types: REPOSITORY) { + nodes { + ... on Repository { + name + description + stargazerCount + forkCount + primaryLanguage { + name + color + } + url + } + } + } + } + } +`; + +export const PinnedRepos = ({ githubUsername, accessToken }) => { + const [pinnedRepos, setPinnedRepos] = useState([]); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + useEffect(() => { + if (!githubUsername) return; + + const fetchPinnedRepos = async () => { + setLoading(true); + setError(null); + + try { + const response = await fetch(GITHUB_GRAPHQL_API, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${accessToken}`, + }, + body: JSON.stringify({ + query: PINNED_REPOS_QUERY, + variables: { username: githubUsername }, + }), + }); + + if (!response.ok) { + throw new Error(`GitHub API error: ${response.status}`); + } + + const result = await response.json(); + + if (result.errors) { + throw new Error(result.errors[0]?.message || "GraphQL error"); + } + + const repos = result.data?.user?.pinnedItems?.nodes || []; + setPinnedRepos(repos); + } catch (err) { + console.error("Error fetching pinned repos:", err); + setError(err.message); + } finally { + setLoading(false); + } + }; + + fetchPinnedRepos(); + }, [githubUsername, accessToken]); + + if (!githubUsername) return null; + + if (loading) return ( +
+ +
+ ); + + if (error) return null; + + if (!pinnedRepos.length) return null; + + return ( +
+
+

+ Pinned Repositories +

+

+ Top repositories pinned on GitHub +

+
+
+ {pinnedRepos.map((repo) => ( + +
+
+ + + +
+

+ {repo.name} +

+
+ {repo.description && ( +

+ {repo.description} +

+ )} +
+ {repo.primaryLanguage && ( + + + {repo.primaryLanguage.name} + + )} + + {repo.stargazerCount} + + + {repo.forkCount} + +
+
+ ))} +
+
+ ); +}; + +export default PinnedRepos; diff --git a/src/pages/Profile.jsx b/src/pages/Profile.jsx index 4fe0193..646ddd1 100644 --- a/src/pages/Profile.jsx +++ b/src/pages/Profile.jsx @@ -35,13 +35,14 @@ import { systemBadges } from "../constants"; import Card from "../components/ui/Card"; import SectionHeader from "../components/ui/SectionHeader"; import Loader from "../components/ui/Loader"; +import PinnedRepos from "../components/profile/PinnedRepos"; import GradientButton from "../components/ui/GradientButton"; import Toast from "../components/ui/Toast"; import collegesList from "../data/colleges.json"; export const Profile = () => { const navigate = useNavigate(); - const { userData: authUserData, user, setUserData, syncGitHubData } = useAuth(); + const { userData: authUserData, user, setUserData, syncGitHubData, ghAccessToken } = useAuth(); const { username } = useParams(); const [publicProfile, setPublicProfile] = useState(null); const [loadingPublicProfile, setLoadingPublicProfile] = useState(!!username); @@ -1563,6 +1564,11 @@ if (updateData.avatar) { + + {/* Trust Score Scorecard */} {(() => { const trustScore = userData?.points?.trustScore ?? null;