import React from 'react'; import { Box, VStack, Heading, Spinner, Text, useColorModeValue, SimpleGrid, } from '@chakra-ui/react'; import { useQuery } from '@tanstack/react-query'; import { getPolls, getPoll } from '../../services/polls'; import PollCard from './PollCard'; interface EmbeddedPollProps { articleId?: number; eventId?: number; videoUrl?: string; title?: string; showTitle?: boolean; maxPolls?: number; // When true, render without outer background/padding so parent wrapper controls layout unstyled?: boolean; } /** * EmbeddedPoll component - displays polls related to specific content * Use in article pages, event pages, or video pages */ const EmbeddedPoll: React.FC = ({ articleId, eventId, videoUrl, title = 'Hlasování', showTitle = true, maxPolls, unstyled = false, }) => { const bgSection = useColorModeValue('gray.50', 'gray.900'); // Build query params based on what's provided const queryParams: any = {}; if (articleId) queryParams.article_id = articleId; if (eventId) queryParams.event_id = eventId; if (videoUrl) queryParams.video_url = videoUrl; // Fetch polls related to this content const { data: polls, isLoading } = useQuery({ queryKey: ['embedded-polls', queryParams], queryFn: () => getPolls(queryParams), enabled: !!(articleId || eventId || videoUrl), // Only fetch if at least one param is provided staleTime: 2 * 60 * 1000, }); // 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', preSortedLimited.map((p) => p.id)], queryFn: async () => { const promises = preSortedLimited.map((poll) => getPoll(poll.id)); return await Promise.all(promises); }, enabled: preSortedLimited.length > 0, }); // Don't render anything if no content identifier provided if (!articleId && !eventId && !videoUrl) { return null; } // Don't render if loading initially if (isLoading) { return ( Načítání hlasování... ); } // Don't render if no polls found if (!polls || polls.length === 0 || !pollsData || pollsData.length === 0) { return null; } // Wrapper styling: allow transparent/compact when unstyled const wrapperProps = unstyled ? { bg: 'transparent', py: 0, px: 0, borderRadius: 'none' as any, my: 0 } : { bg: bgSection, py: 8, px: 4, borderRadius: 'xl' as any, my: 8 }; return ( {showTitle && ( {title} )} {isLoadingPolls ? ( Načítání... ) : ( (() => { // 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 ( ); } if (count === 2) { return ( {limited.map((pollResponse) => ( ))} ); } return ( {limited.map((pollResponse) => ( ))} ); })() )} ); }; export default EmbeddedPoll;