"use client"; import { cn } from "@/lib/utils"; import Link from "next/link"; import { useEffect, useState } from "react"; type GithubStarsProps = { className?: string; repoUrl?: string; label?: string; count?: string; }; // Function to format star count (e.g., 26400 -> "26.4k") function formatStarCount(count: number): string { if (count >= 1000000) { return `${(count / 1000000).toFixed(1)}M`; } if (count >= 1000) { return `${(count / 1000).toFixed(1)}k`; } return count.toString(); } // Extract owner and repo from GitHub URL function extractRepoInfo(url: string): { owner: string; repo: string } | null { try { const match = url.match(/github\.com\/([^\/]+)\/([^\/]+)/); if (match) { return { owner: match[1], repo: match[2].replace(/\.git$/, "") }; } } catch (error) { console.error("Error extracting repo info:", error); } return null; } export function GithubStars({ className, repoUrl = "https://github.com/dokploy/dokploy", label = "GitHub Stars", count: defaultCount = "26.4k", }: GithubStarsProps) { const [starCount, setStarCount] = useState(defaultCount); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const fetchStarCount = async () => { const repoInfo = extractRepoInfo(repoUrl); if (!repoInfo) { setIsLoading(false); return; } try { const response = await fetch( `/api/github-stars?owner=${encodeURIComponent(repoInfo.owner)}&repo=${encodeURIComponent(repoInfo.repo)}`, ); if (response.ok) { const data = await response.json(); const formattedCount = formatStarCount(data.stargazers_count); setStarCount(formattedCount); } } catch (error) { console.error("Error fetching GitHub stars:", error); // Keep default count on error } finally { setIsLoading(false); } }; fetchStarCount(); }, [repoUrl]); return ( {/* sparkling stars */} {/* top-left star */} {/* top-right star */} {/* bottom-right star */} {/* subtle shine */} {/* GitHub mark */} {/* copy */} Stars {isLoading ? "..." : starCount} {/* subtle ring on hover */} ); } export default GithubStars;