This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
"use client";
|
||||
|
||||
import { Box, VStack, Text, Badge, Flex, Image } from "@chakra-ui/react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useColorModeValue } from "@/components/ui/color-mode";
|
||||
import type { ActiveLeagueDto } from "@/lib/api/matches/types";
|
||||
|
||||
interface LeagueSidebarProps {
|
||||
leagues: ActiveLeagueDto[];
|
||||
selectedLeagueId: string | null;
|
||||
onSelect: (leagueId: string | null) => void;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
export default function LeagueSidebar({
|
||||
leagues,
|
||||
selectedLeagueId,
|
||||
onSelect,
|
||||
isLoading,
|
||||
}: LeagueSidebarProps) {
|
||||
const t = useTranslations("matches");
|
||||
|
||||
const bg = useColorModeValue("white", "gray.800");
|
||||
const borderColor = useColorModeValue("gray.100", "gray.700");
|
||||
const activeBg = useColorModeValue("primary.50", "primary.900");
|
||||
const hoverBg = useColorModeValue("gray.50", "gray.750");
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<Box
|
||||
bg={bg}
|
||||
borderRadius="xl"
|
||||
borderWidth="1px"
|
||||
borderColor={borderColor}
|
||||
p={4}
|
||||
>
|
||||
<VStack gap={3}>
|
||||
{Array.from({ length: 6 }).map((_, i) => (
|
||||
<Box
|
||||
key={i}
|
||||
h="40px"
|
||||
w="100%"
|
||||
bg="bg.muted"
|
||||
borderRadius="lg"
|
||||
animation="pulse 1.5s ease-in-out infinite"
|
||||
/>
|
||||
))}
|
||||
</VStack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
bg={bg}
|
||||
borderRadius="xl"
|
||||
borderWidth="1px"
|
||||
borderColor={borderColor}
|
||||
overflow="hidden"
|
||||
>
|
||||
{/* Header */}
|
||||
<Box px={4} py={3} borderBottomWidth="1px" borderColor={borderColor}>
|
||||
<Text
|
||||
fontSize="sm"
|
||||
fontWeight="bold"
|
||||
textTransform="uppercase"
|
||||
letterSpacing="wide"
|
||||
color="fg.muted"
|
||||
>
|
||||
{t("active-leagues")}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* All Leagues Option */}
|
||||
<Box
|
||||
px={4}
|
||||
py={2.5}
|
||||
cursor="pointer"
|
||||
bg={selectedLeagueId === null ? activeBg : "transparent"}
|
||||
_hover={{ bg: selectedLeagueId === null ? activeBg : hoverBg }}
|
||||
onClick={() => onSelect(null)}
|
||||
transition="background 0.15s"
|
||||
borderBottomWidth="1px"
|
||||
borderColor={borderColor}
|
||||
>
|
||||
<Text
|
||||
fontSize="sm"
|
||||
fontWeight={selectedLeagueId === null ? "bold" : "medium"}
|
||||
color={selectedLeagueId === null ? "primary.fg" : "fg"}
|
||||
>
|
||||
{t("all-leagues")}
|
||||
</Text>
|
||||
</Box>
|
||||
|
||||
{/* League List */}
|
||||
<VStack gap={0} align="stretch" maxH="60vh" overflowY="auto">
|
||||
{leagues.map((league) => {
|
||||
const isActive = selectedLeagueId === league.id;
|
||||
return (
|
||||
<Box
|
||||
key={league.id}
|
||||
px={4}
|
||||
py={2.5}
|
||||
cursor="pointer"
|
||||
bg={isActive ? activeBg : "transparent"}
|
||||
_hover={{ bg: isActive ? activeBg : hoverBg }}
|
||||
onClick={() => onSelect(league.id)}
|
||||
transition="background 0.15s"
|
||||
borderBottomWidth="1px"
|
||||
borderColor={borderColor}
|
||||
>
|
||||
<Flex justify="space-between" align="center">
|
||||
<Flex align="center" gap={2} minW={0} flex={1}>
|
||||
{league.countryFlag && (
|
||||
<Image
|
||||
src={league.countryFlag}
|
||||
alt={league.countryName || ""}
|
||||
boxSize="16px"
|
||||
objectFit="contain"
|
||||
flexShrink={0}
|
||||
/>
|
||||
)}
|
||||
<Text
|
||||
fontSize="sm"
|
||||
fontWeight={isActive ? "bold" : "medium"}
|
||||
color={isActive ? "primary.fg" : "fg"}
|
||||
truncate
|
||||
>
|
||||
{league.name}
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
<Flex gap={1.5} flexShrink={0}>
|
||||
{league.liveCount > 0 && (
|
||||
<Badge
|
||||
colorPalette="red"
|
||||
variant="solid"
|
||||
borderRadius="full"
|
||||
fontSize="2xs"
|
||||
px={1.5}
|
||||
>
|
||||
{league.liveCount}
|
||||
</Badge>
|
||||
)}
|
||||
<Badge
|
||||
colorPalette="gray"
|
||||
variant="subtle"
|
||||
borderRadius="full"
|
||||
fontSize="2xs"
|
||||
px={1.5}
|
||||
>
|
||||
{league.matchCount}
|
||||
</Badge>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</VStack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user