-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
added realtime works data card using github api
- Loading branch information
Showing
13 changed files
with
652 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
"use client"; | ||
|
||
export default () => { | ||
return ( | ||
<main> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { get } from "https"; | ||
import { useState } from "react"; | ||
|
||
export function getRandomColor(): string { | ||
let color: string = ""; | ||
const min: number = 50; | ||
const max: number = 255; | ||
|
||
do { | ||
color = `rgb(${Math.floor(Math.random() * (max - min) + min)}, | ||
${Math.floor(Math.random() * (max - min) + min)}, | ||
${Math.floor(Math.random() * (max - min) + min)})`; | ||
} while (color === "rgb(0, 0, 0)"); | ||
|
||
return color; | ||
} | ||
|
||
export function convertDate(dateString: string): string { | ||
const date = new Date(dateString); | ||
|
||
let monthAbbreviations = [ | ||
"Jan", | ||
"Feb", | ||
"Mar", | ||
"Apr", | ||
"May", | ||
"Jun", | ||
"Jul", | ||
"Aug", | ||
"Sep", | ||
"Oct", | ||
"Nov", | ||
"Dec", | ||
]; | ||
|
||
const day = date.getUTCDate(); | ||
const month = monthAbbreviations[date.getUTCMonth()]; | ||
const year = date.getUTCFullYear(); | ||
|
||
return `${day} ${month} ${year}`; | ||
} | ||
|
||
export async function getLatestVersion(releasesUrl: string) { | ||
await new Promise((resolve, reject) => { | ||
if (!releasesUrl) { | ||
reject("Error: Unreleased project"); | ||
} | ||
|
||
const endpoint = releasesUrl.slice(0, -5) + "/latest"; | ||
const parsedUrl = new URL(endpoint); | ||
|
||
const options = { | ||
hostname: parsedUrl.hostname, | ||
path: parsedUrl.pathname, | ||
headers: { | ||
"User-Agent": "node.js", | ||
Accept: "application/json", | ||
}, | ||
}; | ||
|
||
get(options, (res) => { | ||
let data: string = ""; | ||
|
||
res.on("data", (chunk) => { | ||
data += chunk; | ||
}); | ||
|
||
if (res.statusCode === 200) { | ||
resolve(JSON.parse(data).tag_name ?? false); | ||
} else { | ||
reject("Error: " + res.statusCode); | ||
} | ||
}).on("error", (err) => { | ||
reject(err); | ||
}); | ||
}); | ||
} | ||
|
||
export function LatestVersion({ releasesUrl }: { releasesUrl: string }) { | ||
const [state, setState] = useState<string | boolean>(false); | ||
|
||
getLatestVersion(releasesUrl) | ||
.then((version: any) => { | ||
if (version) setState(version); | ||
}) | ||
.catch((err) => { | ||
console.log(err); | ||
}); | ||
|
||
return ( | ||
<p className="text-blue-500"> | ||
{state ? `Version: ${state}` : "Unreleased"} | ||
</p> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { GithubRepoMeta } from "lib/options"; | ||
import { FaGithub } from "react-icons/fa6"; | ||
import { RxExternalLink } from "react-icons/rx"; | ||
import { convertDate } from "./utils"; | ||
|
||
export default ({ projects }: { projects: GithubRepoMeta[] }) => ( | ||
<section className="py-5"> | ||
<div className="max-w-screen-xl mx-auto px-4 md:px-8"> | ||
<ul className="mt-0 grid gap-8 sm:grid-cols-2 lg:grid-cols-3"> | ||
{projects.map((project, idx) => ( | ||
<li | ||
className="border rounded-lg" | ||
key={idx}> | ||
<div className="flex items-start justify-between p-4"> | ||
<div className="space-y-2"> | ||
<h4 className="text-gray-800 font-bold text-blue-700"> | ||
{project.name.toUpperCase()} | ||
</h4> | ||
<p className="text-gray-600 text-sm"> | ||
{project.description} | ||
</p> | ||
</div> | ||
<div className="flex gap-2"> | ||
<a | ||
href={project.htmlUrl + "#readme"} | ||
target="_" | ||
className="text-black text-sm border rounded-lg p-1 duration-150 hover:bg-gray-100 hover:text-indigo-600"> | ||
<FaGithub | ||
size={20} | ||
className="fill-current" | ||
/> | ||
</a> | ||
|
||
{project.homepage ? ( | ||
<a | ||
href={project.homepage ?? ""} | ||
target="_" | ||
className="text-black text-sm border rounded-lg p-1 duration-150 hover:bg-gray-100 hover:text-indigo-600"> | ||
<RxExternalLink | ||
size={20} | ||
className="fill-current" | ||
/> | ||
</a> | ||
) : ( | ||
"" | ||
)} | ||
</div> | ||
</div> | ||
<section className="py-5 px-4 border-t text-sm"> | ||
<div className="flex gap-x-2 justify-between"> | ||
<ul> | ||
<li className="font-medium"> | ||
Created:{" "} | ||
<span className="font-normal text-gray-500"> | ||
{convertDate(project.createdAt)} | ||
</span> | ||
</li> | ||
<li className="font-medium"> | ||
Updated:{" "} | ||
<span className="font-normal text-gray-500"> | ||
{convertDate(project.updatedAt)} | ||
</span> | ||
</li> | ||
{project.openIssuesCount ? ( | ||
<li className="font-medium"> | ||
Request:{" "} | ||
<span className="font-normal text-gray-500"> | ||
{project.openIssuesCount} | ||
</span> | ||
</li> | ||
) : ( | ||
"" | ||
)} | ||
</ul> | ||
<ul> | ||
<p className="text-blue-500"> | ||
©️ {project.license.spdxId} | ||
</p> | ||
{/* <LatestVersion releasesUrl={project.releasesUrl ?? ""} /> */} | ||
</ul> | ||
</div> | ||
</section> | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
</section> | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import * as Tabs from "@radix-ui/react-tabs"; | ||
|
||
import { GithubRepoMeta } from "lib/options"; | ||
import { groupedMetaKey } from "meta"; | ||
import { useEffect, useState } from "react"; | ||
import WorkCard from "./work-card"; | ||
|
||
export default () => { | ||
const [tabItems, setTabItems] = useState< | ||
Record<string, GithubRepoMeta[]> | ||
>({}); | ||
|
||
const [selectedTab, setSelectedTab] = useState<string>("Loading"); | ||
|
||
useEffect(() => { | ||
const groupedMeta = JSON.parse( | ||
localStorage.getItem(groupedMetaKey) ?? "{}", | ||
); | ||
|
||
setTabItems(groupedMeta); | ||
setSelectedTab(Object.keys(groupedMeta)[0]); | ||
}, []); | ||
|
||
return ( | ||
<> | ||
<Tabs.Root | ||
className="max-w-screen-xl mt-2 mx-auto px-4 md:px-8 flex-col" | ||
value={selectedTab} | ||
onValueChange={(val) => setSelectedTab(val)}> | ||
<Tabs.List | ||
className="hidden gap-x-3 py-1 overflow-x-auto px-px text-sm sm:flex place-content-center" | ||
aria-label="Project Experience"> | ||
{Object.keys(tabItems).map((language, idx) => ( | ||
<Tabs.Trigger | ||
key={idx} | ||
className="data-[state=active]:bg-gray-100 data-[state=active]:text-gray-700 data-[state=active]:shadow-sm outline-gray-800 py-1.5 px-3 rounded-lg duration-150 text-gray-500 hover:text-gray-700 hover:bg-gray-100 active:bg-gray-100 font-medium" | ||
value={language}> | ||
{language} | ||
</Tabs.Trigger> | ||
))} | ||
</Tabs.List> | ||
|
||
{/* mobile area */} | ||
<div className="relative text-gray-500 sm:hidden"> | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
viewBox="0 0 20 20" | ||
fill="currentColor" | ||
className="pointer-events-none w-5 h-5 absolute right-2 inset-y-0 my-auto"> | ||
<path | ||
fillRule="evenodd" | ||
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" | ||
clipRule="evenodd" | ||
/> | ||
</svg> | ||
<select | ||
value={selectedTab} | ||
className="py-2 px-3 w-full bg-transparent appearance-none outline-none border rounded-lg shadow-sm focus:border-gray-800 text-sm" | ||
onChange={(e) => setSelectedTab(e.target.value)}> | ||
{Object.keys(tabItems).map((language, idx) => ( | ||
<option | ||
key={idx} | ||
tabIndex={idx}> | ||
{language} | ||
</option> | ||
))} | ||
</select> | ||
</div> | ||
{/* mobile area ended */} | ||
|
||
{Object.keys(tabItems).map((language, idx) => ( | ||
<Tabs.Content | ||
key={idx} | ||
className="py-6" | ||
value={language}> | ||
<WorkCard projects={tabItems[language]} /> | ||
</Tabs.Content> | ||
))} | ||
</Tabs.Root> | ||
</> | ||
); | ||
}; |
Oops, something went wrong.