import { Box, Tabs, TabList, TabPanels, Tab, TabPanel, VStack, HStack, Image, Text, Skeleton, Badge } from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; import React from 'react'; import { facrApi } from '../../services/facr/facrApi'; import { usePublicSettings } from '../../hooks/usePublicSettings'; import { getCompetitionAliasesPublic, CompetitionAlias } from '../../services/competitionAliases'; import { TeamLogo } from '../common/TeamLogo'; import { sortCategoriesWithOrder } from '../../utils/categorySort'; import { sanitizeClubName } from '../../utils/url'; import '../../styles/logos.css'; const Row: React.FC<{ d: string; h: string; hid?: string; hl?: string; a: string; aid?: string; al?: string; s?: string; clubName?: string; clubId?: string }> = ({ d, h, hid, hl, a, aid, al, s, clubName, clubId }) => ( {d} {sanitizeClubName(h)} {s || '-:-'} {(() => { if (!s) return null; const m = s.match(/^(\d+)\s*[:\-]\s*(\d+)$/); if (!m) return null; const hG = parseInt(m[1], 10), aG = parseInt(m[2], 10); // First try ID-based matching (most reliable) let ourHome = false; let ourAway = false; if (clubId && hid && aid) { ourHome = hid === clubId; ourAway = aid === clubId; } // Fallback to name matching if IDs not available or no match if (!ourHome && !ourAway && clubName) { const norm = (x: string) => String(x||'').normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/\s+/g,' ').trim().toLowerCase(); const strip = (x: string) => norm(x).replace(/\b(mestsky|m\.?f\.?k\.?|mfk|tj|sk|sokol|fotbalovy|fotbalový|fotbalovy\s+klub|fotbalovy\s+klub)\b/g,'').replace(/\s+/g,' ').trim(); const A = strip(h); const B = strip(clubName); ourHome = Boolean(A && B && (A===B || A.endsWith(B) || B.endsWith(A))); const C = strip(a); ourAway = Boolean(C && B && (C===B || C.endsWith(B) || B.endsWith(C))); } if (!ourHome && !ourAway) return null; if (hG === aG) return Remíza; const our = ourHome ? hG : aG; const opp = ourHome ? aG : hG; return our > opp ? Výhra : Prohra; })()} {sanitizeClubName(a)} ); const CompetitionMatches: React.FC = () => { const { data: settings } = usePublicSettings(); const clubId = settings?.club_id; const clubType = settings?.club_type || 'football'; const { data, isLoading } = useQuery({ queryKey: ['facr-club', clubId, clubType], queryFn: () => facrApi.getClub(clubId!, clubType as any), enabled: !!clubId, }); // Load competition aliases const [aliases, setAliases] = React.useState>({}); React.useEffect(() => { let mounted = true; (async () => { try { const list: CompetitionAlias[] = await getCompetitionAliasesPublic(); if (!mounted) return; const map: Record = {}; (list || []).forEach((a) => { if (a?.code && a?.alias) map[a.code] = { alias: a.alias, original_name: a.original_name, display_order: a.display_order }; }); setAliases(map); } catch {} })(); return () => { mounted = false; }; }, []); // Precompute sorted competitions safely (must be before any early returns to keep hooks order stable) const competitions = data?.competitions ?? []; const sortedCompetitions = React.useMemo(() => { const arr = Array.isArray(competitions) ? competitions : []; return sortCategoriesWithOrder( arr.map(c => ({ ...c, name: aliases[c.code]?.alias || aliases[c.id]?.alias || c.name, alias: aliases[c.code]?.alias || aliases[c.id]?.alias, display_order: (aliases[c.code]?.display_order) ?? (aliases[c.id]?.display_order), })) ); }, [competitions, aliases]); if (isLoading) return ; if (!clubId) { return ( Pro zobrazení zápasů je potřeba nastavit klub v administraci (Nastavení → Základní údaje). ); } if (!data || !data.competitions || data.competitions.length === 0) { return ( Žádné soutěže ani zápasy nejsou k dispozici pro vybraný klub. ); } // Sort competitions by age (Muži first, then U19, U17, etc.) and respect custom order (computed above) return ( {sortedCompetitions.map((c) => { const label = c.alias || c.name; return ( {label} ); })} {sortedCompetitions.map((c) => ( {(c.matches || []).slice(0, 6).map((m, idx) => ( ))} {(c.matches || []).length === 0 && ( Žádné zápasy k dispozici. )} ))} ); }; export default CompetitionMatches;