feat: add github contributors leaderboard

feat/github
Arik Chakma 7 months ago
parent 264afe4e03
commit 4154eeb8ed
  1. 3
      src/api/leaderboard.ts
  2. 25
      src/components/Leaderboard/LeaderboardPage.tsx

@ -17,6 +17,9 @@ export type ListLeaderboardStatsResponse = {
currentMonth: LeadeboardUserDetails[]; currentMonth: LeadeboardUserDetails[];
lifetime: LeadeboardUserDetails[]; lifetime: LeadeboardUserDetails[];
}; };
githubContributors: {
currentMonth: LeadeboardUserDetails[];
};
}; };
export function leaderboardApi(context: APIContext) { export function leaderboardApi(context: APIContext) {

@ -4,7 +4,7 @@ import type {
ListLeaderboardStatsResponse, ListLeaderboardStatsResponse,
} from '../../api/leaderboard'; } from '../../api/leaderboard';
import { cn } from '../../lib/classname'; import { cn } from '../../lib/classname';
import { FolderKanban, Zap, Trophy } from 'lucide-react'; import { FolderKanban, Zap, Trophy, GitPullRequest } from 'lucide-react';
import { RankBadgeIcon } from '../ReactIcons/RankBadgeIcon'; import { RankBadgeIcon } from '../ReactIcons/RankBadgeIcon';
import { TrophyEmoji } from '../ReactIcons/TrophyEmoji'; import { TrophyEmoji } from '../ReactIcons/TrophyEmoji';
import { SecondPlaceMedalEmoji } from '../ReactIcons/SecondPlaceMedalEmoji'; import { SecondPlaceMedalEmoji } from '../ReactIcons/SecondPlaceMedalEmoji';
@ -64,6 +64,19 @@ export function LeaderboardPage(props: LeaderboardPageProps) {
}, },
]} ]}
/> />
<LeaderboardLane
title="Top Contributors"
tabs={[
{
title: 'This Month',
users: stats.githubContributors.currentMonth,
emptyIcon: (
<GitPullRequest className="size-16 text-gray-300" />
),
emptyText: 'No contributors this month',
},
]}
/>
</div> </div>
</div> </div>
</div> </div>
@ -89,7 +102,7 @@ function LeaderboardLane(props: LeaderboardLaneProps) {
return ( return (
<div className="overflow-hidden rounded-md border bg-white shadow-sm"> <div className="overflow-hidden rounded-md border bg-white shadow-sm">
<div className="flex items-center justify-between gap-2 bg-gray-100 px-3 py-3 mb-3"> <div className="mb-3 flex items-center justify-between gap-2 bg-gray-100 px-3 py-3">
<h3 className="text-base font-medium">{title}</h3> <h3 className="text-base font-medium">{title}</h3>
{tabs.length > 1 && ( {tabs.length > 1 && (
@ -128,19 +141,21 @@ function LeaderboardLane(props: LeaderboardLaneProps) {
<ul className="divide-y divide-gray-100 pb-4"> <ul className="divide-y divide-gray-100 pb-4">
{usersToShow.map((user, counter) => { {usersToShow.map((user, counter) => {
const avatar = user?.avatar const avatar = user?.avatar
? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${user.avatar}` ? user?.avatar?.startsWith('http')
? user?.avatar
: `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${user.avatar}`
: '/images/default-avatar.png'; : '/images/default-avatar.png';
const rank = counter + 1; const rank = counter + 1;
return ( return (
<li <li
key={user.id} key={user.id}
className="flex items-center justify-between gap-1 pl-2 pr-5 py-2.5 hover:bg-gray-50" className="flex items-center justify-between gap-1 py-2.5 pl-2 pr-5 hover:bg-gray-50"
> >
<div className="flex min-w-0 items-center gap-2"> <div className="flex min-w-0 items-center gap-2">
<span <span
className={cn( className={cn(
'relative text-xs mr-1 flex size-6 shrink-0 items-center justify-center rounded-full tabular-nums', 'relative mr-1 flex size-6 shrink-0 items-center justify-center rounded-full text-xs tabular-nums',
{ {
'text-black': rank <= 3, 'text-black': rank <= 3,
'text-gray-400': rank > 3, 'text-gray-400': rank > 3,

Loading…
Cancel
Save