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,134 @@
|
||||
import { assetUrl } from '../utils/url';
|
||||
|
||||
export interface RelatedClub {
|
||||
id: string;
|
||||
name: string;
|
||||
logo_url?: string;
|
||||
competition?: string;
|
||||
last_played_iso?: string;
|
||||
matches_played?: number;
|
||||
}
|
||||
|
||||
const normalize = (value: string) =>
|
||||
String(value || '')
|
||||
.normalize('NFD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
const resolveBackendUrl = (path: string): string => {
|
||||
try {
|
||||
if (/^https?:\/\//i.test(path)) return path;
|
||||
if (path.startsWith('/cache') || path.startsWith('/uploads') || path.startsWith('/api/')) {
|
||||
const base = process.env.REACT_APP_API_BASE_URL || process.env.REACT_APP_API_URL || 'http://localhost:8080/api/v1';
|
||||
const origin = new URL(base).origin;
|
||||
return new URL(path, origin).toString();
|
||||
}
|
||||
return path;
|
||||
} catch {
|
||||
return path;
|
||||
}
|
||||
};
|
||||
|
||||
const fetchJSON = async <T>(path: string): Promise<T | null> => {
|
||||
try {
|
||||
const res = await fetch(resolveBackendUrl(path), { cache: 'no-cache' });
|
||||
if (!res.ok) return null;
|
||||
return (await res.json()) as T;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const parseDateTime = (dt?: string): Date | null => {
|
||||
if (!dt) return null;
|
||||
const [datePart, timePart = '00:00'] = String(dt).split(' ');
|
||||
const [day, month, year] = (datePart || '').split('.');
|
||||
if (!day || !month || !year) return null;
|
||||
const iso = `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}T${timePart.slice(0, 5)}:00`;
|
||||
const d = new Date(iso);
|
||||
return Number.isNaN(d.getTime()) ? null : d;
|
||||
};
|
||||
|
||||
let cachePromise: Promise<RelatedClub[]> | null = null;
|
||||
|
||||
const buildRelatedClubs = (clubInfo: any): RelatedClub[] => {
|
||||
if (!clubInfo) return [];
|
||||
const ourNameNorm = normalize(clubInfo.name || '');
|
||||
const competitions = Array.isArray(clubInfo.competitions) ? clubInfo.competitions : [];
|
||||
const map = new Map<string, RelatedClub & { lastPlayedDate?: Date }>();
|
||||
|
||||
const considerTeam = (team: {
|
||||
name?: string;
|
||||
id?: string;
|
||||
logo?: string;
|
||||
competition?: string;
|
||||
occurredAt?: Date | null;
|
||||
}) => {
|
||||
const teamName = team.name?.trim();
|
||||
if (!teamName) return;
|
||||
const normName = normalize(teamName);
|
||||
if (!normName || normName === ourNameNorm) return;
|
||||
|
||||
const existing = map.get(normName);
|
||||
const matchesPlayed = (existing?.matches_played ?? 0) + 1;
|
||||
const lastPlayedDate = team.occurredAt && (!existing?.lastPlayedDate || team.occurredAt > existing.lastPlayedDate)
|
||||
? team.occurredAt
|
||||
: existing?.lastPlayedDate;
|
||||
const logoUrl = team.logo || existing?.logo_url;
|
||||
const competition = team.competition || existing?.competition;
|
||||
|
||||
map.set(normName, {
|
||||
id: team.id || existing?.id || normName,
|
||||
name: teamName,
|
||||
logo_url: logoUrl ? assetUrl(logoUrl) || logoUrl : existing?.logo_url,
|
||||
competition,
|
||||
matches_played: matchesPlayed,
|
||||
last_played_iso: lastPlayedDate ? lastPlayedDate.toISOString() : existing?.last_played_iso,
|
||||
lastPlayedDate,
|
||||
});
|
||||
};
|
||||
|
||||
competitions.forEach((comp: any) => {
|
||||
const matches = Array.isArray(comp?.matches) ? comp.matches : [];
|
||||
matches.forEach((match: any) => {
|
||||
const occurredAt = parseDateTime(match?.date_time);
|
||||
considerTeam({
|
||||
name: match?.home,
|
||||
id: match?.home_id || match?.homeId,
|
||||
logo: match?.home_logo_url,
|
||||
competition: comp?.name,
|
||||
occurredAt,
|
||||
});
|
||||
considerTeam({
|
||||
name: match?.away,
|
||||
id: match?.away_id || match?.awayId,
|
||||
logo: match?.away_logo_url,
|
||||
competition: comp?.name,
|
||||
occurredAt,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return Array.from(map.values())
|
||||
.map(({ lastPlayedDate, ...rest }) => rest)
|
||||
.sort((a, b) => {
|
||||
const ad = a.last_played_iso ? new Date(a.last_played_iso).getTime() : 0;
|
||||
const bd = b.last_played_iso ? new Date(b.last_played_iso).getTime() : 0;
|
||||
return bd - ad;
|
||||
});
|
||||
};
|
||||
|
||||
const fetchRelatedClubs = async (): Promise<RelatedClub[]> => {
|
||||
const clubInfo = await fetchJSON<any>('/cache/prefetch/facr_club_info.json');
|
||||
if (!clubInfo) return [];
|
||||
return buildRelatedClubs(clubInfo);
|
||||
};
|
||||
|
||||
export const getRelatedClubs = async (): Promise<RelatedClub[]> => {
|
||||
if (!cachePromise) {
|
||||
cachePromise = fetchRelatedClubs().catch(() => []);
|
||||
}
|
||||
return cachePromise;
|
||||
};
|
||||
Reference in New Issue
Block a user