org-activity-heatmap / src /components /OrganizationHeader.tsx
cfahlgren1's picture
cfahlgren1 HF Staff
refactor, rename things a bit
6ee3edd
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 flex-wrap justify-center">
{provider.authorsData.map((authorData, index) => (
<React.Fragment key={authorData.author}>
{index > 0 && (
<span className="text-muted-foreground text-sm font-medium mx-1">+</span>
)}
<div className="flex items-center gap-1">
<div className="relative">
<img
src={authorData.avatarUrl || `https://huggingface.co/${authorData.author}/avatar.jpg`}
alt={`${authorData.fullName} logo`}
className="w-8 h-8 rounded-md shadow-sm border border-border/50"
onError={(e) => {
const target = e.target as HTMLImageElement;
target.src = `https://ui-avatars.com/api/?name=${encodeURIComponent(authorData.fullName)}&background=random`;
}}
/>
{authorData.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>
<span className="text-base font-bold text-foreground">
<a
href={`https://huggingface.co/${authorData.author}`}
target="_blank"
rel="noopener noreferrer"
className="hover:text-blue-500 hover:underline transition-colors duration-200"
>
{authorData.author}
</a>
</span>
</div>
</React.Fragment>
))}
</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;