Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 0 additions & 132 deletions src/components/GithubFeed.astro

This file was deleted.

133 changes: 133 additions & 0 deletions src/components/GithubRepos.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
---
export const prerender = false;

import { Octokit } from "@octokit/rest";
import { Icon } from "astro-icon/components";
import RepoCard from "./RepoCard.astro";

interface DisplayRepo {
owner: string;
name: string;
description: string;
url: string;
stars: number;
language?: string;
}

const octokit = new Octokit({
auth: import.meta.env.GITHUB_TOKEN
});

const GITHUB_USERNAME = "dsnsgithub";
const STARRED_COUNT = 6;

async function fetchPinnedRepos(): Promise<DisplayRepo[]> {
// Pinned repositories are only exposed through the GraphQL API.
const response = await fetch("https://api.github.com/graphql", {
method: "POST",
headers: {
Authorization: `Bearer ${import.meta.env.GITHUB_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
query: `
query ($login: String!) {
user(login: $login) {
pinnedItems(first: 6, types: REPOSITORY) {
nodes {
... on Repository {
name
description
url
stargazerCount
primaryLanguage { name }
owner { login }
}
}
}
}
}
`,
variables: { login: GITHUB_USERNAME }
})
});

const json = await response.json();
const items: Array<Record<string, any>> = json.data?.user?.pinnedItems?.nodes ?? [];

return items.map((repo) => ({
owner: repo.owner.login,
name: repo.name,
description: repo.description ?? "",
url: repo.url,
stars: repo.stargazerCount,
language: repo.primaryLanguage?.name
}));
}

async function fetchStarredRepos(): Promise<DisplayRepo[]> {
const res = await octokit.rest.activity.listReposStarredByUser({
username: GITHUB_USERNAME,
sort: "created",
direction: "desc",
per_page: STARRED_COUNT
});

return res.data.map((item) => {
const repo = "repo" in item ? item.repo : item;

return {
owner: repo.owner.login,
name: repo.name,
description: repo.description ?? "",
url: repo.html_url,
stars: repo.stargazers_count,
language: repo.language ?? undefined
};
});
}

function sortRepos(repos: DisplayRepo[]): DisplayRepo[] {
return [...repos].sort((a, b) => b.stars - a.stars);
}

const [pinned, starred] = await Promise.all([fetchPinnedRepos(), fetchStarredRepos()]);
---

<div class="flex flex-col gap-6">
{pinned.length === 0 && starred.length === 0 && (
<p class="py-4 text-center text-gray-500">No repositories found.</p>
)}

{
pinned.length > 0 && (
<div>
<h3 class="mb-3 flex items-center gap-2 text-lg font-bold">
<Icon name="mdi:pin" class="text-viola-700" />
Pinned Repositories
</h3>
<div class="grid gap-3 sm:grid-cols-2">
{pinned.map((repo) => (
<RepoCard owner={repo.owner} name={repo.name} description={repo.description} url={repo.url} stars={repo.stars} language={repo.language} />
))}
</div>
</div>
)
}

{
starred.length > 0 && (
<div>
<h3 class="mb-3 flex items-center gap-2 text-lg font-bold">
<Icon name="mdi:star" class="text-viola-700" />
Repositories I Find Cool
</h3>
<div class="grid gap-3 sm:grid-cols-2">
{sortRepos(starred).map((repo) => (
<RepoCard owner={repo.owner} name={repo.name} description={repo.description} url={repo.url} stars={repo.stars} language={repo.language} />
))}
</div>
</div>
)
}
</div>
36 changes: 36 additions & 0 deletions src/components/RepoCard.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
import { Icon } from "astro-icon/components";

interface Props {
url: string;
owner: string;
name: string;
description: string;
stars: number;
language?: string;
}

const { url, owner, name, description, stars, language } = Astro.props;
---

<a
href={url}
target="_blank"
rel="noopener noreferrer"
class="flex flex-col rounded-xl bg-viola-50 p-5 shadow-lg duration-500 hover:scale-[1.01] hover:transition hover:duration-500"
>
<div class="mb-1 flex items-center justify-between gap-2">
<p class="truncate font-bold text-viola-700" title={`${owner}/${name}`}>{name}</p>
<p class="flex shrink-0 items-center gap-1 text-xs text-gray-500">
<Icon name="mdi:star" class="text-xs text-gray-400" />
{stars}
</p>
</div>

{description && <p class="line-clamp-2 text-sm text-gray-600">{description}</p>}

<div class="mt-auto flex items-center gap-2 pt-3 text-[10px] sm:text-[11px]">
{language && <span class="rounded-lg bg-viola-200 p-1 px-2 font-semibold">{language}</span>}
<span class="truncate text-gray-400">{owner}</span>
</div>
</a>
8 changes: 4 additions & 4 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import scheduliIcon from "../assets/schedule.svg";
import betterHudIcon from "../assets/betterhud.png";
import { Icon } from "astro-icon/components";
import DiscordStatus from "../components/DiscordStatus.tsx";
import GithubFeed from "../components/GithubFeed.astro";
import GithubRepos from "../components/GithubRepos.astro";
import GithubFeedSkeleton from "../components/GithubFeedSkeleton.astro";
---

Expand Down Expand Up @@ -71,10 +71,10 @@ import GithubFeedSkeleton from "../components/GithubFeedSkeleton.astro";
</div>

<div class="m-2 rounded-lg bg-viola-100 p-6 shadow-lg lg:p-8">
<h2 class="mb-6 text-2xl font-bold">GitHub Feed</h2>
<GithubFeed server:defer>
<h2 class="mb-6 text-2xl font-bold">GitHub</h2>
<GithubRepos server:defer>
<GithubFeedSkeleton slot="fallback" />
</GithubFeed>
</GithubRepos>
</div>
</div>
</Layout>
24 changes: 0 additions & 24 deletions src/types/GitHub.ts

This file was deleted.