This commit is contained in:
Tomas Dvorak
2026-01-26 08:13:18 +01:00
parent aa036b6550
commit dfc079288f
505 changed files with 95755 additions and 5712 deletions
+33 -15
View File
@@ -29,7 +29,8 @@ import {
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { AddIcon, DeleteIcon, ChevronDownIcon, ChevronUpIcon, CloseIcon } from '@chakra-ui/icons';
import { FiPlus } from 'react-icons/fi';
import { getPolls, createPoll, updatePoll, Poll, CreatePollRequest } from '../../services/polls';
import { getAdminPolls, getPolls, createPoll, updatePoll, Poll, CreatePollRequest } from '../../services/polls';
import { useConfirmDialog } from '../../contexts/ConfirmDialogContext';
interface PollLinkerProps {
articleId?: number;
@@ -47,6 +48,7 @@ const PollLinker: React.FC<PollLinkerProps> = ({ articleId, eventId, onPollsChan
const [isExpanded, setIsExpanded] = useState(true);
const [selectedPollId, setSelectedPollId] = useState<string>('');
const [showCreateForm, setShowCreateForm] = useState(false);
const { confirm } = useConfirmDialog();
// Poll creation form state
const [newPollData, setNewPollData] = useState<CreatePollRequest>({
@@ -82,7 +84,7 @@ const PollLinker: React.FC<PollLinkerProps> = ({ articleId, eventId, onPollsChan
// Query for all available polls
const { data: allPolls, isLoading: isLoadingAll } = useQuery({
queryKey: ['all-admin-polls'],
queryFn: () => getPolls({ status: 'active' }),
queryFn: () => getAdminPolls({ status: 'active' }),
});
// Mutation to link existing poll
@@ -189,10 +191,16 @@ const PollLinker: React.FC<PollLinkerProps> = ({ articleId, eventId, onPollsChan
linkPollMutation.mutate(parseInt(selectedPollId));
};
const handleUnlinkPoll = (pollId: number) => {
if (window.confirm('Opravdu chcete odpojit tuto anketu?')) {
unlinkPollMutation.mutate(pollId);
}
const handleUnlinkPoll = async (pollId: number) => {
const ok = await confirm({
title: 'Odpojit anketu',
message: 'Opravdu chcete odpojit tuto anketu?',
confirmText: 'Odpojit',
cancelText: 'Zrušit',
isDanger: true,
});
if (!ok) return;
unlinkPollMutation.mutate(pollId);
};
const resetNewPollForm = () => {
@@ -272,13 +280,13 @@ const PollLinker: React.FC<PollLinkerProps> = ({ articleId, eventId, onPollsChan
}));
};
// Filter out polls that are already linked elsewhere to avoid accidental reuse
const linkedPollIds = new Set(linkedPolls?.map(p => p.id) || []);
const availablePolls = allPolls?.filter(p => {
if (linkedPollIds.has(p.id)) return false; // already linked to this content, handled above
const linkedElsewhere = !!(p.related_article_id || p.related_event_id || p.related_match_id || p.related_video_url);
return !linkedElsewhere;
}) || [];
// Filter out polls that are already linked to THIS content to avoid duplicates
// But allow polls that are linked elsewhere (user can decide to reuse)
const linkedPollIds = new Set(linkedPolls?.map((p: Poll) => p.id) || []);
const availablePolls = allPolls?.filter((p: Poll) => !linkedPollIds.has(p.id)) || [];
// For debugging: also include all polls to see what's available
const allAvailablePolls = allPolls || [];
if (!articleId && !eventId) {
return null;
@@ -323,7 +331,7 @@ const PollLinker: React.FC<PollLinkerProps> = ({ articleId, eventId, onPollsChan
<Text fontSize="xs" fontWeight="bold" color="gray.500">
Připojené ankety:
</Text>
{linkedPolls.map((poll) => (
{linkedPolls.map((poll: Poll) => (
<HStack
key={poll.id}
p={2}
@@ -390,7 +398,7 @@ const PollLinker: React.FC<PollLinkerProps> = ({ articleId, eventId, onPollsChan
size="sm"
flex={1}
>
{availablePolls.map((poll) => (
{availablePolls.map((poll: Poll) => (
<option key={poll.id} value={poll.id}>
{poll.title} ({poll.status}) - {poll.total_votes} hlasů
</option>
@@ -408,6 +416,16 @@ const PollLinker: React.FC<PollLinkerProps> = ({ articleId, eventId, onPollsChan
</Button>
</HStack>
</VStack>
) : allAvailablePolls.length > 0 ? (
<Alert status="warning" size="sm">
<AlertIcon />
<VStack align="start" spacing={2}>
<Text fontSize="sm">Všechny aktivní ankety jsou již propojeny s touto aktivitou.</Text>
<Text fontSize="xs" color="gray.600">
Dostupné ankety ({allAvailablePolls.length}): {allAvailablePolls.map(p => p.title).join(', ')}
</Text>
</VStack>
</Alert>
) : (
<Alert status="info" size="sm">
<AlertIcon />