Heatmap-Leaderboard / src /components /OrganizationHeader.tsx
ginigen-ai's picture
card: single VIDraft name with stacked avatar group; drop JGOS-Model and Powergen-AI
c60c951 verified
Raw
History Blame
10.1 kB
import React from "react";
import { ProviderInfo } from "../types/heatmap";
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip";
interface OrganizationHeaderProps {
provider: ProviderInfo;
calendarKey: string;
providerName: string;
totalCount: number;
}
const OrganizationHeader: React.FC<OrganizationHeaderProps> = ({
provider,
calendarKey,
providerName,
totalCount,
}) => {
return (
<TooltipProvider>
<div className="mb-4">
{/* Organization Name & Stats Badge */}
<div className="text-center bg-muted/20 rounded-lg p-3 border border-border/30">
{/* Avatar and Name Row */}
<div className="flex items-center justify-center gap-2 mb-2">
{/* Multi-author avatars and names */}
{provider.authorsData && provider.authorsData.length > 1 ? (
<div className="flex items-center gap-2 justify-center">
{/* 아이콘만 겹쳐서 그룹화 — 이름은 대표(첫 번째)만 표시 */}
<div className="flex items-center" title={provider.authorsData.map(a => a.author).join(" · ")}>
{provider.authorsData.slice(0, 6).map((authorData, index) => (
<img
key={authorData.author}
src={authorData.avatarUrl || `https://huggingface.co/${authorData.author}/avatar.jpg`}
alt={`${authorData.fullName} logo`}
title={authorData.author}
className="w-7 h-7 rounded-md shadow-sm border-2 border-background bg-background"
style={{ marginLeft: index === 0 ? 0 : -8, zIndex: 10 - index }}
onError={(e) => {
const target = e.target as HTMLImageElement;
target.src = `https://ui-avatars.com/api/?name=${encodeURIComponent(authorData.fullName)}&background=random`;
}}
/>
))}
{provider.authorsData.length > 6 && (
<span
className="ml-1 text-[11px] font-bold text-muted-foreground bg-muted rounded px-1.5 py-0.5 border border-border/50"
title={provider.authorsData.slice(6).map(a => a.author).join(" · ")}
>
+{provider.authorsData.length - 6}
</span>
)}
</div>
<h3 className="text-base font-bold text-foreground">
<a
href={`https://huggingface.co/${provider.authorsData[0].author}`}
target="_blank"
rel="noopener noreferrer"
className="hover:text-blue-500 hover:underline transition-colors duration-200"
>
{provider.authorsData[0].author}
</a>
</h3>
</div>
) : (
<div className="flex items-center gap-2">
{provider.avatarUrl && (
<div className="relative">
<img
src={provider.avatarUrl}
alt={`${providerName} logo`}
className="w-8 h-8 rounded-md shadow-sm border border-border/50"
/>
{provider.isVerified && (
<div className="absolute -bottom-0.5 -right-0.5 w-3 h-3 bg-blue-500 rounded-full flex items-center justify-center">
<svg className="w-2 h-2 text-white" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
</svg>
</div>
)}
</div>
)}
<h3 className="text-base font-bold text-foreground">
<a
href={`https://huggingface.co/${calendarKey}`}
target="_blank"
rel="noopener noreferrer"
className="hover:text-blue-500 hover:underline transition-colors duration-200"
>
{providerName}
</a>
</h3>
</div>
)}
</div>
{/* Compact Organization Stats */}
<div className="flex flex-wrap justify-center gap-2 text-xs mb-3">
{provider.authorsData && provider.authorsData.length > 1 ? (
<Tooltip>
<TooltipTrigger asChild>
<div className="bg-background/60 rounded px-2 py-1 border border-border/40 cursor-pointer">
<span className="font-semibold text-foreground">{(provider.numModels || 0).toLocaleString()}</span>
<span className="text-muted-foreground ml-1">models</span>
</div>
</TooltipTrigger>
<TooltipContent side="bottom">
<div className="text-xs">
{provider.authorsData.map(author => (
<div key={`models-${author.author}`}>
{author.author}: {author.numModels.toLocaleString()}
</div>
))}
</div>
</TooltipContent>
</Tooltip>
) : (
<div className="bg-background/60 rounded px-2 py-1 border border-border/40">
<span className="font-semibold text-foreground">{(provider.numModels || 0).toLocaleString()}</span>
<span className="text-muted-foreground ml-1">models</span>
</div>
)}
{provider.authorsData && provider.authorsData.length > 1 ? (
<Tooltip>
<TooltipTrigger asChild>
<div className="bg-background/60 rounded px-2 py-1 border border-border/40 cursor-pointer">
<span className="font-semibold text-foreground">{(provider.numDatasets || 0).toLocaleString()}</span>
<span className="text-muted-foreground ml-1">datasets</span>
</div>
</TooltipTrigger>
<TooltipContent side="bottom">
<div className="text-xs">
{provider.authorsData.map(author => (
<div key={`datasets-${author.author}`}>
{author.author}: {author.numDatasets.toLocaleString()}
</div>
))}
</div>
</TooltipContent>
</Tooltip>
) : (
<div className="bg-background/60 rounded px-2 py-1 border border-border/40">
<span className="font-semibold text-foreground">{(provider.numDatasets || 0).toLocaleString()}</span>
<span className="text-muted-foreground ml-1">datasets</span>
</div>
)}
{provider.authorsData && provider.authorsData.length > 1 ? (
<Tooltip>
<TooltipTrigger asChild>
<div className="bg-background/60 rounded px-2 py-1 border border-border/40 cursor-pointer">
<span className="font-semibold text-foreground">{(provider.numSpaces || 0).toLocaleString()}</span>
<span className="text-muted-foreground ml-1">spaces</span>
</div>
</TooltipTrigger>
<TooltipContent side="bottom">
<div className="text-xs">
{provider.authorsData.map(author => (
<div key={`spaces-${author.author}`}>
{author.author}: {author.numSpaces.toLocaleString()}
</div>
))}
</div>
</TooltipContent>
</Tooltip>
) : (
<div className="bg-background/60 rounded px-2 py-1 border border-border/40">
<span className="font-semibold text-foreground">{(provider.numSpaces || 0).toLocaleString()}</span>
<span className="text-muted-foreground ml-1">spaces</span>
</div>
)}
{provider.authorsData && provider.authorsData.length > 1 ? (
<Tooltip>
<TooltipTrigger asChild>
<div className="bg-background/60 rounded px-2 py-1 border border-border/40 cursor-pointer">
<span className="font-semibold text-foreground">{(provider.numFollowers || 0).toLocaleString()}</span>
<span className="text-muted-foreground ml-1">followers</span>
</div>
</TooltipTrigger>
<TooltipContent side="bottom">
<div className="text-xs">
{provider.authorsData.map(author => (
<div key={`followers-${author.author}`}>
{author.author}: {author.numFollowers.toLocaleString()}
</div>
))}
</div>
</TooltipContent>
</Tooltip>
) : (
<div className="bg-background/60 rounded px-2 py-1 border border-border/40">
<span className="font-semibold text-foreground">{(provider.numFollowers || 0).toLocaleString()}</span>
<span className="text-muted-foreground ml-1">followers</span>
</div>
)}
</div>
</div>
</div>
</TooltipProvider>
);
};
export default OrganizationHeader;