Skip to content
This repository has been archived by the owner on Sep 26, 2024. It is now read-only.

Commit

Permalink
feat: display repos' contributors avatars (#383)
Browse files Browse the repository at this point in the history
closes #333
  • Loading branch information
nightknighto authored Oct 22, 2022
1 parent 2fc96d4 commit ecebb1e
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 66 deletions.
67 changes: 6 additions & 61 deletions src/components/Hero.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { MutableRefObject, useRef, useState } from "react";
import { useDebounce, useDidUpdate, useKeys } from "rooks";
import { FaRegDotCircle } from "react-icons/fa";
import { AiOutlineStar } from "react-icons/ai";

// import StackedAvatar from "./StackedAvatar";
import { fetchRecommendations } from "../lib/supabase";
import humanizeNumber from "../lib/humanizeNumber";
import { getAvatarLink } from "../lib/github";
import searchNormal from "../assets/searchNormal.svg";
import cmdKIcon from "../assets/cmdK.svg";
import SearchedRepoCard from "./SearchedRepoCard";

const Hero = () => {
const containerRef = useRef<Document>(document);
Expand Down Expand Up @@ -101,62 +97,11 @@ const Hero = () => {
<p className="text-gray-500 text-sm font-semibold">Repository</p>
</div>

{fetchedData.map(({ full_name, name, description, issues, stars }) => (
<a
key={full_name}
href={`https://app.opensauced.pizza/repos/${full_name}`}
rel="noreferrer"
target="_blank"
>
<div className="flex flex-col hover:bg-gray-50 ">
<div className="flex flex-col px-10 md:px-3.5 py-2.5">
<div className="flex items-center gap-x-2.5 mb-1">
<div className="w-6 h-6 overflow-hidden border-gray-400 border-px bg-red-100 rounded-full">
<img
alt={full_name}
className="w-full h-full"
src={getAvatarLink(full_name.replace(`/${String(name)}`, ""))}
/>
</div>

<p className="text-base text-gray-500 font-semibold">
{full_name}
</p>
</div>

<p className="text-sm text-gray-500">
{description}
</p>

<div className="flex justify-between mt-2">
{/* <div className="flex gap-x-1">
<StackedAvatar contributors={contributions} />
</div> */}

<div className="flex gap-x-1.5">
<div className="flex items-center gap-x-1">
<FaRegDotCircle aria-hidden="true" />

<p className="text-gray-500 text-xs">
{humanizeNumber(issues)}
</p>
</div>

<div className="flex items-center gap-x-1">
<AiOutlineStar
aria-hidden="true"
className="mr-1"
/>

<p className="text-gray-500 text-xs">
{humanizeNumber(stars)}
</p>
</div>
</div>
</div>
</div>
</div>
</a>
{fetchedData.map(data => (
<SearchedRepoCard
key={data.full_name}
data={data}
/>
))}
</div>
)}
Expand Down
6 changes: 4 additions & 2 deletions src/components/HotRepoCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import Skeleton from "react-loading-skeleton";
import { getAvatarLink } from "../lib/github";
import humanizeNumber from "../lib/humanizeNumber";

// import StackedAvatar from "./StackedAvatar";
import StackedAvatar from "./StackedAvatar";
import useRepo from "../hooks/useRepo";
import useVotedRepos from "../hooks/useVotedRepos";
import useContributions from "../hooks/useContributions";

export declare interface HotRepoCardProps {
repoName: string;
Expand All @@ -20,6 +21,7 @@ const HotRepoCard = ({ repoName }: HotRepoCardProps): JSX.Element => {
const { votedReposIds, checkVoted, voteHandler } = useVotedRepos();
const { repo, isLoading, isError } = useRepo(repoName);
const [isVoted, setIsVoted] = useState(false);
const { data: contributions } = useContributions(repoName);

useEffect(() => {
repo && setIsVoted(checkVoted(repo.id));
Expand Down Expand Up @@ -131,7 +133,7 @@ const HotRepoCard = ({ repoName }: HotRepoCardProps): JSX.Element => {
</div>
</div>

{/* <StackedAvatar contributors={contributions} /> */}
<StackedAvatar contributors={contributions} />
</div>
</div>
);
Expand Down
9 changes: 6 additions & 3 deletions src/components/RepoList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { useEffect, useState } from "react";
import { FaArrowAltCircleUp, FaDotCircle, FaStar } from "react-icons/fa";
import humanizeNumber from "../lib/humanizeNumber";
import { getAvatarLink, getRepoLink } from "../lib/github";

// import StackedAvatar from "./StackedAvatar";
import StackedAvatar from "./StackedAvatar";
import useVotedRepos from "../hooks/useVotedRepos";
import { RiCheckboxCircleFill } from "react-icons/ri";
import cx from "classnames";
import useContributions from "../hooks/useContributions";

export declare interface RepoListProps {
data: DbRepo;
Expand All @@ -28,6 +28,9 @@ const RepoList = ({ data }: RepoListProps): JSX.Element => {
// contributionsCount,
} = data;

// {full_name} consists of `{owner}/{repo}`, so this link is actually `repos/{owner}/{repo}/contributions`
const { data: contributions } = useContributions(full_name);

useEffect(() => {
setIsVoted(checkVoted(id));
}, [votedReposIds]);
Expand Down Expand Up @@ -94,7 +97,7 @@ const RepoList = ({ data }: RepoListProps): JSX.Element => {
</p>
</div>

{/* <StackedAvatar contributors={contributions} />*/}
<StackedAvatar contributors={contributions} />
</div>
</div>

Expand Down
73 changes: 73 additions & 0 deletions src/components/SearchedRepoCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { AiOutlineStar } from "react-icons/ai";
import { FaRegDotCircle } from "react-icons/fa";
import useContributions from "../hooks/useContributions";
import { getAvatarLink } from "../lib/github";
import humanizeNumber from "../lib/humanizeNumber";
import StackedAvatar from "./StackedAvatar";

export declare interface SearchedRepoCardProps {
data: DbRepo;
}

const SearchedRepoCard = ({ data: { full_name, name, description, issues, stars } }: SearchedRepoCardProps) => {
const { data: contributions } = useContributions(full_name);

return (
<a
href={`https://app.opensauced.pizza/repos/${full_name}`}
rel="noreferrer"
target="_blank"
>
<div className="flex flex-col hover:bg-gray-50 ">
<div className="flex flex-col px-10 md:px-3.5 py-2.5">
<div className="flex items-center gap-x-2.5 mb-1">
<div className="w-6 h-6 overflow-hidden border-gray-400 border-px bg-red-100 rounded-full">
<img
alt={full_name}
className="w-full h-full"
src={getAvatarLink(full_name.replace(`/${String(name)}`, ""))}
/>
</div>

<p className="text-base text-gray-500 font-semibold">
{full_name}
</p>
</div>

<p className="text-sm text-gray-500">
{description}
</p>

<div className="flex justify-between mt-2">
<div className="flex gap-x-1">
<StackedAvatar contributors={contributions} />
</div>

<div className="flex gap-x-1.5">
<div className="flex items-center gap-x-1">
<FaRegDotCircle aria-hidden="true" />

<p className="text-gray-500 text-xs">
{humanizeNumber(issues)}
</p>
</div>

<div className="flex items-center gap-x-1">
<AiOutlineStar
aria-hidden="true"
className="mr-1"
/>

<p className="text-gray-500 text-xs">
{humanizeNumber(stars)}
</p>
</div>
</div>
</div>
</div>
</div>
</a>
);
};

export default SearchedRepoCard;
25 changes: 25 additions & 0 deletions src/hooks/useContributions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import useSWR from "swr";

interface PaginatedContributorsResponse {
readonly data: DbContribution[];
readonly meta: PageMetaDto;
}

const useContributions = (repoName: string, limit = 10, orderBy = "recent") => {
const baseEndpoint = `repos/${repoName}/contributions`;
const limitQuery = `&limit=${limit}`;
const orderByQuery = orderBy ? `&updated_at=${orderBy}` : "";
const endpointString = `${baseEndpoint}?${limitQuery}${orderByQuery}`;

const { data, error, mutate } = useSWR<PaginatedContributorsResponse, Error>(endpointString);

return {
data: data?.data ?? [],
meta: data?.meta ?? { itemCount: 0 },
isLoading: !error && !data,
isError: !!error,
mutate,
};
};

export default useContributions;

0 comments on commit ecebb1e

Please sign in to comment.