diff --git a/components/Graphs/MetricCard.stories.tsx b/components/Graphs/MetricCard.stories.tsx deleted file mode 100644 index 007ba853ce..0000000000 --- a/components/Graphs/MetricCard.stories.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { Meta, StoryObj } from "@storybook/react"; -import MetricCard from "./MetricCard"; - -type MetricCardAndRepositoryArgs = React.ComponentProps & { repository: string }; -type Story = StoryObj; - -const meta: Meta = { - title: "Components/Graphs/MetricCard", - component: MetricCard, - args: { - range: 30, - isLoading: false, - }, -}; - -export default meta; - -export const StarMetricCard: Story = { - args: { - variant: "stars", - stats: [ - { bucket: "2024-03-31T00:00:00.000Z", star_count: 1 }, - { bucket: "2024-03-30T00:00:00.000Z", star_count: 2 }, - { bucket: "2024-03-29T00:00:00.000Z", star_count: 1 }, - { bucket: "2024-03-23T00:00:00.000Z", star_count: 1 }, - { bucket: "2024-03-19T00:00:00.000Z", star_count: 1 }, - { bucket: "2024-03-17T00:00:00.000Z", star_count: 2 }, - { bucket: "2024-03-14T00:00:00.000Z", star_count: 1 }, - { bucket: "2024-03-13T00:00:00.000Z", star_count: 3 }, - { bucket: "2024-03-12T00:00:00.000Z", star_count: 3 }, - { bucket: "2024-03-11T00:00:00.000Z", star_count: 1 }, - { bucket: "2024-03-06T00:00:00.000Z", star_count: 1 }, - ], - }, -}; - -export const ForkMetricCard = { - args: { - variant: "forks", - stats: [ - { bucket: "2024-03-28T00:00:00.000Z", forks_count: 1 }, - { bucket: "2024-03-23T00:00:00.000Z", forks_count: 2 }, - { bucket: "2024-03-22T00:00:00.000Z", forks_count: 1 }, - { bucket: "2024-03-14T00:00:00.000Z", forks_count: 1 }, - { bucket: "2024-03-13T00:00:00.000Z", forks_count: 1 }, - { bucket: "2024-03-11T00:00:00.000Z", forks_count: 1 }, - { bucket: "2024-03-07T00:00:00.000Z", forks_count: 1 }, - ], - }, -}; - -export const LoadingMetricCard = { - args: { - isLoading: true, - }, -}; diff --git a/components/Graphs/MetricCard.tsx b/components/Graphs/MetricCard.tsx deleted file mode 100644 index df8405d1d0..0000000000 --- a/components/Graphs/MetricCard.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import EChartsReact from "echarts-for-react"; -import { useMemo } from "react"; -import { StatsType } from "lib/hooks/api/useFetchMetricStats"; -import Card from "components/atoms/Card/card"; -import humanizeNumber from "lib/utils/humanizeNumber"; -import SkeletonWrapper from "components/atoms/SkeletonLoader/skeleton-wrapper"; - -type MetricCardProps = { - stats: StatsType[] | undefined; - variant: "stars" | "forks"; - range: 7 | 30 | 90; - isLoading: boolean; -}; - -export default function MetricCard({ stats, variant, range, isLoading }: MetricCardProps) { - const countProperty = variant === "stars" ? "star_count" : "forks_count"; - const seriesData = useMemo(() => stats?.map((stat) => stat[countProperty] ?? 0) ?? [], [countProperty, stats]); - const bucketData = useMemo(() => stats?.map((stat) => new Date(stat.bucket).toDateString()) ?? [], [stats]); - - const option = useMemo(() => { - return { - xAxis: { - type: "category", - data: bucketData, - show: false, - }, - yAxis: { - type: "value", - show: false, - }, - tooltip: { - trigger: "axis", - axisPointer: { - type: "shadow", - }, - }, - series: [ - { - data: seriesData, - symbol: "none", - type: variant === "stars" ? "line" : "bar", - }, - ], - color: "hsla(19, 100%, 50%, 1)", - }; - }, [bucketData, seriesData, variant]); - - const total = useMemo( - () => seriesData?.reduce((stat, currentValue) => (stat || 0) + (currentValue || 0), 0), - [seriesData] - ); - - return ( - -

- {variant}{" "} - {isLoading ? ( - - - - ) : ( - {range} days - )} -

- - {isLoading ? ( - - ) : ( -
-

{humanizeNumber(total!, "abbreviation")}

-
- -
-
- )} -
- ); -} diff --git a/components/Workspaces/RepositoryStatCard.tsx b/components/Workspaces/RepositoryStatCard.tsx index 121a428308..f1728ff69d 100644 --- a/components/Workspaces/RepositoryStatCard.tsx +++ b/components/Workspaces/RepositoryStatCard.tsx @@ -1,5 +1,8 @@ +import { FaStar } from "react-icons/fa6"; +import { BiGitRepoForked } from "react-icons/bi"; import { ArrowTrendingDownIcon, ArrowTrendingUpIcon, MinusSmallIcon } from "@heroicons/react/24/solid"; import { GitPullRequestIcon, HeartIcon, IssueOpenedIcon } from "@primer/octicons-react"; + import Card from "components/atoms/Card/card"; import Pill from "components/atoms/Pill/pill"; import SkeletonWrapper from "components/atoms/SkeletonLoader/skeleton-wrapper"; @@ -21,12 +24,22 @@ type RepositoryStatCardProps = { type: "engagement"; stats: { stars: number; forks: number; activity_ratio: number } | undefined; } + | { + type: "stars"; + stats: { total: number; range: number; over_range: number; average_over_range: number } | undefined; + } + | { + type: "forks"; + stats: { total: number; range: number; over_range: number; average_over_range: number } | undefined; + } ); const titles = { pulls: "Pull Requests", issues: "Issues", engagement: "Engagement", + stars: "Stars", + forks: "Forks", } as const; type CardType = RepositoryStatCardProps["type"]; @@ -39,6 +52,10 @@ function getIcon(type: CardType) { return ; case "engagement": return ; + case "stars": + return ; + case "forks": + return ; } } @@ -50,6 +67,9 @@ function getStatPropertiesByType(type: CardType) { return ["opened", "closed", "velocity"]; case "engagement": return ["stars", "forks", "activity_ratio"]; + case "forks": + case "stars": + return ["total", "over_range", "average_over_range"]; default: throw new Error("Invalid repository stat card type"); } @@ -123,8 +143,14 @@ export const RepositoryStatCard = ({ stats, type, isLoading, hasError }: Reposit .map(([stat, value]) => { return ( - - {stat.replace("_", " ")} + + {type === "stars" || type === "forks" + ? stat === "over_range" + ? `Over ${stats.range} Days` + : stat === "average_over_range" + ? `Avg. per day` + : stat.replace("_", " ") + : stat.replace("_", " ")} ["range"]; +type Range = 30 | 7 | 90 | 180 | 360; interface RepoPageProps { repoData: DbRepo; @@ -82,6 +81,9 @@ export default function RepoPage({ repoData, image, ogImageUrl }: RepoPageProps) range, }); + const starsRangedTotal = starsData?.reduce((prev, curr) => prev + curr.star_count!, 0); + const forksRangedTotal = forkStats?.reduce((prev, curr) => prev + curr.forks_count!, 0); + const copyUrlToClipboard = async () => { const url = new URL(window.location.href).toString(); posthog!.capture(`clicked: ${repoData.full_name} repo page share`); @@ -128,26 +130,46 @@ export default function RepoPage({ repoData, image, ogImageUrl }: RepoPageProps) -
- - - - -
- - + +
+ + +
+ + +