mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
144 lines
4.7 KiB
TypeScript
144 lines
4.7 KiB
TypeScript
import { Box, Text, VStack, HStack, Image, Skeleton, Link as ChakraLink, Icon } from '@chakra-ui/react';
|
|
import { FaNewspaper, FaUser, FaCalendarAlt } from 'react-icons/fa';
|
|
import { Link as RouterLink } from 'react-router-dom';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { api } from '../../services/api';
|
|
import { Widget } from './Widget';
|
|
import { format, parseISO } from 'date-fns';
|
|
import { cs } from 'date-fns/locale';
|
|
import { Article } from '../../types';
|
|
|
|
export const ArticlesWidget = () => {
|
|
const { data: articles = [], isLoading, error } = useQuery<Article[]>({
|
|
queryKey: ['recentArticles'],
|
|
queryFn: async () => {
|
|
try {
|
|
const { data } = await api.get('/articles', {
|
|
params: {
|
|
limit: 3,
|
|
include: 'author',
|
|
sort: '-createdAt',
|
|
published: true
|
|
}
|
|
});
|
|
return data.data || [];
|
|
} catch (err) {
|
|
console.error('Error fetching articles:', err);
|
|
return [];
|
|
}
|
|
},
|
|
staleTime: 5 * 60 * 1000, // 5 minutes
|
|
});
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<Widget title="Poslední články" icon={FaNewspaper}>
|
|
<VStack spacing={4} align="stretch">
|
|
{[1, 2, 3].map((i) => (
|
|
<Box key={i}>
|
|
<Skeleton height="120px" mb={2} borderRadius="md" />
|
|
<Skeleton height="20px" mb={2} width="80%" />
|
|
<Skeleton height="16px" width="60%" />
|
|
</Box>
|
|
))}
|
|
</VStack>
|
|
</Widget>
|
|
);
|
|
}
|
|
|
|
if (error || !articles.length) {
|
|
return (
|
|
<Widget title="Poslední články" icon={FaNewspaper}>
|
|
<VStack p={4} spacing={4}>
|
|
<Box p={4} bg="gray.50" borderRadius="md" textAlign="center" w="full">
|
|
<Icon as={FaNewspaper} boxSize={6} color="gray.400" mb={2} />
|
|
<Text color="gray.500">Žádné články nebyly nalezeny</Text>
|
|
</Box>
|
|
</VStack>
|
|
</Widget>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Widget title="Poslední články" icon={FaNewspaper}>
|
|
<VStack spacing={3} align="stretch" divider={<Box borderBottomWidth="1px" borderColor="gray.100" />}>
|
|
{articles.map((article) => (
|
|
<ChakraLink
|
|
key={article.id}
|
|
as={RouterLink}
|
|
to={`/clanky/${article.slug}`}
|
|
_hover={{ textDecoration: 'none' }}
|
|
display="block"
|
|
>
|
|
<Box _hover={{ bg: 'gray.50' }} borderRadius="md" p={2}>
|
|
<HStack align="flex-start" spacing={3}>
|
|
<Box
|
|
flexShrink={0}
|
|
width="60px"
|
|
height="60px"
|
|
bg="gray.100"
|
|
borderRadius="md"
|
|
overflow="hidden"
|
|
position="relative"
|
|
>
|
|
{article.imageUrl ? (
|
|
<Image
|
|
src={article.imageUrl}
|
|
alt={article.title}
|
|
width="100%"
|
|
height="100%"
|
|
objectFit="cover"
|
|
/>
|
|
) : (
|
|
<Box
|
|
width="100%"
|
|
height="100%"
|
|
display="flex"
|
|
alignItems="center"
|
|
justifyContent="center"
|
|
bg="gray.200"
|
|
>
|
|
<Icon as={FaNewspaper} color="gray.400" boxSize={5} />
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
<Box flex={1} minW={0}>
|
|
<Text fontWeight="medium" fontSize="sm" noOfLines={2} mb={1}>
|
|
{article.title}
|
|
</Text>
|
|
<HStack spacing={3} fontSize="xs" color="gray.500">
|
|
<HStack spacing={1}>
|
|
<Icon as={FaUser} boxSize={3} />
|
|
<Text>{article.author.name}</Text>
|
|
</HStack>
|
|
<HStack spacing={1}>
|
|
<Icon as={FaCalendarAlt} boxSize={3} />
|
|
<Text>
|
|
{format(parseISO(article.createdAt), 'd. M. yyyy', {
|
|
locale: cs,
|
|
})}
|
|
</Text>
|
|
</HStack>
|
|
</HStack>
|
|
</Box>
|
|
</HStack>
|
|
</Box>
|
|
</ChakraLink>
|
|
))}
|
|
<Box textAlign="right" mt={2}>
|
|
<ChakraLink
|
|
as={RouterLink}
|
|
to="/admin/clanky"
|
|
color="blue.500"
|
|
fontWeight="medium"
|
|
fontSize="sm"
|
|
_hover={{ textDecoration: 'underline' }}
|
|
>
|
|
Zobrazit všechny články →
|
|
</ChakraLink>
|
|
</Box>
|
|
</VStack>
|
|
</Widget>
|
|
);
|
|
};
|