This commit is contained in:
Tomas Dvorak
2025-10-28 22:38:27 +01:00
parent 3d621e2187
commit 823fabee02
106 changed files with 9011 additions and 3930 deletions
+91 -25
View File
@@ -6,6 +6,7 @@ import {
Spinner,
Text,
useColorModeValue,
SimpleGrid,
} from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query';
import { getPolls, getPoll } from '../../services/polls';
@@ -17,6 +18,7 @@ interface EmbeddedPollProps {
videoUrl?: string;
title?: string;
showTitle?: boolean;
maxPolls?: number;
}
/**
@@ -29,6 +31,7 @@ const EmbeddedPoll: React.FC<EmbeddedPollProps> = ({
videoUrl,
title = 'Hlasování',
showTitle = true,
maxPolls,
}) => {
const bgSection = useColorModeValue('gray.50', 'gray.900');
@@ -46,16 +49,31 @@ const EmbeddedPoll: React.FC<EmbeddedPollProps> = ({
staleTime: 2 * 60 * 1000,
});
// Get full poll data for each
const pollsToDisplay = polls?.slice(0, 3) || []; // Max 3 polls per content
// Get full poll data for each (all linked polls)
const pollsToDisplay = polls || [];
const preSortedLimited = React.useMemo(() => {
const sorted = [...pollsToDisplay].sort((a, b) => {
const aRating = a.type === 'rating' ? 1 : 0;
const bRating = b.type === 'rating' ? 1 : 0;
if (aRating !== bRating) return bRating - aRating;
const aFeat = a.featured ? 1 : 0;
const bFeat = b.featured ? 1 : 0;
if (aFeat !== bFeat) return bFeat - aFeat;
const aDate = new Date(a.created_at).getTime();
const bDate = new Date(b.created_at).getTime();
return bDate - aDate;
});
return typeof maxPolls === 'number' ? sorted.slice(0, maxPolls) : sorted;
}, [pollsToDisplay, maxPolls]);
const { data: pollsData, isLoading: isLoadingPolls } = useQuery({
queryKey: ['embedded-polls-details', pollsToDisplay.map((p) => p.id)],
queryKey: ['embedded-polls-details', preSortedLimited.map((p) => p.id)],
queryFn: async () => {
const promises = pollsToDisplay.map((poll) => getPoll(poll.id));
const promises = preSortedLimited.map((poll) => getPoll(poll.id));
return await Promise.all(promises);
},
enabled: pollsToDisplay.length > 0,
enabled: preSortedLimited.length > 0,
});
// Don't render anything if no content identifier provided
@@ -84,35 +102,83 @@ const EmbeddedPoll: React.FC<EmbeddedPollProps> = ({
return (
<Box bg={bgSection} py={8} px={4} borderRadius="xl" my={8}>
<VStack spacing={6} maxW="3xl" mx="auto">
<VStack spacing={6} maxW="6xl" mx="auto">
{showTitle && (
<Heading size="md" textAlign="center">
{title}
</Heading>
)}
<VStack spacing={4} w="full">
{isLoadingPolls ? (
<VStack py={8}>
<Spinner />
<Text>Načítání...</Text>
</VStack>
) : (
pollsData.map((pollResponse) => (
<Box key={pollResponse.poll.id} w="full">
<PollCard
poll={pollResponse.poll}
hasVoted={pollResponse.has_voted}
isActive={pollResponse.is_active}
canShowResults={pollResponse.can_show_results}
/>
</Box>
))
)}
</VStack>
{isLoadingPolls ? (
<VStack py={8}>
<Spinner />
<Text>Načítání...</Text>
</VStack>
) : (
(() => {
// Sort: rating first, then featured, then newest
const sorted = [...(pollsData || [])].sort((a, b) => {
const aRating = a.poll.type === 'rating' ? 1 : 0;
const bRating = b.poll.type === 'rating' ? 1 : 0;
if (aRating !== bRating) return bRating - aRating;
const aFeat = a.poll.featured ? 1 : 0;
const bFeat = b.poll.featured ? 1 : 0;
if (aFeat !== bFeat) return bFeat - aFeat;
const aDate = new Date(a.poll.created_at).getTime();
const bDate = new Date(b.poll.created_at).getTime();
return bDate - aDate;
});
const limited = typeof maxPolls === 'number' ? sorted.slice(0, maxPolls) : sorted;
const count = limited.length;
if (count === 1) {
const pollResponse = limited[0];
return (
<Box w="full">
<PollCard
poll={pollResponse.poll}
hasVoted={pollResponse.has_voted}
isActive={pollResponse.is_active}
canShowResults={pollResponse.can_show_results}
/>
</Box>
);
}
if (count === 2) {
return (
<SimpleGrid w="full" columns={{ base: 1, md: 2 }} spacing={4}>
{limited.map((pollResponse) => (
<Box key={pollResponse.poll.id}>
<PollCard
poll={pollResponse.poll}
hasVoted={pollResponse.has_voted}
isActive={pollResponse.is_active}
canShowResults={pollResponse.can_show_results}
/>
</Box>
))}
</SimpleGrid>
);
}
return (
<SimpleGrid w="full" columns={{ base: 1, sm: 2, lg: 3 }} spacing={4}>
{limited.map((pollResponse) => (
<Box key={pollResponse.poll.id}>
<PollCard
poll={pollResponse.poll}
hasVoted={pollResponse.has_voted}
isActive={pollResponse.is_active}
canShowResults={pollResponse.can_show_results}
/>
</Box>
))}
</SimpleGrid>
);
})()
)}
</VStack>
</Box>
);
};
export default EmbeddedPoll;