53 lines
1.2 KiB
TypeScript
53 lines
1.2 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { Trophy } from "lucide-react";
|
|
import { cn } from "~/lib/utils";
|
|
import { resolveSportIconUrl } from "~/lib/sport-icon-url";
|
|
|
|
interface SportIconProps {
|
|
sportName: string;
|
|
iconUrl?: string | null;
|
|
size?: "sm" | "md" | "lg" | "xl";
|
|
className?: string;
|
|
decorative?: boolean;
|
|
}
|
|
|
|
const sizeClasses = {
|
|
sm: "h-5 w-5",
|
|
md: "h-8 w-8",
|
|
lg: "h-12 w-12",
|
|
xl: "h-16 w-16",
|
|
};
|
|
|
|
export function SportIcon({
|
|
sportName,
|
|
iconUrl,
|
|
size = "md",
|
|
className,
|
|
decorative = false,
|
|
}: SportIconProps) {
|
|
const [failed, setFailed] = useState(false);
|
|
const resolvedIconUrl = resolveSportIconUrl(iconUrl);
|
|
|
|
useEffect(() => {
|
|
setFailed(false);
|
|
}, [resolvedIconUrl]);
|
|
|
|
if (resolvedIconUrl && !failed) {
|
|
return (
|
|
<img
|
|
src={resolvedIconUrl}
|
|
alt={decorative ? "" : sportName}
|
|
className={cn(sizeClasses[size], "shrink-0 object-contain", className)}
|
|
onError={() => setFailed(true)}
|
|
/>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Trophy
|
|
aria-hidden={decorative}
|
|
aria-label={decorative ? undefined : sportName}
|
|
className={cn(sizeClasses[size], "shrink-0 text-muted-foreground", className)}
|
|
/>
|
|
);
|
|
}
|