From 3f7fe0320fadadde9653ad224878b308f7d8a16d Mon Sep 17 00:00:00 2001 From: "sa.cux" Date: Wed, 31 Jan 2024 14:47:38 +0100 Subject: [PATCH] refactor pages and deleted unnecessary code --- src/pages/profile/index.tsx | 13 +- src/pages/stats/[login].tsx | 351 +++++------------------------------- src/utils/exportAsImage.ts | 46 ----- src/utils/index.ts | 1 - 4 files changed, 51 insertions(+), 360 deletions(-) delete mode 100644 src/utils/exportAsImage.ts delete mode 100644 src/utils/index.ts diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx index 940ab50..e8925dc 100644 --- a/src/pages/profile/index.tsx +++ b/src/pages/profile/index.tsx @@ -6,9 +6,10 @@ import { import { useGitHubQuery } from "@/hooks"; import Image from "next/image"; import Link from "next/link"; -import { exportAsImage } from "@/utils"; import GitHubCalendar from "react-github-calendar"; import { Tooltip as ReactTooltip } from "react-tooltip"; +import { exportAsImage } from "@/utils/exportRepositories"; +import { ExportOptions } from "@/utils/exportOptions"; interface Activity { date: string; @@ -53,7 +54,11 @@ export default function Profile() { diff --git a/src/pages/stats/[login].tsx b/src/pages/stats/[login].tsx index 2d1fb46..54e56ff 100644 --- a/src/pages/stats/[login].tsx +++ b/src/pages/stats/[login].tsx @@ -1,14 +1,13 @@ -import { RepositoryContributionsCard } from "@/components"; -import { useGitHubPullRequests } from "@/hooks"; -import { PullRequestContributionsByRepository } from "@/types/github"; -import { exportAsImage } from "@/utils"; +import { useState } from "react"; import { useSession } from "next-auth/react"; import { useRouter } from "next/router"; -import { useMemo, useState } from "react"; +import { useGitHubPullRequests, useFilteredRepositories } from "@/hooks"; import CardSkeleton from "@/components/CardSkeleton"; -import { toast } from "react-toastify"; - -const yearsRange = 4; +import ReposFilters from "@/components/ReposFilters"; +import FormatStatsRender from "@/components/FormatStatsRender"; +import { RepositoryRenderFormat } from "@/types/github"; +import { exportAsJSON, exportAsText } from "@/utils/exportRepositories"; +import { generateText } from "@/utils/generateText"; export default function Stats() { const { data: session } = useSession(); @@ -16,313 +15,45 @@ export default function Stats() { const { login } = router.query; const baseYear = new Date().getFullYear(); const [year, setYear] = useState(baseYear); - const [format, setFormat] = useState<"cards" | "text" | "json">("cards"); - const [hideOwnRepo, setHideOwnRepo] = useState(false); - - const { - repositories, - isLoading, - }: { - repositories: PullRequestContributionsByRepository[]; - isLoading: boolean; - } = useGitHubPullRequests(year, login as string); + const [format, setFormat] = useState("cards"); const [searchQuery, setSearchQuery] = useState(""); + const [hideOwnRepo, setHideOwnRepo] = useState(false); - const filteredRepositories = useMemo(() => { - const filterOutOwnRepos = ( - repositories: PullRequestContributionsByRepository[] - ) => { - return repositories?.filter( - (repoData) => repoData.repository.owner.login !== session?.user.login - ); - }; - - const filterReposBySearchQuery = ( - repositories: PullRequestContributionsByRepository[] - ) => { - const query = searchQuery.toLowerCase(); - return repositories?.filter((repoData) => - repoData.repository.name.toLowerCase().includes(query) - ); - }; - - const filterRepos = ( - repositories: PullRequestContributionsByRepository[] - ) => { - if (!searchQuery) { - return hideOwnRepo ? filterOutOwnRepos(repositories) : repositories; - } - - const filteredReposBySearchQuery = filterReposBySearchQuery(repositories); - if (!hideOwnRepo) { - return filteredReposBySearchQuery; - } - - return filterOutOwnRepos(filteredReposBySearchQuery); - }; + const { repositories, isLoading } = useGitHubPullRequests( + year, + login as string + ); - return filterRepos(repositories); - }, [repositories, searchQuery, hideOwnRepo, session]); + const filteredRepositories = useFilteredRepositories( + repositories, + searchQuery, + hideOwnRepo + ); const handleHideOwnRepo = () => { setHideOwnRepo((prevHideOwnRepo) => !prevHideOwnRepo); }; - const exportJSON = () => { - const jsonStringData = JSON.stringify(repositories, null, 2); - - const blob = new Blob([jsonStringData], { type: "application/json" }); - - const url = URL.createObjectURL(blob); - - const link = document.createElement("a"); - //setting the link as url of the blob - link.href = url; - link.download = "data.json"; - link.click(); - URL.revokeObjectURL(url); - }; - - const exportText = () => { - const text = generateText(); - const blob = new Blob([text], { type: "text/plain" }); - - const url = URL.createObjectURL(blob); - - const link = document.createElement("a"); - //setting the link as url of the blob - link.href = url; - link.download = "data.txt"; - link.click(); - URL.revokeObjectURL(url); - }; - - function generateText() { - let text = "List of repositories and their pull requests:\n\n"; - - for (const repoData of filteredRepositories) { - const repositoryName = repoData.repository.name; - const ownerLogin = repoData.repository.owner.login; - const stargazerCount = repoData.repository.stargazerCount; - const avatarUrl = repoData.repository.owner.avatarUrl; - - text += `Repository: ${repositoryName}\n`; - text += `Owner: ${ownerLogin}\n`; - text += `Stargazers: ${stargazerCount}\n`; - text += `Owner Avatar: ${avatarUrl}\n\n`; - - const contributions = repoData.contributions.nodes; - text += "Contributions:\n"; - for (const contribution of contributions) { - const prId = contribution.pullRequest.id; - const prTitle = contribution.pullRequest.title; - const prState = contribution.pullRequest.state; - text += `- Pull Request: ${prTitle}\n`; - text += ` ID: ${prId}\n`; - text += ` State: ${prState}\n`; - } - - text += "\n"; - } - return text; - } - - const copyToClipboard = (format: "text" | "json") => { - let data = null; - - if (format === "text") data = generateText(); - else data = JSON.stringify(repositories, null, 2); - - navigator.clipboard - .writeText(data) - .then(() => { - toast.success(`${format} copied to clipboard`); - }) - .catch(() => { - toast.error(`Failed to copy ${format} to clipboard`); - }); - }; - - const formatRender = useMemo(() => { - switch (format) { - case "cards": - return ( - <> -
- -
    -
  • - -
  • -
  • - -
  • -
-
-
- {filteredRepositories?.length > 0 - ? filteredRepositories?.map( - ({ repository, contributions }, i) => ( - - ) - ) - : "No repositories found"} -
- - ); - case "json": - return ( -
- - -
-
{JSON.stringify(filteredRepositories, null, 2)}
-
-
- ); - case "text": - return ( -
- - -
-
{generateText()}
-
-
- ); - default: - return ( -
-

📃

-

Format is not matching any!

-
- ); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [repositories, format, searchQuery, hideOwnRepo]); - return (
-
-

- {session?.user.name} ({session?.user.login}) -

-
-
-
-
Select Year
-
- {new Array(yearsRange).fill(0).map((_, i) => { - const radioYear = baseYear - yearsRange + i + 1; - return ( - setYear(radioYear)} - checked={year === radioYear} - /> - ); - })} -
-
- - setSearchQuery(e.target.value)} - /> -
-
- - -
-
- -
-
Select Format
-
- setFormat("cards")} - checked={format === "cards"} - /> - setFormat("text")} - checked={format === "text"} - /> - - setFormat("json")} - checked={format === "json"} - /> -
-
+
+

