This commit is contained in:
Tomáš Dvořák
2025-10-16 17:10:13 +02:00
parent f5e7be92c7
commit 35d0954afd
84 changed files with 9571 additions and 4668 deletions
+167 -33
View File
@@ -822,26 +822,66 @@ const CalendarPage: React.FC = () => {
borderColor={listMatchBorder}
_hover={{ bg: listMatchHoverBg, borderColor: 'brand.primary', cursor: 'pointer', transform: 'translateY(-2px)', boxShadow: 'md' }}
transition="all 0.2s"
gap={3}
>
<Flex direction="column" minW="180px">
<Text fontWeight="semibold" color={listDateText}>{m.date}</Text>
{m.venue && <Text color={listVenueText} fontSize="sm">{m.venue}</Text>}
<Flex direction="column" minW="100px">
<Text fontWeight="semibold" color={listDateText} fontSize="sm">{m.date}</Text>
<Text color={listTimeText} fontSize="sm">{m.time || '—'}</Text>
{m.venue && <Text color={listVenueText} fontSize="xs" mt={1}>{m.venue}</Text>}
</Flex>
<Flex direction="column" align="center" gap={1} flex="1" justify="center">
{!isPast && countdown ? (
<Badge colorScheme="orange" fontSize="md">za {countdown}</Badge>
) : (
<Flex align="center" gap={2} justify="center">
{m.home_logo_url && (
<Image src={m.home_logo_url} alt={m.home} boxSize="20px" borderRadius="full" objectFit="cover" />
)}
<Badge colorScheme={isPast && m.score ? (getSentiment(m)?.color || 'gray') : 'gray'}>{isPast && m.score ? m.score : 'vs'}</Badge>
{m.away_logo_url && (
<Image src={m.away_logo_url} alt={m.away} boxSize="20px" borderRadius="full" objectFit="cover" />
)}
</Flex>
)}
<Text fontSize="sm" color={listTimeText}>{m.time || '—'}</Text>
<Flex align="center" gap={3} flex="1">
{/* Home Team */}
<Flex align="center" gap={2} flex="1" justify="flex-end">
<Text fontSize="sm" fontWeight="medium" textAlign="right" color={listDateText}>
{m.home}
</Text>
{m.home_logo_url && (
<Image
src={m.home_logo_url}
alt={m.home}
boxSize="32px"
borderRadius="full"
objectFit="cover"
border="2px solid"
borderColor="gray.200"
/>
)}
</Flex>
{/* Score or Countdown */}
<Flex direction="column" align="center" gap={1} minW="80px">
{!isPast && countdown ? (
<Badge colorScheme="orange" fontSize="sm" px={2}>za {countdown}</Badge>
) : (
<Badge colorScheme={isPast && m.score ? (getSentiment(m)?.color || 'gray') : 'gray'} fontSize="md" px={3} py={1}>
{isPast && m.score ? m.score : 'vs'}
</Badge>
)}
{sentiment && (
<Text fontSize="xs" color={`${sentiment.color}.600`} fontWeight="semibold">
{sentiment.label}
</Text>
)}
</Flex>
{/* Away Team */}
<Flex align="center" gap={2} flex="1" justify="flex-start">
{m.away_logo_url && (
<Image
src={m.away_logo_url}
alt={m.away}
boxSize="32px"
borderRadius="full"
objectFit="cover"
border="2px solid"
borderColor="gray.200"
/>
)}
<Text fontSize="sm" fontWeight="medium" textAlign="left" color={listDateText}>
{m.away}
</Text>
</Flex>
</Flex>
</Flex>
{href && (
@@ -905,10 +945,12 @@ const CalendarPage: React.FC = () => {
</Flex>
);
}
if (selected.comp?.name || selected.match.__compName) {
const compName = selected.comp?.name || selected.match.__compName;
// Don't show "Všechny soutěže" badge - only show specific competition names
if (compName && compName !== 'Všechny soutěže') {
return (
<Flex justify="center">
<Badge colorScheme="purple">{selected.comp?.name || selected.match.__compName}</Badge>
<Badge colorScheme="purple">{compName}</Badge>
</Flex>
);
}
@@ -971,20 +1013,112 @@ const CalendarPage: React.FC = () => {
<Text fontSize="md" color="gray.700">
{selected.match.time || '—'}
</Text>
{(() => {
const dt = new Date(`${selected.match.date}T${(selected.match.time || '00:00')}:00`);
const isPast = Date.now() >= dt.getTime();
const hasScore = Boolean(selected.match.score);
if (!hasScore && !isPast && modalCountdown.countdownString) {
return (
<Badge colorScheme="orange" mt={2} fontSize="sm" px={2} py={1}>
Začíná za {modalCountdown.countdownString}
</Badge>
);
}
return null;
})()}
</Box>
{/* Enhanced Countdown Display for Upcoming Matches */}
{(() => {
const dt = new Date(`${selected.match.date}T${(selected.match.time || '00:00')}:00`);
const isPast = Date.now() >= dt.getTime();
const hasScore = Boolean(selected.match.score);
if (!hasScore && !isPast && modalCountdown.isActive && modalCountdown.timeRemaining > 0) {
const days = Math.floor(modalCountdown.timeRemaining / (24 * 60 * 60 * 1000));
const hours = Math.floor((modalCountdown.timeRemaining % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000));
const minutes = Math.floor((modalCountdown.timeRemaining % (60 * 60 * 1000)) / (60 * 1000));
const seconds = Math.floor((modalCountdown.timeRemaining % (60 * 1000)) / 1000);
return (
<Box
mt={4}
p={4}
bg="orange.50"
borderRadius="lg"
borderWidth="2px"
borderColor="orange.200"
>
<Text fontSize="sm" fontWeight="semibold" color="orange.800" mb={3} textAlign="center">
Zápas začíná za
</Text>
<Grid
templateColumns={days > 0 ? "repeat(4, 1fr)" : "repeat(3, 1fr)"}
gap={3}
>
{days > 0 && (
<Box textAlign="center">
<Box
bg="white"
borderRadius="md"
p={3}
borderWidth="1px"
borderColor="orange.300"
boxShadow="sm"
>
<Text fontSize="2xl" fontWeight="bold" color="orange.600">
{days}
</Text>
</Box>
<Text fontSize="xs" color="gray.600" mt={1} fontWeight="medium">
{days === 1 ? 'den' : days < 5 ? 'dny' : 'dní'}
</Text>
</Box>
)}
<Box textAlign="center">
<Box
bg="white"
borderRadius="md"
p={3}
borderWidth="1px"
borderColor="orange.300"
boxShadow="sm"
>
<Text fontSize="2xl" fontWeight="bold" color="orange.600">
{String(hours).padStart(2, '0')}
</Text>
</Box>
<Text fontSize="xs" color="gray.600" mt={1} fontWeight="medium">
{hours === 1 ? 'hodina' : hours < 5 ? 'hodiny' : 'hodin'}
</Text>
</Box>
<Box textAlign="center">
<Box
bg="white"
borderRadius="md"
p={3}
borderWidth="1px"
borderColor="orange.300"
boxShadow="sm"
>
<Text fontSize="2xl" fontWeight="bold" color="orange.600">
{String(minutes).padStart(2, '0')}
</Text>
</Box>
<Text fontSize="xs" color="gray.600" mt={1} fontWeight="medium">
{minutes === 1 ? 'minuta' : minutes < 5 ? 'minuty' : 'minut'}
</Text>
</Box>
<Box textAlign="center">
<Box
bg="white"
borderRadius="md"
p={3}
borderWidth="1px"
borderColor="orange.300"
boxShadow="sm"
>
<Text fontSize="2xl" fontWeight="bold" color="orange.600">
{String(seconds).padStart(2, '0')}
</Text>
</Box>
<Text fontSize="xs" color="gray.600" mt={1} fontWeight="medium">
{seconds === 1 ? 'sekunda' : seconds < 5 ? 'sekundy' : 'sekund'}
</Text>
</Box>
</Grid>
</Box>
);
}
return null;
})()}
<Box h="1px" bg="gray.200" />
<Heading as="h3" size="sm">Odběr notifikací pro fanoušky</Heading>
<Text fontSize="sm" color="gray.600">Zadejte svůj email a budeme vás informovat o novinkách a zápasech.</Text>