mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-05 03:02:56 +00:00
upload
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Image, ImageProps, Skeleton } from '@chakra-ui/react';
|
||||
import { getTeamLogo } from '../../utils/sportLogosAPI';
|
||||
import { getLogoStyle, getLogoClassName } from '../../utils/logoUtils';
|
||||
import '../../styles/logos.css';
|
||||
|
||||
interface TeamLogoProps extends Omit<ImageProps, 'src'> {
|
||||
teamId?: string;
|
||||
teamName?: string;
|
||||
facrLogo?: string;
|
||||
size?: 'small' | 'medium' | 'large' | 'custom';
|
||||
fallbackIcon?: React.ReactElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* TeamLogo component with automatic logoapi.sportcreative.eu integration
|
||||
* Features:
|
||||
* - Fetches from logoapi first (with local caching)
|
||||
* - Falls back to FACR logo if logoapi doesn't have it
|
||||
* - Properly centers and formats logos
|
||||
* - Handles SVG optimization
|
||||
*/
|
||||
export const TeamLogo: React.FC<TeamLogoProps> = ({
|
||||
teamId,
|
||||
teamName,
|
||||
facrLogo,
|
||||
size = 'medium',
|
||||
fallbackIcon,
|
||||
alt,
|
||||
...imageProps
|
||||
}) => {
|
||||
const [logoUrl, setLogoUrl] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let mounted = true;
|
||||
|
||||
const fetchLogo = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError(false);
|
||||
|
||||
const url = await getTeamLogo(teamId, teamName, facrLogo);
|
||||
|
||||
if (mounted) {
|
||||
setLogoUrl(url);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to fetch logo:', e);
|
||||
if (mounted) {
|
||||
setError(true);
|
||||
// Fallback to FACR or placeholder
|
||||
setLogoUrl(facrLogo || '/logo192.png');
|
||||
}
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fetchLogo();
|
||||
|
||||
return () => {
|
||||
mounted = false;
|
||||
};
|
||||
}, [teamId, teamName, facrLogo]);
|
||||
|
||||
// Size mapping
|
||||
const sizeMap = {
|
||||
small: { boxSize: '24px' },
|
||||
medium: { boxSize: '32px' },
|
||||
large: { boxSize: '48px' },
|
||||
custom: {},
|
||||
};
|
||||
|
||||
const sizeProps = size !== 'custom' ? sizeMap[size] : {};
|
||||
|
||||
// Class name based on size
|
||||
const className = `match-logo-${size} ${imageProps.className || ''}`.trim();
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Skeleton
|
||||
{...sizeProps}
|
||||
borderRadius="4px"
|
||||
className="logo-loading"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// Check if this is a circular container
|
||||
const isCircular = imageProps.borderRadius === 'full' || imageProps.style?.borderRadius === '50%';
|
||||
|
||||
// Get appropriate styling and className using utility functions
|
||||
// Only pass size to utils if it's not 'custom' (utils only accept standard sizes)
|
||||
const utilSize = size !== 'custom' ? size : 'medium';
|
||||
const logoStyle = getLogoStyle(logoUrl, isCircular, utilSize);
|
||||
const logoClassName = getLogoClassName(logoUrl, isCircular, utilSize);
|
||||
|
||||
return (
|
||||
<Image
|
||||
src={logoUrl || '/logo192.png'}
|
||||
alt={alt || teamName || 'Team logo'}
|
||||
{...sizeProps}
|
||||
{...imageProps}
|
||||
className={`${className} ${logoClassName}`}
|
||||
objectFit="contain"
|
||||
loading="lazy"
|
||||
fallback={fallbackIcon}
|
||||
style={{
|
||||
...imageProps.style,
|
||||
...logoStyle
|
||||
}}
|
||||
onError={() => {
|
||||
if (!error) {
|
||||
setError(true);
|
||||
setLogoUrl(facrLogo || '/logo192.png');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default TeamLogo;
|
||||
Reference in New Issue
Block a user