import React, { useEffect, useMemo, useState } from 'react'; import MainLayout from '../components/layout/MainLayout'; import { Box, Container, Heading, Text, Tabs, TabList, TabPanels, Tab, TabPanel, Table, Thead, Tbody, Tr, Th, Td, Flex, Spinner, Badge, Link, useColorModeValue } from '@chakra-ui/react'; import { getCompetitionAliasesPublic, CompetitionAlias } from '../services/competitionAliases'; import SponsorsSection from '../components/common/SponsorsSection'; import NewsletterCTA from '../components/common/NewsletterCTA'; import ClubModal from '../components/home/ClubModal'; import { usePublicSettings } from '../hooks/usePublicSettings'; import { sortCategoriesWithOrder } from '../utils/categorySort'; import { TeamLogo } from '../components/common/TeamLogo'; type TableRow = { rank: string; team: string; team_id?: string; team_logo_url?: string; played: string; wins: string; draws: string; losses: string; score: string; points: string; }; type CompetitionTable = { id: string; name: string; code?: string; matches_link?: string; rows: TableRow[]; }; const resolveBackendUrl = (path: string) => { try { if (/^https?:\/\//i.test(path)) return path; if (path.startsWith('/cache') || path.startsWith('/uploads')) { const base = process.env.REACT_APP_API_BASE_URL || process.env.REACT_APP_API_URL || 'http://localhost:8080/api/v1'; const u = new URL(base); u.pathname = path; return u.toString(); } return path; } catch { return path; } }; const TablesPage: React.FC = () => { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [competitions, setCompetitions] = useState([]); const [aliasMap, setAliasMap] = useState>({}); const [selectedClub, setSelectedClub] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); const { data: settings } = usePublicSettings(); const cardBg = useColorModeValue('white', 'gray.800'); const borderColor = useColorModeValue('gray.200', 'gray.700'); const textSecondary = useColorModeValue('gray.600', 'gray.400'); const tableBg = useColorModeValue('white', 'gray.800'); const tableHeaderBg = useColorModeValue('var(--primary, #C53030)', 'var(--primary, #9b2c2c)'); const tableTextColor = useColorModeValue('gray.800', 'gray.200'); const rowOddBg = useColorModeValue('white', 'gray.800'); const rowEvenBg = useColorModeValue('gray.50', 'gray.700'); const handleClubClick = (club: any) => { setSelectedClub(club); setIsModalOpen(true); }; useEffect(() => { let cancelled = false; (async () => { setLoading(true); setError(null); try { // Load aliases first let amap: Record = {}; try { const aliases: CompetitionAlias[] = await getCompetitionAliasesPublic(); (aliases || []).forEach((a) => { if (a?.code && a?.alias) amap[a.code] = { alias: a.alias, original_name: a.original_name, display_order: a.display_order }; }); } catch {} const res = await fetch(resolveBackendUrl('/cache/prefetch/facr_tables.json'), { cache: 'no-cache' }); if (!res.ok) throw new Error(`HTTP ${res.status}`); const json = await res.json(); const comps: CompetitionTable[] = Array.isArray(json?.competitions) ? json.competitions.map((c: any, idx: number) => { const overall = c?.table?.overall || []; const rows: TableRow[] = Array.isArray(overall) ? overall.map((r: any) => ({ rank: String(r.rank ?? ''), team: String(r.team ?? ''), team_id: r.team_id, team_logo_url: r.team_logo_url ? resolveBackendUrl(r.team_logo_url) : undefined, played: String(r.played ?? ''), wins: String(r.wins ?? ''), draws: String(r.draws ?? ''), losses: String(r.losses ?? ''), score: String(r.score ?? ''), points: String(r.points ?? ''), })) : []; return { id: String(c.id || idx), name: (amap?.[c?.code]?.alias) || (amap?.[String(c.id || idx)]?.alias) || c.name || c.code || `Soutěž ${idx+1}`, alias: (amap?.[c?.code]?.alias) || (amap?.[String(c.id || idx)]?.alias), display_order: (amap?.[c?.code]?.display_order) ?? (amap?.[String(c.id || idx)]?.display_order), code: c.code, matches_link: c.matches_link, rows, }; }) : []; if (!cancelled) { setAliasMap(amap); // Only keep competitions that have at least one row in the table const filtered = (comps || []).filter((c) => Array.isArray(c.rows) && c.rows.length > 0); // Sort competitions by age (Muži first, then U19, U17, etc.) and respect custom order const sorted = sortCategoriesWithOrder(filtered) as typeof filtered; setCompetitions(sorted); } } catch (e: any) { if (!cancelled) setError(e?.message || 'Nepodařilo se načíst tabulky.'); } finally { if (!cancelled) setLoading(false); } })(); return () => { cancelled = true; }; }, []); return ( Tabulky Oficiální tabulky FACR podle soutěží. {loading && ( Načítám tabulky… )} {error && ( {error} )} {!!competitions.length && ( {competitions.map((c) => ( {c.name} ))} {competitions.map((c) => ( {c.name} {c.matches_link && ( Rozpis a detail soutěže )} {c.rows.map((r, idx) => ( handleClubClick(r)} > ))}
# Tým Z V R P Skóre Body
{r.rank} {r.team} {r.played} {r.wins} {r.draws} {r.losses} {r.score} {r.points}
))}
)} {!loading && !error && competitions.length === 0 && ( Pro tento klub nejsou dostupné tabulky. )}
{/* Newsletter CTA */} {/* Sponsors Section */} setIsModalOpen(false)} club={selectedClub} clubType={(settings?.club_type as 'football' | 'futsal') || 'football'} />
); }; export default TablesPage;