Skip to content

Commit

Permalink
Add Top Contributions
Browse files Browse the repository at this point in the history
  • Loading branch information
devXprite committed Mar 31, 2024
1 parent 7c19b42 commit b9eb3c5
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 56 deletions.
4 changes: 2 additions & 2 deletions app/[username]/Languages.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ const Languages = ({ languages }) => {
<div key={name} className="box group flex items-center justify-around gap-4 p-3">
<LanguageIcon
name={name}
className="size-8 md:size-10 transition-all duration-300 group-hover:grayscale-0 group-hover:rotate-y-180"
className="size-8 transition-all duration-300 group-hover:grayscale-0 group-hover:rotate-y-180 md:size-10"
/>
<div>
<p className="font-[Electrolize] text-lg md:text-xl font-bold">
<p className="font-[Electrolize] text-lg font-bold md:text-xl">
<CountUp start={0} end={size} decimals={2} />
<span className="ml-1 text-lg">%</span>
</p>
Expand Down
42 changes: 4 additions & 38 deletions app/[username]/PopularProjects.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,11 @@
import GridContainer from '@/components/GridContainer';
import { VscRepo } from 'react-icons/vsc';
import { GoRepoForked } from 'react-icons/go';
import { GoIssueOpened } from "react-icons/go";
import { FaRegStar } from 'react-icons/fa';
import { FaCodePullRequest } from "react-icons/fa6";
import RepoCard from '@/components/RepoCard';

const PopularProjects = ({ projects }) => {
return (
<GridContainer name="Popular Projects" className={'gap-4 md:gap-6 grid-cols-1 md:grid-cols-3'}>
{projects.map(project => (
<div key={project.name} className="box flex flex-col px-4 py-3 text-left">
<h3 className="flex items-center gap-2 text-lg font-bold">
<VscRepo /> {project.name}
</h3>
<p className="mb-3 mt-2 line-clamp-3 text-sm font-medium text-gray-400">{project.description}</p>

<div className="mt-auto flex items-center justify-between md:justify-start gap-4 text-sm font-medium">
{/* Language */}
<p className="flex items-center gap-2 text-gray-300">
<span
className="size-3 rounded-full"
style={{
backgroundColor: project.primaryLanguage?.color || '#ccc',
}}
></span>
<span>{project.primaryLanguage?.name || 'Unknown'}</span>
</p>
<p className="flex items-center gap-1">
<FaRegStar /> {project.stargazerCount}
</p>
<p className="flex items-center gap-1">
<GoRepoForked /> {project.forkCount}
</p>
<p className="hidden md:flex items-center gap-1">
<GoIssueOpened /> {project.issues.totalCount}
</p>
<p className="flex items-center gap-1">
<FaCodePullRequest /> {project.pullRequests.totalCount}
</p>
</div>
</div>
<GridContainer name="Popular Projects" className={'grid-cols-1 gap-4 md:grid-cols-3 md:gap-6'}>
{projects.map(repo => (
<RepoCard key={repo.id} {...repo} />
))}
</GridContainer>
);
Expand Down
65 changes: 65 additions & 0 deletions app/[username]/TopContributions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 'use client';

import GridContainer from '@/components/GridContainer';
import { IoGitPullRequestSharp, IoGitMergeSharp } from 'react-icons/io5';
import { RiGitClosePullRequestLine } from 'react-icons/ri';

const PrIcon = ({ status }) => {
if (status === 'MERGED') {
return (
<div className="rounded bg-purple-500 p-[3px] text-white">
<IoGitMergeSharp />
</div>
);
}

if (status === 'CLOSED') {
return (
<div className="rounded bg-red-500 p-[3px] text-white">
<RiGitClosePullRequestLine />
</div>
);
}

return (
<div className="rounded bg-green-600 p-[3px] text-white">
<IoGitPullRequestSharp />
</div>
);
};

const TopContributions = ({ contributions }) => {
return (
<GridContainer name="Top Contributions" className={'grid-cols-1 md:grid-cols-3'}>
{contributions.map(({ repository, contributions }, i) => (
<div key={i} className="box flex flex-col gap-5 px-4 py-3 text-left">
<h3 className="flex items-center gap-2 text-lg font-bold">
<img className="mr-1 size-11 rounded-md" src={repository.owner.avatarUrl} />

<div>
<p>{repository.name}</p>
<p className="-mt-1 text-sm text-gray-400">@{repository.owner.login}</p>
</div>

<p className="ml-auto rounded-md border border-gray-600 bg-gray-700 p-1.5">
{contributions.totalCount < 10 ? `0${contributions.totalCount}` : contributions.totalCount}
</p>
</h3>

<ul className="space-y-1">
{contributions.nodes.splice(0, 3).map(({ pullRequest }, i) => (
<div key={i} className="flex items-center justify-between gap-2 ">
<p className="line-clamp-1 font-medium">{pullRequest.title}</p>
<PrIcon status={pullRequest.state} />
</div>
))}
</ul>
</div>
))}


</GridContainer>
);
};

export default TopContributions;
28 changes: 21 additions & 7 deletions app/[username]/UserInfo.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { FaCalendar } from 'react-icons/fa';

const UserInfo = props => {
return (
<>
<div className="mx-auto flex max-w-screen-md flex-col items-center justify-around gap-4 pb-6 md:flex-row md:gap-20">
<div className="relative size-36 rounded-full border-[4px] border-gray-600 md:size-44">
<div className="mx-auto flex max-w-screen-lg flex-col items-center justify-evenly gap-4 pb-6 md:flex-row md:gap-14">
<div className="relative size-36 flex-none rounded-full border-[4px] border-gray-600 md:size-48">
<img className="rounded-full" src={props.avatarUrl} alt={props.name} />

{/* {props.status && (
Expand All @@ -16,12 +18,24 @@ const UserInfo = props => {
</div>

<div className="flex h-full flex-col text-center md:text-left">
<h2 className="text-gradient text-4xl font-bold md:text-6xl">{props.name}</h2>
<h4 className="-mt-1.5 mb-2 text-xl text-gray-400 md:mb-4 md:mt-0 md:text-3xl">
@{props.username}
</h4>
<h2 className="text-gradient text-4xl font-bold md:text-6xl">{props.name || props.username}</h2>
<h4 className="-mt-1 text-gray-400 md:mb-1 md:text-3xl">@{props.username}</h4>

<p className="mb-3 flex items-center justify-center md:justify-start gap-2">
<FaCalendar />
<span>
Joined on{' '}
<span className="font-medium">
{new Date(props.createdAt).toLocaleDateString('en-IN', {
day: '2-digit',
month: 'long',
year: 'numeric',
})}
</span>
</span>
</p>

<p className="mt-auto text-gray-300">{props.bio}</p>
<p className="mt-auto md:line-clamp-2 text-gray-300 md:max-w-lg">{props.bio}</p>
</div>
</div>
</>
Expand Down
5 changes: 4 additions & 1 deletion app/[username]/page.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import Stats from './Stats';
import Calendar from './Calendar';
import Languages from './Languages';
import PopularProjects from './PopularProjects';

import UserInfo from './UserInfo';
import fetchUserInfo from '@/utils/fetchUserInfo';
import fetchUserData from '@/utils/fetchUserData';
import Charts from './Charts';
import ActivityGraph from './ActivityGraph';
import TopContributions from './TopContributions';
import Languages from './Languages';

const page = async ({ params: { username } }) => {
console.log('Username:', username);
Expand All @@ -22,6 +23,7 @@ const page = async ({ params: { username } }) => {
starsPerLanguages,
popularRepositories,
userStats,
topContributions,
} = await fetchUserData(username);

return (
Expand All @@ -30,6 +32,7 @@ const page = async ({ params: { username } }) => {
<Stats stats={userStats} />
<Languages languages={languagesSize} />
<PopularProjects projects={popularRepositories} />
<TopContributions contributions={topContributions} />

<Charts
commitsPerRepo={commitsPerRepo}
Expand Down
2 changes: 1 addition & 1 deletion app/globals.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
@apply cursor-pointer rounded border border-gray-600 select-none bg-gray-700/25 px-3 py-2 text-center shadow-md shadow-gray-900 transition-all duration-300;

&:hover {
@apply md:scale-105 border-2 border-gray-300 bg-gray-700 shadow-lg shadow-gray-950;
@apply md:scale-105 border-gray-400 bg-gray-700 shadow-lg shadow-gray-950;
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion components/GridContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ const GridContainer = ({ name, className, children }) => {
return (
<section className="rounded-md border border-gray-700 bg-gray-900 shadow-lg shadow-black">
<h3 className="bg-gray-800 px-5 py-3 text-xl font-semibold text-gray-200">{name}</h3>
<div className={twMerge('grid grid-cols-2 gap-4 p-3 md:p-5 md:grid-cols-5 bg-gray-800/50', className)}>{children}</div>
<div className={twMerge('grid grid-cols-2 gap-4 bg-gray-800/50 p-3 md:grid-cols-5 md:p-5', className)}>
{children}
{children.length === 0 && (
<div className="col-span-full flex w-full items-center justify-center py-8 md:text-lg">
<p className="text-gray-500">Not enough data.</p>
</div>
)}
</div>
</section>
);
};
Expand Down
44 changes: 44 additions & 0 deletions components/RepoCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { VscRepo } from 'react-icons/vsc';
import { GoRepoForked } from 'react-icons/go';
import { GoIssueOpened } from 'react-icons/go';
import { FaRegStar } from 'react-icons/fa';
import { FaCodePullRequest } from 'react-icons/fa6';

const RepoCard = props => {
return (
<div className="box flex flex-col px-4 py-3 text-left">
<h3 className="flex items-center gap-2 text-lg font-bold">
<VscRepo /> {props.name}
</h3>
<p className="mb-3 mt-2 line-clamp-3 text-sm font-medium text-gray-400">
{props.description || 'No description'}
</p>

<div className="mt-auto flex items-center justify-between gap-4 text-sm font-medium md:justify-start">
<p className="flex items-center gap-2 text-gray-300">
<span
className="size-3 rounded-full"
style={{
backgroundColor: props.primaryLanguage?.color || '#ccc',
}}
></span>
<span>{props.primaryLanguage?.name || 'Unknown'}</span>
</p>
<p className="flex items-center gap-1">
<FaRegStar /> {props.stargazerCount}
</p>
<p className="flex items-center gap-1">
<GoRepoForked /> {props.forkCount}
</p>
<p className="hidden items-center gap-1 md:flex">
<GoIssueOpened /> {props.issues.totalCount}
</p>
<p className="flex items-center gap-1">
<FaCodePullRequest /> {props.pullRequests.totalCount}
</p>
</div>
</div>
);
};

export default RepoCard;
43 changes: 38 additions & 5 deletions utils/fetchUserData.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,39 @@ popularRepositories: repositories(
`;

const contributionsCollectionQuery = `
contributionsCollection{
contributionCalendar{
weeks{
contributionDays{
contributionsCollection {
pullRequestContributionsByRepository {
contributions(last: 10) {
totalCount
nodes {
pullRequest {
id
title
state
}
}
}
repository {
name
description
stargazerCount
forkCount
diskUsage
url
createdAt
primaryLanguage {
name
color
}
owner{
avatarUrl(size: 50)
login
}
}
}
contributionCalendar {
weeks {
contributionDays {
contributionCount
contributionLevel
date
Expand Down Expand Up @@ -160,7 +189,10 @@ const fetchUserData = async login => {
const popularRepositories = user.popularRepositories.nodes;
const userStats = getUserStats(user);

console.log(rateLimit);
const topContributions = user.contributionsCollection.pullRequestContributionsByRepository
.filter(contribution => contribution.repository.owner.login !== login)
.splice(0, 9);


return {
languagesSize,
Expand All @@ -170,6 +202,7 @@ const fetchUserData = async login => {
starsPerLanguages,
popularRepositories,
contributionCalendar,
topContributions,
userStats,
};
};
Expand Down
2 changes: 1 addition & 1 deletion utils/parse/getUserStats.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const getUserStats = userData => {
const stats = {
Followers: userData.followers.totalCount,
Repositories: userData.repositories.totalCount,
Repositories: userData.repositoriesWithStargazerCount.totalCount,
Organizations: userData.organizations.totalCount,
Gists: userData.gists.totalCount,
'Pull Requests': userData.pullRequests.totalCount,
Expand Down

0 comments on commit b9eb3c5

Please sign in to comment.