66 lines
2.0 KiB
React
66 lines
2.0 KiB
React
|
|
/**
|
||
|
|
* Reusable Heat Badges component
|
||
|
|
* Displays competition heats with compact notation (e.g., "J&J NOV 1 L")
|
||
|
|
*
|
||
|
|
* @param {Array} heats - Array of heat objects with { competitionType, division, heatNumber, role }
|
||
|
|
* @param {number} maxVisible - Maximum number of badges to show before "+X more" (default: 3)
|
||
|
|
* @param {boolean} compact - Use compact display (default: true)
|
||
|
|
* @param {string} className - Additional CSS classes for container
|
||
|
|
*
|
||
|
|
* @example
|
||
|
|
* <HeatBadges heats={userHeats} maxVisible={3} />
|
||
|
|
* // Renders: "J&J NOV 1 L" "STR INT 2 F" "+2"
|
||
|
|
*/
|
||
|
|
const HeatBadges = ({
|
||
|
|
heats = [],
|
||
|
|
maxVisible = 3,
|
||
|
|
compact = true,
|
||
|
|
className = ''
|
||
|
|
}) => {
|
||
|
|
if (!heats || heats.length === 0) return null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Format heat object into compact notation
|
||
|
|
* Example: { competitionType: 'Jack & Jill', division: 'Novice', heatNumber: 1, role: 'Leader' }
|
||
|
|
* Returns: "J&J NOV 1 L"
|
||
|
|
*/
|
||
|
|
const formatHeat = (heat) => {
|
||
|
|
const parts = [
|
||
|
|
heat.competitionType?.abbreviation || '',
|
||
|
|
heat.division?.abbreviation || '',
|
||
|
|
heat.heatNumber,
|
||
|
|
];
|
||
|
|
if (heat.role) {
|
||
|
|
parts.push(heat.role.charAt(0)); // L or F
|
||
|
|
}
|
||
|
|
return parts.join(' ');
|
||
|
|
};
|
||
|
|
|
||
|
|
const visibleHeats = heats.slice(0, maxVisible);
|
||
|
|
const remainingCount = heats.length - maxVisible;
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className={`flex flex-wrap gap-1 ${className}`}>
|
||
|
|
{visibleHeats.map((heat, idx) => (
|
||
|
|
<span
|
||
|
|
key={idx}
|
||
|
|
className="text-xs px-1.5 py-0.5 bg-amber-100 text-amber-800 rounded font-mono"
|
||
|
|
title={`${heat.competitionType?.name || ''} ${heat.division?.name || ''} Heat ${heat.heatNumber} (${heat.role || ''})`}
|
||
|
|
>
|
||
|
|
{formatHeat(heat)}
|
||
|
|
</span>
|
||
|
|
))}
|
||
|
|
{remainingCount > 0 && (
|
||
|
|
<span
|
||
|
|
className="text-xs px-1.5 py-0.5 bg-gray-200 text-gray-700 rounded font-mono"
|
||
|
|
title={`${remainingCount} more heat${remainingCount > 1 ? 's' : ''}`}
|
||
|
|
>
|
||
|
|
+{remainingCount}
|
||
|
|
</span>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default HeatBadges;
|