mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-05 03:02:56 +00:00
dev day #79
This commit is contained in:
@@ -9,9 +9,11 @@ import { assetUrl } from '../../utils/url';
|
||||
let __teamOverridesCache: { ts: number; data: { by_id?: Record<string, { name?: string; logo_url?: string }>; by_name?: Record<string, string> } } | null = null;
|
||||
const loadTeamOverrides = async (): Promise<{ by_id?: Record<string, { name?: string; logo_url?: string }>; by_name?: Record<string, string> }> => {
|
||||
const now = Date.now();
|
||||
if (__teamOverridesCache && now - __teamOverridesCache.ts < 60_000) {
|
||||
const TTL = 5_000;
|
||||
if (__teamOverridesCache && now - __teamOverridesCache.ts < TTL) {
|
||||
return __teamOverridesCache.data || {};
|
||||
}
|
||||
// Try fresh public endpoint first
|
||||
try {
|
||||
const res = await fetch(`/api/v1/public/team-logo-overrides?t=${now}`, { cache: 'no-cache' });
|
||||
if (res.ok) {
|
||||
@@ -20,6 +22,7 @@ const loadTeamOverrides = async (): Promise<{ by_id?: Record<string, { name?: st
|
||||
return json || {};
|
||||
}
|
||||
} catch {}
|
||||
// Fallback to static cache snapshot
|
||||
try {
|
||||
const res2 = await fetch('/cache/prefetch/team_logo_overrides.json', { cache: 'no-cache' });
|
||||
if (res2.ok) {
|
||||
@@ -28,10 +31,45 @@ const loadTeamOverrides = async (): Promise<{ by_id?: Record<string, { name?: st
|
||||
return json || {};
|
||||
}
|
||||
} catch {}
|
||||
// Final fallback: previously cached data or empty
|
||||
if (__teamOverridesCache) return __teamOverridesCache.data || {};
|
||||
__teamOverridesCache = { ts: now, data: {} };
|
||||
return {};
|
||||
};
|
||||
|
||||
// Normalization helpers for name-based matching
|
||||
const __normalize = (s?: string) => {
|
||||
let out = String(s || '');
|
||||
out = out
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.toLowerCase();
|
||||
out = out.replace(/[\u2012\u2013\u2014\u2015\u2212]/g, '-');
|
||||
out = out.replace(/\bn\.?\b/g, ' nad ');
|
||||
out = out.replace(/\bp\.?\b/g, ' pod ');
|
||||
out = out.replace(/[.,!;:()\[\]{}]/g, ' ');
|
||||
// Remove legal suffixes often appended to Czech organizations
|
||||
out = out.replace(/[\s,]*(z\.?\s*s\.?|o\.?\s*s\.?)\s*$/g, '');
|
||||
// Remove common organization phrases
|
||||
const orgPhrases = [
|
||||
'fotbalovy klub',
|
||||
'sportovni klub',
|
||||
'telovychovna jednota',
|
||||
'skolni sportovni klub',
|
||||
'spolek',
|
||||
'fotbal',
|
||||
'futsal',
|
||||
];
|
||||
for (const phrase of orgPhrases) {
|
||||
const re = new RegExp('(^|\\b)'+ phrase + '(\\b|$)', 'g');
|
||||
out = out.replace(re, ' ');
|
||||
}
|
||||
// Remove common short prefixes/tokens (FK, FC, MFK, TJ, SK, SFC, AFK, BFK, HFK, etc.)
|
||||
out = out.replace(/\b(1\.)?\s*(sfc|afc|fc|fk|mfk|tj|sk|afk|bfk|hfk)\b\.?/g, ' ');
|
||||
out = out.replace(/\s+/g, ' ').trim();
|
||||
return out;
|
||||
};
|
||||
|
||||
interface TeamLogoProps extends Omit<ImageProps, 'src'> {
|
||||
teamId?: string;
|
||||
teamName?: string;
|
||||
@@ -70,7 +108,7 @@ export const TeamLogo: React.FC<TeamLogoProps> = ({
|
||||
setLoading(true);
|
||||
setError(false);
|
||||
// Load admin overrides (cached)
|
||||
let overrides: { by_id?: Record<string, { name?: string; logo_url?: string }> } = {};
|
||||
let overrides: { by_id?: Record<string, { name?: string; logo_url?: string }>; by_name?: Record<string, string> } = {} as any;
|
||||
try { overrides = await loadTeamOverrides(); } catch {}
|
||||
// Prefer local club logo for own team when IDs match
|
||||
if (
|
||||
@@ -89,9 +127,49 @@ export const TeamLogo: React.FC<TeamLogoProps> = ({
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const url = await getTeamLogo(teamId, teamName, facrLogo);
|
||||
if (mounted) {
|
||||
setLogoUrl(url);
|
||||
// Try name-based override first if ID override not found
|
||||
let appliedByName = false;
|
||||
try {
|
||||
const byName: Record<string, string> = (overrides as any)?.by_name || {};
|
||||
if (teamName && byName && Object.keys(byName).length > 0) {
|
||||
const normMap: Record<string, string> = {};
|
||||
for (const k of Object.keys(byName)) { normMap[__normalize(k)] = byName[k]; }
|
||||
const normTeam = __normalize(teamName);
|
||||
let candidate = byName[teamName] || normMap[normTeam];
|
||||
if (!candidate) {
|
||||
// Suffix/containment match after normalization to handle sponsors/affixes
|
||||
const entries = Object.keys(byName).map((k) => ({ keyNorm: __normalize(k), url: byName[k] }));
|
||||
for (const { keyNorm, url } of entries) {
|
||||
if (!keyNorm) continue;
|
||||
if (normTeam.endsWith(keyNorm) || keyNorm.endsWith(normTeam)) { candidate = url; break; }
|
||||
}
|
||||
}
|
||||
if (!candidate) {
|
||||
const t1 = normTeam.split(' ')[0];
|
||||
if (t1 && t1.length >= 5) {
|
||||
for (const { keyNorm, url } of Object.keys(byName).map((k) => ({ keyNorm: __normalize(k), url: byName[k] }))) {
|
||||
const k1 = String(keyNorm).split(' ')[0];
|
||||
if (k1 === t1) { candidate = url; break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (candidate) {
|
||||
appliedByName = true;
|
||||
if (mounted) {
|
||||
if (typeof candidate === 'string' && candidate.startsWith('/')) {
|
||||
setLogoUrl(assetUrl(candidate) || candidate);
|
||||
} else {
|
||||
setLogoUrl(candidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
if (!appliedByName) {
|
||||
const url = await getTeamLogo(teamId, teamName, facrLogo);
|
||||
if (mounted) {
|
||||
setLogoUrl(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
Reference in New Issue
Block a user