Skip to content

Commit

Permalink
feat(ui): add project list on /about
Browse files Browse the repository at this point in the history
  • Loading branch information
duyet committed Jun 23, 2024
1 parent 942042e commit 063bf99
Show file tree
Hide file tree
Showing 4 changed files with 174 additions and 36 deletions.
3 changes: 1 addition & 2 deletions apps/blog/app/about/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import Container from '@duyet/components/Container';
import Header from '@duyet/components/Header';
import * as React from 'react';

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<Header />
<Container className="mb-16 md:mb-32">{children}</Container>
{children}
</>
);
}
77 changes: 43 additions & 34 deletions apps/blog/app/about/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import Container from '@duyet/components/Container';
import { Projects } from '../../components/projects';

interface Link {
name: string;
link?: string;
Expand Down Expand Up @@ -38,43 +41,49 @@ const links: Link[] = [

export default function About() {
return (
<div className="space-y-6 leading-loose">
<h1 className="my-10 text-6xl font-bold lg:text-7xl">Duyệt</h1>
<p>
<strong>Data Engineer</strong> with 5+ years of experience. I am
confident in my knowledge of Data Engineering concepts, best practices
and state-of-the-art data and Cloud technologies.
</p>

<div className="flex flex-col gap-5">
<div className="mb-16 space-y-6 leading-loose">
<Container className="mb-8 md:mb-16">
<h1 className="my-10 text-6xl font-bold lg:text-7xl">Duyệt</h1>
<p>
{links.map(({ name, link = '#' }) => (
<a
className="mr-4 text-blue-600"
href={link}
key={name}
rel="nofollow noopener noreferrer"
target="_blank"
>
{name}
</a>
))}
<strong>Data Engineer</strong> with 5+ years of experience. I am
confident in my knowledge of Data Engineering concepts, best practices
and state-of-the-art data and Cloud technologies.
</p>

<p>
Skills & stacks:{' '}
{skills.map(({ name, link = '#' }) => (
<a
className="mr-4 inline-block text-blue-600"
href={link}
key={name}
rel="noopener noreferrer"
target="_blank"
>
{name}
</a>
))}
</p>
<div className="flex flex-col gap-5">
<p>
{links.map(({ name, link = '#' }) => (
<a
className="mr-4 text-blue-600"
href={link}
key={name}
rel="nofollow noopener noreferrer"
target="_blank"
>
{name}
</a>
))}
</p>

<p>
Skills & stacks:{' '}
{skills.map(({ name, link = '#' }) => (
<a
className="mr-4 inline-block text-blue-600"
href={link}
key={name}
rel="noopener noreferrer"
target="_blank"
>
{name}
</a>
))}
</p>
</div>
</Container>

<div className="lg:m-15 m-5 md:mx-20">
<Projects />
</div>
</div>
);
Expand Down
129 changes: 129 additions & 0 deletions apps/blog/components/projects.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/* eslint-disable camelcase */
import { cn } from '@duyet/libs/utils';
import { CodeIcon, StarIcon } from '@radix-ui/react-icons';
import Link from 'next/link';

interface ProjectProps {
className?: string;
}

interface Project {
name: string;
html_url: string;
description: string;
stargazers_count: number;
language: string;
archived: boolean;
disabled: boolean;
}

export async function Projects({ className }: ProjectProps) {
const projects = await getGithubProjects(
'duyet',
['clickhouse-monitoring', 'pricetrack', 'grant-rs', 'charts'],
[
'awesome-web-scraper',
'vietnamese-wordlist',
'vietnamese-namedb',
'vietnamese-frontend-interview-questions',
'opencv-car-detection',
'saveto',
'firebase-shorten-url',
'google-search-crawler',
],
12,
);

return (
<div className={cn('w-full', className)}>
<div className="mt-4 grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{projects.map((project) => (
<ProjectItem key={project.name} project={project} />
))}
</div>
</div>
);
}

function ProjectItem({
project: { name, html_url, description, stargazers_count, language },
}: {
project: Project;
}) {
return (
<div className="group relative rounded-lg border bg-background p-4 transition-all hover:shadow-lg">
<Link className="absolute inset-0 z-10" href={html_url} prefetch={false}>
<span className="sr-only">View project</span>
</Link>

<div className="space-y-2">
<div className="flex items-center justify-between">
<h3 className="text-lg font-semibold tracking-tight">{name}</h3>
<div className="flex items-center gap-1 text-sm text-muted-foreground">
<StarIcon className="h-4 w-4" />
<span>{stargazers_count}</span>
</div>
</div>

<p className="text-sm text-muted-foreground">
{description || 'No description'}
</p>

{language ? (
<div className="flex items-center gap-2 text-sm text-muted-foreground">
<CodeIcon className="h-4 w-4" />
<span>{language}</span>
</div>
) : null}
</div>
</div>
);
}

/**
* Get Github projects of a user with some preferred projects and ignored projects
*/
async function getGithubProjects(
owner: string,
preferredProjects: string[] = [],
ignoredProjects: string[] = [],
n = 8,
): Promise<Project[]> {
let allProjects: Project[] = [];

const fetchPage = async (page: number) => {
const params = new URLSearchParams({
sort: 'pushed',
per_page: '100',
type: 'all',
page: page.toString(),
});
const res = await fetch(
`https://api.github.com/users/${owner}/repos?${params.toString()}`,
{ cache: 'force-cache' },
);
return res.json() as Promise<Project[]>;
};

const results = await Promise.all([1, 2, 3, 4, 5, 6].map(fetchPage));
allProjects = results.flat();

const filteredProjects = allProjects.filter(
(project: Project) =>
project.stargazers_count > 0 &&
!project.archived &&
!project.disabled &&
!ignoredProjects.includes(project.name),
);

const sortedProjects = [
...preferredProjects
.map((name) => filteredProjects.find((p) => p.name === name))
.filter(Boolean),
...filteredProjects.filter((p) => !preferredProjects.includes(p.name)),
]
.filter((project): project is Project => project !== undefined)
.sort((a, b) => b.stargazers_count - a.stargazers_count);

return sortedProjects.slice(0, n);
}
1 change: 1 addition & 0 deletions apps/blog/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@duyet/components": "*",
"@duyet/libs": "*",
"@headlessui/tailwindcss": "^0.2.0",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-toggle-group": "^1.0.3",
"@tremor/react": "^3.0.0",
"@vercel/analytics": "^1.0.0",
Expand Down

0 comments on commit 063bf99

Please sign in to comment.