| import React from "react"; | |
| import { ProviderInfo, CalendarData } from "../types/heatmap"; | |
| import OrganizationCard from "./OrganizationCard"; | |
| import ProviderHeatmapSkeleton from "./ProviderHeatmapSkeleton"; | |
| interface HeatmapGridProps { | |
| sortedProviders: ProviderInfo[]; | |
| calendarData: CalendarData; | |
| isLoading: boolean; | |
| highlightedAuthors?: Set<string>; | |
| } | |
| const HeatmapGrid: React.FC<HeatmapGridProps> = ({ | |
| sortedProviders, | |
| calendarData, | |
| isLoading, | |
| highlightedAuthors, | |
| }) => { | |
| if (isLoading) { | |
| return ( | |
| <div className="flex flex-col gap-8 max-w-4xl mx-auto mb-16"> | |
| {Array.from({ length: 3 }).map((_, idx) => ( | |
| <ProviderHeatmapSkeleton key={idx} /> | |
| ))} | |
| </div> | |
| ); | |
| } | |
| return ( | |
| <div className="flex flex-col gap-8 max-w-4xl mx-auto mb-16"> | |
| {sortedProviders.map((provider, index) => { | |
| const isHighlighted = highlightedAuthors | |
| ? provider.authors.some((a) => highlightedAuthors.has(a)) | |
| : false; | |
| return ( | |
| <div | |
| key={provider.fullName || provider.authors[0]} | |
| className={`relative rounded-2xl transition-all duration-300 ${ | |
| isHighlighted | |
| ? "ring-2 ring-amber-400/60 dark:ring-amber-500/40 shadow-[0_0_20px_rgba(251,191,36,0.15)]" | |
| : "" | |
| }`} | |
| > | |
| {/* ⭐ Our Team 배지 */} | |
| {isHighlighted && ( | |
| <div className="absolute -top-3 -right-3 z-10"> | |
| <span className="inline-flex items-center gap-1 px-3 py-1 rounded-full text-xs font-bold bg-gradient-to-r from-amber-400 via-yellow-400 to-orange-400 text-white shadow-lg shadow-amber-400/30 border border-amber-300/50"> | |
| ⭐ Our Team | |
| </span> | |
| </div> | |
| )} | |
| <OrganizationCard | |
| provider={provider} | |
| calendarData={calendarData} | |
| rank={index + 1} | |
| /> | |
| </div> | |
| ); | |
| })} | |
| </div> | |
| ); | |
| }; | |
| export default HeatmapGrid; |