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,123 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user