+ {session?.user.name && + session?.user.login && + `${session.user.name} (${session.user.login})`} +

+ {isLoading ? (
{Array.from({ length: 10 }, (_, index) => ( @@ -331,13 +62,13 @@ export default function Stats() {
))}
- ) : filteredRepositories?.length > 0 ? ( - formatRender ) : ( -
-

📃

-

No Contributions

-
+ exportAsJSON(filteredRepositories)} + exportText={() => exportAsText(generateText(filteredRepositories))} + /> )}
); diff --git a/src/utils/exportAsImage.ts b/src/utils/exportAsImage.ts deleted file mode 100644 index d1cf38a..0000000 --- a/src/utils/exportAsImage.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { toPng } from "html-to-image"; -import { toast } from "react-toastify"; - -export const exportAsImage = async ( - selector: string, - option: "download" | "clipboard", - filename?: string -) => { - const dataURI = await toPng(document.querySelector(selector) as HTMLElement, { - includeQueryParams: true, - cacheBust: true, - }); - const image = new Image(); - image.src = dataURI; - image.onload = () => { - const canvas = document.createElement("canvas"); - canvas.width = image.width; - canvas.height = image.height; - const context = canvas.getContext("2d"); - context?.drawImage(image, 0, 0); - canvas.toBlob((blob) => { - if (blob) { - if (option === "download") { - const url = URL.createObjectURL(blob); - const a = document.createElement("a"); - a.href = url; - a.download = filename ? `${filename}.png` : "image.png"; - a.click(); - URL.revokeObjectURL(url); - a.remove(); - } - if (option === "clipboard") { - navigator.clipboard - .write([new ClipboardItem({ "image/png": blob })]) - .then(() => { - toast.success("Image copied to clipboard"); - }) - .catch(() => { - toast.error("Failed to copy image to clipboard"); - }); - } - } - }); - canvas.remove(); - }; -}; diff --git a/src/utils/index.ts b/src/utils/index.ts deleted file mode 100644 index 17a5365..0000000 --- a/src/utils/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./exportAsImage";