import { type HeatmapCell } from "@/src/features/score-analytics/lib/heatmap-utils"; import { getContrastColor } from "@/src/features/score-analytics/lib/color-scales"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/src/components/ui/tooltip"; import { cn } from "@/src/utils/tailwind"; import { useState } from "react"; interface HeatmapCellProps { cell?: HeatmapCell; color?: string; // Color for the cell (computed by parent) onHover?: (cell: HeatmapCell | null) => void; onClick?: (cell: HeatmapCell) => void; renderTooltip?: (cell: HeatmapCell) => React.ReactNode; cellClassName?: string; showValues?: boolean; } interface CellWithDataProps { cell: HeatmapCell; color?: string; onHover?: (cell: HeatmapCell | null) => void; onClick?: (cell: HeatmapCell) => void; renderTooltip?: (cell: HeatmapCell) => React.ReactNode; cellClassName?: string; showValues: boolean; } /** * Empty cell component (no data) */ function EmptyCell({ cellClassName }: { cellClassName?: string }) { return (
); } /** * Cell with data component */ function CellWithData({ cell, color, onHover, onClick, renderTooltip, cellClassName, showValues, }: CellWithDataProps) { const [isHovered, setIsHovered] = useState(false); // Determine if cell is empty (value = 0) const isEmpty = cell.value === 0; const hasInteraction = onClick !== undefined; // Use color from parent, fallback to transparent for empty cells const cellColor = color || "transparent"; const textColor = isEmpty ? "hsl(var(--muted-foreground))" : getContrastColor(cellColor); const sharedClassName = cn( "h-full w-full rounded-sm border-[0.5px]", "flex items-center justify-center", "text-xs font-medium", "transition-all duration-150", "whitespace-pre-line text-center leading-tight", hasInteraction && "cursor-pointer", !hasInteraction && "cursor-default", // Apply CSS filters based on hover state and whether cell is empty isEmpty && isHovered && "brightness-95", !isEmpty && isHovered && "brightness-75 saturate-[3]", cellClassName, ); const sharedStyle = { backgroundColor: isEmpty ? "hsl(var(--background))" : cellColor, borderColor: isEmpty ? "hsl(var(--border) / 0.34)" // Transparent border for empty cells : cellColor, // Border matches fill for filled cells color: textColor === "white" ? "white" : "black", }; const handleMouseEnter = () => { setIsHovered(true); onHover?.(cell); }; const handleMouseLeave = () => { setIsHovered(false); onHover?.(null); }; const cellContent = hasInteraction ? ( ) : (