mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-04-26 16:28:28 -04:00
149 lines
3.8 KiB
TypeScript
149 lines
3.8 KiB
TypeScript
import { graphql } from "@octokit/graphql";
|
|
import { NextSeo } from "next-seo";
|
|
import Content from "../components/Content";
|
|
import PageTitle from "../components/PageTitle";
|
|
import Link from "../components/Link";
|
|
import RepositoryCard from "../components/RepositoryCard";
|
|
import { SiGithub } from "react-icons/si";
|
|
import { styled, theme } from "../lib/styles/stitches.config";
|
|
import config from "../lib/config";
|
|
import type { GetStaticProps, InferGetStaticPropsType } from "next";
|
|
import type { User, Repository } from "@octokit/graphql-schema";
|
|
import type { Project } from "../types";
|
|
|
|
const Wrapper = styled("div", {
|
|
display: "flex",
|
|
flexFlow: "row wrap",
|
|
justifyContent: "space-between",
|
|
alignItems: "flex-start",
|
|
width: "100%",
|
|
lineHeight: 1.1,
|
|
});
|
|
|
|
const Card = styled(RepositoryCard, {
|
|
flexGrow: 1,
|
|
margin: "0.6em",
|
|
width: "370px",
|
|
});
|
|
|
|
const ViewMore = styled("p", {
|
|
textAlign: "center",
|
|
marginBottom: 0,
|
|
fontWeight: 500,
|
|
});
|
|
|
|
const GitHubLogo = styled(SiGithub, {
|
|
width: "1.2em",
|
|
height: "1.2em",
|
|
verticalAlign: "-0.2em",
|
|
margin: "0 0.15em",
|
|
fill: theme.colors.text,
|
|
});
|
|
|
|
const Projects = ({ repos }: InferGetStaticPropsType<typeof getStaticProps>) => {
|
|
return (
|
|
<>
|
|
<NextSeo
|
|
title="Projects"
|
|
openGraph={{
|
|
title: "Projects",
|
|
}}
|
|
/>
|
|
|
|
<PageTitle>💾 Projects</PageTitle>
|
|
|
|
<Content>
|
|
<Wrapper>
|
|
{repos.map((repo) => (
|
|
<Card key={repo.name} {...repo} />
|
|
))}
|
|
</Wrapper>
|
|
|
|
<ViewMore>
|
|
<Link href={`https://github.com/${config.authorSocial.github}`}>
|
|
View more on <GitHubLogo /> GitHub...
|
|
</Link>
|
|
</ViewMore>
|
|
</Content>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export const getStaticProps: GetStaticProps<{
|
|
repos: Project[];
|
|
}> = async () => {
|
|
// don't fail the entire site build if the required API key for this page is missing
|
|
if (!process.env.GH_PUBLIC_TOKEN || process.env.GH_PUBLIC_TOKEN === "") {
|
|
console.warn(`ERROR: I can't fetch any GitHub projects without "GH_PUBLIC_TOKEN" set! Skipping for now...`);
|
|
|
|
return {
|
|
notFound: true,
|
|
};
|
|
}
|
|
|
|
// https://docs.github.com/en/graphql/reference/objects#repository
|
|
const { user } = await graphql<{ user: User }>(
|
|
`
|
|
query ($username: String!, $sort: RepositoryOrderField!, $limit: Int) {
|
|
user(login: $username) {
|
|
repositories(
|
|
first: $limit
|
|
isLocked: false
|
|
isFork: false
|
|
ownerAffiliations: OWNER
|
|
privacy: PUBLIC
|
|
orderBy: { field: $sort, direction: DESC }
|
|
) {
|
|
edges {
|
|
node {
|
|
name
|
|
url
|
|
description
|
|
pushedAt
|
|
stargazerCount
|
|
forkCount
|
|
primaryLanguage {
|
|
name
|
|
color
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`,
|
|
{
|
|
username: config.authorSocial.github,
|
|
sort: "STARGAZERS",
|
|
limit: 12,
|
|
headers: {
|
|
accept: "application/vnd.github.v3+json",
|
|
authorization: `token ${process.env.GH_PUBLIC_TOKEN}`,
|
|
},
|
|
}
|
|
);
|
|
|
|
const results = user.repositories.edges as Array<{ node: Repository }>;
|
|
|
|
const repos = results.map<Project>(({ node: repo }) => ({
|
|
name: repo.name,
|
|
url: repo.url,
|
|
description: repo.description as string,
|
|
updatedAt: repo.pushedAt,
|
|
stars: repo.stargazerCount,
|
|
forks: repo.forkCount,
|
|
language: repo.primaryLanguage as Project["language"],
|
|
}));
|
|
|
|
return {
|
|
props: {
|
|
repos,
|
|
},
|
|
// fetch updated data and update page every 10 minutes (as needed)
|
|
// https://nextjs.org/docs/basic-features/data-fetching#incremental-static-regeneration
|
|
revalidate: 600,
|
|
};
|
|
};
|
|
|
|
export default Projects;
|