diff --git a/hooks/useContributorData.ts b/hooks/useContributorData.ts index a702594..bf6fa9a 100644 --- a/hooks/useContributorData.ts +++ b/hooks/useContributorData.ts @@ -1,46 +1,38 @@ import useSWR from "swr"; import { useCallback } from "react"; interface PaginatedDataResponse { - readonly data: DBContributors[]; + readonly data: DBContributorsPR[]; readonly meta: Meta; } -type Response = - | { type: "loading" } - | { type: "error"; error: Error } - // Todo: figure out meta - | { type: "result"; data: DBContributors[]; meta: { itemCount: number } }; - // We're not currently using this, we're just using useSWR directly inside ChildWithSWR // this needs useCallback wrap if we want to use it in the other component -const useContributorData = () => { - useCallback(async (owner: string, repo: string): Promise => { - // useSWR is probably going to be a sticking point - // eslint-disable-next-line react-hooks/rules-of-hooks - const { data, error, mutate } = useSWR( - `repos/${owner}/${repo}/contributions` - ); - - if (!error && !data) { - return { type: "loading" }; - } - - if (error) { - return { - type: "error", - error: error - }; - } - - return { - type: "result", - data: data?.data ?? [], - meta: data?.meta ?? { itemCount: 0 } - // commenting for now to appease build - // mutate - }; - }, []); +const useContributorData = (repo: string, startDate?: number, status?: "closed" | "open") => { + const query = new URLSearchParams(); + + if (startDate) { + query.set("prev_days_start_date", `${startDate}`); + } + if (status) { + query.set("status", `${status}`); + } + query.set("repo", `${repo}`); + + query.set("limit", "100"); + + const baseEndpoint = "prs/search"; + + const endpointString = `${baseEndpoint}?${query.toString()}`; + + const { data, error, mutate } = useSWR(repo ? endpointString : null); + + return { + data: data?.data ?? [], + isLoading: !data && !error, + isError: Object.keys(error ?? {}).length > 0, + meta: data?.meta ?? { itemCount: 0 }, + mutate, + }; }; -// good catch [] export { useContributorData }; diff --git a/pages/[owner]/[repo]/index.tsx b/pages/[owner]/[repo]/index.tsx index b81397e..d29544c 100644 --- a/pages/[owner]/[repo]/index.tsx +++ b/pages/[owner]/[repo]/index.tsx @@ -9,7 +9,8 @@ import { FaArrowTrendUp, FaArrowTrendDown } from "react-icons/fa6"; const CIResponsiveLine = dynamic(() => import("./CIResponsiveLine"), { ssr: false }); -import prCounts from "./prCounts"; +import prPerDay from "./prCounts"; +import { useContributorData } from "hooks/useContributorData"; export interface PaginatedDataResponse { readonly data: DBContributorsPR[]; @@ -24,19 +25,26 @@ interface StatsCardProps { } const ChildWithSWR = (props: { owner: string; repo: string }) => { const { owner, repo } = props; - const { data, error, mutate } = useSWR(`prs/search?repo=${owner}%2F${repo}`); + + const { data: openedPrs } = useContributorData(`${owner}/${repo}`, 0, "open"); + const { data: prevMonthOpenedPrs, meta: prevMonthOpenedPrsMeta } = useContributorData(`${owner}/${repo}`, 30, "open"); + + const { data: closedPrs } = useContributorData(`${owner}/${repo}`, 0, "closed"); + const { data: prevMonthClosedPrs, meta: prevMonthClosedPrsMeta } = useContributorData( + `${owner}/${repo}`, + 30, + "closed" + ); + + const { data: currentData, isError, isLoading, meta } = useContributorData(`${owner}/${repo}`); + // fetch previous months data seperately to compare - const { - data: prevMonthData, - error: prevMonthError, - mutate: prevMonthMutate, - } = useSWR(`prs/search?repo=${owner}%2F${repo}&prev_days_start_date=30`); - if (!data && !error) { + if (isLoading) { return <>Loading...; } - const chartData = prCounts(data!.data); + const chartData = prPerDay(openedPrs, closedPrs); const getPercentageChange = (prevCount: number, currentCount: number) => { const percentageChange = ((currentCount - prevCount) / prevCount) * 100; @@ -93,24 +101,24 @@ const ChildWithSWR = (props: { owner: string; repo: string }) => { pr.pr_is_merged === true).length} + prevMonthCount={prevMonthClosedPrs ? prevMonthClosedPrsMeta.itemCount : undefined} /> item.pr_state === "close" && !item.pr_is_merged).length} + prevMonthCount={prevMonthClosedPrsMeta ? prevMonthClosedPrsMeta.itemCount : undefined} /> - +
diff --git a/pages/[owner]/[repo]/prCounts.ts b/pages/[owner]/[repo]/prCounts.ts index bbdfe34..603afed 100644 --- a/pages/[owner]/[repo]/prCounts.ts +++ b/pages/[owner]/[repo]/prCounts.ts @@ -1,15 +1,3 @@ -import { PaginatedDataResponse } from "."; - -const prCounts = (prData: DBContributorsPR[]) => { - const meta = count(prData); - const prsPerDay = prPerDay(prData); - - return { - meta, - prsPerDay, - }; -}; - const count = (prData: DBContributorsPR[]): { mergedCount: number; closedCount: number; totalCount: number } => { const mergedCount = prData.filter((item) => item.pr_is_merged).length; // Merged PRs const closedCount = prData.filter((item) => item.pr_state === "closed").length; // Closed PRs @@ -23,17 +11,24 @@ const count = (prData: DBContributorsPR[]): { mergedCount: number; closedCount: }; }; -const prPerDay = (prData: DBContributorsPR[]) => { - const sortedPRs = prData.sort((a, b) => { +const prPerDay = (open: DBContributorsPR[], closed: DBContributorsPR[]) => { + const sortedMergedPRs = closed.sort((a, b) => { + const aDate = new Date(a.pr_created_at); + const bDate = new Date(b.pr_created_at); + + return aDate.getTime() - bDate.getTime(); + }); + + const sortedOpenedPRs = open.sort((a, b) => { const aDate = new Date(a.pr_created_at); const bDate = new Date(b.pr_created_at); return aDate.getTime() - bDate.getTime(); }); - const mergedPRsPerDay = sortedPRs.reduce>((acc, item) => { + const mergedPRsPerDay = sortedMergedPRs.reduce>((acc, item) => { const mergedDate = new Date(item.pr_merged_at).toLocaleDateString(); - if (item.pr_is_merged && item.pr_merged_at !== "0001-01-01T00:00:00.000Z") { + if (item.pr_is_merged) { if (!acc[mergedDate]) { acc[mergedDate] = 0; } @@ -43,10 +38,10 @@ const prPerDay = (prData: DBContributorsPR[]) => { return acc; }, {}); - const closedPRsPerDay = sortedPRs.reduce>((acc, item) => { + const closedPRsPerDay = sortedMergedPRs.reduce>((acc, item) => { const closedDate = new Date(item.pr_updated_at).toLocaleDateString(); - if (item.pr_state === "closed") { + if (item.pr_is_merged === false) { if (!acc[closedDate]) { acc[closedDate] = 0; } @@ -56,15 +51,13 @@ const prPerDay = (prData: DBContributorsPR[]) => { return acc; }, {}); - const openedPRsPerDay = sortedPRs.reduce>((acc, item) => { + const openedPRsPerDay = sortedOpenedPRs.reduce>((acc, item) => { const openedDate = new Date(item.pr_created_at).toLocaleDateString(); - if (item.pr_state === "open") { - if (!acc[openedDate]) { - acc[openedDate] = 0; - } - acc[openedDate]++; + if (!acc[openedDate]) { + acc[openedDate] = 0; } + acc[openedDate]++; return acc; }, {}); @@ -74,8 +67,6 @@ const prPerDay = (prData: DBContributorsPR[]) => { const mergedPrs = Object.entries(mergedPRsPerDay).map(([x, y]) => ({ x, y })); - console.log("Merged PRs per day:", mergedPrs); - return [ { id: "Opened PRs", @@ -83,7 +74,7 @@ const prPerDay = (prData: DBContributorsPR[]) => { data: openedPRs, }, { - id: "Pull Requests", + id: "Merged PRs", color: "#f59e0b", data: mergedPrs, }, @@ -95,4 +86,4 @@ const prPerDay = (prData: DBContributorsPR[]) => { ]; }; -export default prCounts; +export default prPerDay;