import React, { useState, useMemo } from "react"; import { Input } from "./ui/input"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, } from "./ui/dialog"; import { Button } from "./ui/button"; import { fetchAllAuthorsData, fetchOrganizationData } from "../utils/authors"; import { generateCalendarData } from "../utils/calendar"; import Heatmap from "./Heatmap"; import { ModelData } from "../types/heatmap"; import { LEADERBOARD_SIZE } from "../constants/organizations"; interface UserSearchDialogProps { candidateAuthors: string[]; minActivityCount: number; } const UserSearchDialog: React.FC = ({ candidateAuthors, minActivityCount, }) => { const [isOpen, setIsOpen] = useState(false); const [isLoading, setIsLoading] = useState(false); const [searchInput, setSearchInput] = useState(""); const [searchedData, setSearchedData] = useState(null); const [isCopied, setIsCopied] = useState(false); const [currentSearchTerm, setCurrentSearchTerm] = useState(""); const [userInfo, setUserInfo] = useState<{ fullName: string; avatarUrl: string | null; } | null>(null); const handleSearch = async () => { if (searchInput.trim()) { setIsLoading(true); try { const authorInfo = await fetchOrganizationData([searchInput.trim()]); const resolvedName = authorInfo.authorsData?.[0]?.author || searchInput.trim(); const authorData = await fetchAllAuthorsData([resolvedName]); setSearchedData(authorData); setUserInfo(authorInfo); setCurrentSearchTerm(resolvedName); } catch (error) { console.error("Error fetching data for searched user:", error); setSearchedData(null); setUserInfo(null); setCurrentSearchTerm(""); } setIsLoading(false); } else { setSearchedData(null); setUserInfo(null); setCurrentSearchTerm(""); } }; const handleKeyPress = (e: React.KeyboardEvent) => { if (e.key === "Enter") { handleSearch(); } }; const handleInputChange = (e: React.ChangeEvent) => { setSearchInput(e.target.value); }; const getIframeCode = (username: string) => { return ``; }; const handleCopyCode = () => { const iframeCode = getIframeCode(searchInput); navigator.clipboard.writeText(iframeCode).then(() => { setIsCopied(true); setTimeout(() => setIsCopied(false), 2000); }); }; const searchedHeatmapData = useMemo(() => { if (searchedData && searchedData.length > 0 && userInfo) { return generateCalendarData(searchedData, [ { authors: [currentSearchTerm], color: "#0088cc", fullName: userInfo.fullName, avatarUrl: userInfo.avatarUrl, }, ])[currentSearchTerm]; } return null; }, [searchedData, currentSearchTerm, userInfo]); const suggestionBanner = useMemo(() => { if (!searchedHeatmapData || !currentSearchTerm) return null; const isTracked = candidateAuthors.some( (a) => a.toLowerCase() === currentSearchTerm.toLowerCase() ); if (isTracked) return null; const totalActivity = searchedHeatmapData.reduce( (sum, day) => sum + day.count, 0 ); if (totalActivity < minActivityCount) return null; const title = encodeURIComponent( `Add ${currentSearchTerm} to tracked organizations` ); const description = encodeURIComponent( `${currentSearchTerm} has ${totalActivity} new repos in the last year and qualifies for the top 16.` ); const url = `https://huggingface.co/spaces/v1an1/model-release-heatmap/discussions/new?title=${title}&description=${description}`; return { totalActivity, url }; }, [searchedHeatmapData, currentSearchTerm, candidateAuthors, minActivityCount]); const handleDialogOpenChange = (open: boolean) => { setIsOpen(open); if (!open) { setSearchInput(""); setSearchedData(null); setCurrentSearchTerm(""); setIsLoading(false); setIsCopied(false); setUserInfo(null); } }; return ( Get your Hugging Face Heatmap
{isLoading ? (

Loading...

) : searchedHeatmapData && userInfo ? (
{suggestionBanner && (

{currentSearchTerm} has{" "} {suggestionBanner.totalActivity} repos this year and qualifies for the top {LEADERBOARD_SIZE}!

Request to add →
)}

Embed in iFrame

                      {getIframeCode(searchInput)}
                    
) : searchedData !== null && searchedData.length === 0 ? (

User or Organization not found

) : null}
); }; export default UserSearchDialog;