mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
124 lines
4.4 KiB
TypeScript
124 lines
4.4 KiB
TypeScript
import { Box, Button, Heading, HStack, Input, Spinner, Table, Tbody, Td, Th, Thead, Tr, Text, VStack, List, ListItem } from '@chakra-ui/react';
|
|
import { useEffect, useMemo, useState } from 'react';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { facrApi } from '../services/facr/facrApi';
|
|
import type { ClubInfo, Competition, TableRow, SearchResult } from '../services/facr/types';
|
|
import { TeamLogo } from '../components/common/TeamLogo';
|
|
|
|
type SelectedClub = { clubId: string; clubType: 'football' | 'futsal' };
|
|
const STORAGE_KEY = 'facrClub';
|
|
|
|
const StandingsPage: React.FC = () => {
|
|
const [query, setQuery] = useState('');
|
|
const [selected, setSelected] = useState<SelectedClub | null>(null);
|
|
|
|
useEffect(() => {
|
|
const saved = localStorage.getItem(STORAGE_KEY);
|
|
if (saved) {
|
|
try { setSelected(JSON.parse(saved)); } catch {}
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (selected) localStorage.setItem(STORAGE_KEY, JSON.stringify(selected));
|
|
}, [selected]);
|
|
|
|
const { data: searchData, isFetching: searching } = useQuery({
|
|
queryKey: ['facr', 'search', query],
|
|
queryFn: () => facrApi.searchClubs(query),
|
|
enabled: query.trim().length >= 3,
|
|
});
|
|
|
|
const { data: clubTable, isLoading, isError } = useQuery<ClubInfo>({
|
|
queryKey: ['facr', 'clubTable', selected?.clubType, selected?.clubId],
|
|
queryFn: () => facrApi.getClubTable(selected!.clubId, selected!.clubType),
|
|
enabled: !!selected,
|
|
});
|
|
|
|
const tableRows: TableRow[] = useMemo(() => {
|
|
if (!clubTable?.competitions) return [];
|
|
// pick first competition that has table.overall
|
|
const compWithTable: Competition | undefined = clubTable.competitions.find(c => c.table?.overall?.length) || clubTable.competitions[0];
|
|
return compWithTable?.table?.overall || [];
|
|
}, [clubTable]);
|
|
|
|
return (
|
|
<VStack align="stretch" spacing={4}>
|
|
<Heading size="lg">Tabulka</Heading>
|
|
|
|
<Box bg="white" p={4} borderWidth="1px" borderRadius="md">
|
|
<HStack>
|
|
<Input placeholder="Vyhledat klub (min. 3 znaky)" value={query} onChange={(e) => setQuery(e.target.value)} />
|
|
<Button onClick={() => setQuery(query.trim())} isLoading={searching}>Hledat</Button>
|
|
</HStack>
|
|
{searchData?.results?.length ? (
|
|
<List spacing={2} mt={3}>
|
|
{searchData.results.slice(0, 8).map((r: SearchResult) => (
|
|
<ListItem key={`${r.club_type}-${r.club_id}`}>
|
|
<Button size="sm" variant="ghost" onClick={() => setSelected({ clubId: r.club_id, clubType: r.club_type })}>
|
|
{r.name}
|
|
</Button>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
) : null}
|
|
</Box>
|
|
|
|
{!selected && (
|
|
<Text color="gray.500">Vyberte klub pro zobrazení tabulky soutěže.</Text>
|
|
)}
|
|
|
|
{selected && isLoading && <Spinner />}
|
|
{selected && isError && <Text color="red.500">Chyba při načítání tabulky</Text>}
|
|
|
|
{selected && !isLoading && (
|
|
<Table bg="white">
|
|
<Thead>
|
|
<Tr>
|
|
<Th>#</Th>
|
|
<Th>Tým</Th>
|
|
<Th isNumeric>Z</Th>
|
|
<Th isNumeric>V</Th>
|
|
<Th isNumeric>R</Th>
|
|
<Th isNumeric>P</Th>
|
|
<Th isNumeric>Skóre</Th>
|
|
<Th isNumeric>Body</Th>
|
|
</Tr>
|
|
</Thead>
|
|
<Tbody>
|
|
{tableRows.map((row) => (
|
|
<Tr key={row.team_id}>
|
|
<Td>{row.rank}</Td>
|
|
<Td>
|
|
<HStack>
|
|
<TeamLogo
|
|
teamId={row.team_id}
|
|
teamName={row.team}
|
|
facrLogo={row.team_logo_url}
|
|
size="small"
|
|
alt={row.team}
|
|
objectFit="contain"
|
|
/>
|
|
<Text>{row.team}</Text>
|
|
</HStack>
|
|
</Td>
|
|
<Td isNumeric>{row.played}</Td>
|
|
<Td isNumeric>{row.wins}</Td>
|
|
<Td isNumeric>{row.draws}</Td>
|
|
<Td isNumeric>{row.losses}</Td>
|
|
<Td isNumeric>{row.score}</Td>
|
|
<Td isNumeric>{row.points}</Td>
|
|
</Tr>
|
|
))}
|
|
{tableRows.length === 0 && (
|
|
<Tr><Td colSpan={8}><Text>Tabulka není dostupná.</Text></Td></Tr>
|
|
)}
|
|
</Tbody>
|
|
</Table>
|
|
)}
|
|
</VStack>
|
|
);
|
|
}
|
|
|
|
export default StandingsPage;
|