2025-03-28 12:05:40 +00:00
|
|
|
"use client";
|
|
|
|
|
import React, { useContext, useEffect, useState } from "react";
|
|
|
|
|
import GradientTitle from "./GradientTitle";
|
|
|
|
|
import ParticipantCard from "./ParticipantCard";
|
|
|
|
|
import { v4 } from "uuid";
|
|
|
|
|
import { IAllVotes, VotingItem } from "@/models/allVotes.model";
|
|
|
|
|
import { Queries } from "@/api/queries";
|
|
|
|
|
import Loader from "../Loader";
|
|
|
|
|
import VoteContext from "@/context/VoteContext";
|
|
|
|
|
import PageBage from "./PageBage";
|
|
|
|
|
import Image from "next/image";
|
|
|
|
|
import { useMediaQuery } from "usehooks-ts";
|
|
|
|
|
import Countdown from "./Countdown";
|
|
|
|
|
import Link from "next/link";
|
|
|
|
|
import Confetti from "../common/Confetti";
|
|
|
|
|
import { useRouter, useSearchParams } from "next/navigation";
|
2024-08-19 12:44:56 +00:00
|
|
|
|
2025-03-28 12:11:31 +00:00
|
|
|
interface IParams {
|
|
|
|
|
vote_id?: string;
|
2025-03-28 12:50:41 +00:00
|
|
|
all?: boolean;
|
2025-03-28 12:11:31 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-03 12:35:46 +00:00
|
|
|
interface ISocketMessage {
|
|
|
|
|
voting_id: number;
|
|
|
|
|
voting_item_id: number;
|
|
|
|
|
client_id: number;
|
|
|
|
|
message: string;
|
|
|
|
|
date: string;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-28 12:50:41 +00:00
|
|
|
const ParticipantsList = ({ vote_id, all }: IParams) => {
|
2025-03-28 12:05:40 +00:00
|
|
|
const searchParams = useSearchParams();
|
|
|
|
|
const router = useRouter();
|
2024-08-19 12:44:56 +00:00
|
|
|
const [data, setData] = useState<IAllVotes>();
|
2024-09-03 12:35:46 +00:00
|
|
|
const [participantsData, setParticipantsData] = useState<VotingItem[]>([]);
|
2024-08-19 12:44:56 +00:00
|
|
|
const [voteStatus, setVoteStatus] = useState<string>();
|
2025-03-28 12:05:40 +00:00
|
|
|
const [eventStatus, setEventStatus] = useState<string>("Not started");
|
2024-10-17 13:31:55 +00:00
|
|
|
const [manualClose, setManualClose] = useState(false); // Track manual closure
|
|
|
|
|
|
2024-08-19 12:44:56 +00:00
|
|
|
const [winnersCount, setWinnersCount] = useState<number>(0);
|
2024-09-03 12:35:46 +00:00
|
|
|
|
|
|
|
|
// States realted to web socket
|
|
|
|
|
const [smsNumber, setSmsNumber] = useState<string | null>(null);
|
|
|
|
|
const [socket, setSocket] = useState<WebSocket | null>(null);
|
|
|
|
|
const [isConnected, setIsConnected] = useState(false);
|
|
|
|
|
|
2025-03-28 12:05:40 +00:00
|
|
|
const mobile = useMediaQuery("(max-width: 768px)");
|
2024-08-19 12:44:56 +00:00
|
|
|
|
|
|
|
|
const { setVoteDescription } = useContext(VoteContext).voteDescriptionContext;
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2025-03-28 12:11:31 +00:00
|
|
|
const id = searchParams.get("d");
|
2025-03-28 12:05:40 +00:00
|
|
|
if (id) {
|
2025-03-28 12:11:31 +00:00
|
|
|
Queries.getVoteByUUID(id).then((res) => {
|
|
|
|
|
setData(res);
|
|
|
|
|
setParticipantsData(res.data.voting_items);
|
|
|
|
|
setVoteDescription(res.data.description);
|
|
|
|
|
setVoteStatus(res.data.status);
|
|
|
|
|
setSmsNumber(res.data.sms_number);
|
|
|
|
|
});
|
|
|
|
|
} else if (vote_id) {
|
|
|
|
|
Queries.getVote(vote_id).then((res) => {
|
2024-08-19 12:44:56 +00:00
|
|
|
setData(res);
|
|
|
|
|
setParticipantsData(res.data.voting_items);
|
|
|
|
|
setVoteDescription(res.data.description);
|
|
|
|
|
setVoteStatus(res.data.status);
|
2024-09-03 12:35:46 +00:00
|
|
|
setSmsNumber(res.data.sms_number);
|
2024-08-19 12:44:56 +00:00
|
|
|
});
|
2025-03-28 12:50:41 +00:00
|
|
|
} else if (all) {
|
|
|
|
|
Queries.getAllVotes().then((res) => {
|
|
|
|
|
setData(res);
|
|
|
|
|
setParticipantsData([...res.data.voting_items]);
|
|
|
|
|
setVoteDescription(res.data.description);
|
|
|
|
|
setVoteStatus(res.data.status);
|
|
|
|
|
setSmsNumber(res.data.sms_number);
|
|
|
|
|
});
|
2025-03-28 17:40:28 +00:00
|
|
|
} else {
|
2025-03-28 12:11:31 +00:00
|
|
|
router.push("/vote/active");
|
2024-08-19 12:44:56 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-03 12:35:46 +00:00
|
|
|
if (participantsData) {
|
|
|
|
|
winnersCountHandle(participantsData);
|
2024-08-19 12:44:56 +00:00
|
|
|
}
|
2024-09-03 12:35:46 +00:00
|
|
|
}, []);
|
2024-08-19 12:44:56 +00:00
|
|
|
|
2024-09-03 12:35:46 +00:00
|
|
|
useEffect(() => {
|
|
|
|
|
let socket: WebSocket | null = null;
|
|
|
|
|
let reconnectTimeout: NodeJS.Timeout | null = null;
|
|
|
|
|
let pingInterval: NodeJS.Timeout | null = null;
|
2024-08-19 12:44:56 +00:00
|
|
|
|
2024-09-03 12:35:46 +00:00
|
|
|
const connectWebSocket = () => {
|
|
|
|
|
try {
|
2024-10-17 13:31:55 +00:00
|
|
|
// Only connect if manualClose is false
|
|
|
|
|
if (!manualClose) {
|
2025-03-28 12:05:40 +00:00
|
|
|
socket = new WebSocket(
|
|
|
|
|
`wss://sms.turkmentv.gov.tm/ws/voting?dst=${smsNumber}`
|
|
|
|
|
);
|
2024-10-17 13:31:55 +00:00
|
|
|
setSocket(socket);
|
|
|
|
|
|
|
|
|
|
socket.onopen = () => {
|
2025-03-28 12:05:40 +00:00
|
|
|
console.log("WebSocket is connected");
|
2024-10-17 13:31:55 +00:00
|
|
|
setIsConnected(true);
|
|
|
|
|
|
|
|
|
|
pingInterval = setInterval(() => {
|
|
|
|
|
if (socket?.readyState === WebSocket.OPEN) {
|
|
|
|
|
try {
|
2025-03-28 12:05:40 +00:00
|
|
|
socket.send(JSON.stringify({ type: "ping" }));
|
2024-10-17 13:31:55 +00:00
|
|
|
} catch (error) {
|
2025-03-28 12:05:40 +00:00
|
|
|
console.error("Error sending ping:", error);
|
2024-10-17 13:31:55 +00:00
|
|
|
}
|
2024-09-03 12:35:46 +00:00
|
|
|
}
|
2024-10-17 13:31:55 +00:00
|
|
|
}, 25000); // Ping every 25 seconds
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
socket.onmessage = (event) => {
|
|
|
|
|
try {
|
|
|
|
|
const message = JSON.parse(event.data);
|
|
|
|
|
handleWebSocketMessage(message);
|
|
|
|
|
} catch (error) {
|
2025-03-28 12:05:40 +00:00
|
|
|
console.error("Error processing message:", error);
|
2024-10-17 13:31:55 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
socket.onerror = (error) => {
|
2025-03-28 12:05:40 +00:00
|
|
|
console.error("WebSocket error:", error);
|
2024-10-17 13:31:55 +00:00
|
|
|
|
|
|
|
|
if (!manualClose && !reconnectTimeout) {
|
|
|
|
|
reconnectTimeout = setTimeout(() => {
|
2025-03-28 12:05:40 +00:00
|
|
|
console.log("Attempting to reconnect WebSocket after error...");
|
2024-10-17 13:31:55 +00:00
|
|
|
connectWebSocket();
|
|
|
|
|
}, 5000); // Reconnect after 5 seconds
|
2024-09-03 12:35:46 +00:00
|
|
|
}
|
2024-10-17 13:31:55 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
socket.onclose = () => {
|
2025-03-28 12:05:40 +00:00
|
|
|
console.log("WebSocket is closed");
|
2024-10-17 13:31:55 +00:00
|
|
|
setIsConnected(false);
|
|
|
|
|
|
|
|
|
|
if (pingInterval) {
|
|
|
|
|
clearInterval(pingInterval);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Clean up resources on close
|
|
|
|
|
if (reconnectTimeout) {
|
|
|
|
|
clearTimeout(reconnectTimeout);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
2024-09-03 12:35:46 +00:00
|
|
|
} catch (error) {
|
2025-03-28 12:05:40 +00:00
|
|
|
console.error("WebSocket connection error:", error);
|
2024-09-03 12:35:46 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2024-10-17 13:31:55 +00:00
|
|
|
// WebSocket connection only if eventStatus is 'Started'
|
2025-03-28 12:05:40 +00:00
|
|
|
if (smsNumber && eventStatus === "Started" && !manualClose) {
|
2024-09-03 12:35:46 +00:00
|
|
|
connectWebSocket();
|
2024-08-19 12:44:56 +00:00
|
|
|
}
|
2024-09-03 12:35:46 +00:00
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
if (socket) {
|
2024-10-17 13:31:55 +00:00
|
|
|
setManualClose(true); // Mark it as a manual close
|
2024-09-03 12:35:46 +00:00
|
|
|
socket.close();
|
|
|
|
|
}
|
|
|
|
|
if (reconnectTimeout) {
|
|
|
|
|
clearTimeout(reconnectTimeout);
|
|
|
|
|
}
|
|
|
|
|
if (pingInterval) {
|
|
|
|
|
clearInterval(pingInterval);
|
|
|
|
|
}
|
|
|
|
|
};
|
2024-10-17 13:31:55 +00:00
|
|
|
}, [smsNumber, eventStatus, manualClose]); // Add manualClose to dependencies
|
2024-09-03 12:35:46 +00:00
|
|
|
|
|
|
|
|
const handleWebSocketMessage = (message: ISocketMessage) => {
|
|
|
|
|
setParticipantsData((prevVotingItems) => {
|
|
|
|
|
if (!prevVotingItems) return [];
|
|
|
|
|
|
|
|
|
|
// Update the corresponding voting item
|
|
|
|
|
const updatedItems = prevVotingItems.map((item, index) =>
|
2025-03-28 12:05:40 +00:00
|
|
|
item.id === message.voting_item_id
|
|
|
|
|
? { ...item, votes_count: item.votes_count + 1 }
|
|
|
|
|
: item
|
2024-09-03 12:35:46 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Sort the updated items array by votes_count in descending order
|
|
|
|
|
return updatedItems.sort((a, b) => b.votes_count - a.votes_count);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const addVotes = () => {
|
|
|
|
|
setParticipantsData((prevVotingItems) => {
|
|
|
|
|
if (!prevVotingItems) return [];
|
|
|
|
|
|
|
|
|
|
// Update the corresponding voting item
|
|
|
|
|
const updatedItems = prevVotingItems.map((item, index) =>
|
2025-03-28 12:05:40 +00:00
|
|
|
index === 1 ? { ...item, votes_count: item.votes_count + 1 } : item
|
2024-09-03 12:35:46 +00:00
|
|
|
);
|
|
|
|
|
|
2025-03-28 12:05:40 +00:00
|
|
|
console.log("votes updated");
|
2024-09-10 12:36:03 +00:00
|
|
|
console.log(updatedItems.sort((a, b) => b.votes_count - a.votes_count));
|
2024-09-03 12:35:46 +00:00
|
|
|
// Sort the updated items array by votes_count in descending order
|
|
|
|
|
return updatedItems.sort((a, b) => b.votes_count - a.votes_count);
|
|
|
|
|
});
|
|
|
|
|
};
|
2024-08-19 12:44:56 +00:00
|
|
|
|
|
|
|
|
const winnersCountHandle = (winners: VotingItem[]) => {
|
|
|
|
|
let count = 0;
|
|
|
|
|
winners.map((winner) => {
|
2025-03-28 12:05:40 +00:00
|
|
|
if (
|
|
|
|
|
winner.votes_percents === 100 &&
|
|
|
|
|
winner.votes_count === winners[0].votes_count
|
|
|
|
|
) {
|
2024-08-19 12:44:56 +00:00
|
|
|
count++;
|
|
|
|
|
setWinnersCount(count);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return count;
|
|
|
|
|
};
|
|
|
|
|
|
2024-09-19 12:17:04 +00:00
|
|
|
const hasVotes = participantsData.some((item) => item.votes_count > 0);
|
|
|
|
|
|
2024-08-19 12:44:56 +00:00
|
|
|
if (data) {
|
|
|
|
|
if (!data?.data) {
|
|
|
|
|
return (
|
|
|
|
|
<div className="py-12">
|
2025-03-28 12:05:40 +00:00
|
|
|
<GradientTitle title={"No voting to show on the site"} size="big" />
|
2024-08-19 12:44:56 +00:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="flex flex-col gap-[20px] sm:gap-[40px] w-full items-center">
|
2025-03-28 12:05:40 +00:00
|
|
|
{data.data.description ? (
|
|
|
|
|
<PageBage title={data.data.description} />
|
|
|
|
|
) : null}
|
2024-08-19 12:44:56 +00:00
|
|
|
|
2025-03-28 12:05:40 +00:00
|
|
|
{eventStatus === "Finished" && <Confetti />}
|
2025-01-06 11:43:35 +00:00
|
|
|
|
2024-08-19 12:44:56 +00:00
|
|
|
{data.data.banner ? (
|
|
|
|
|
<div className="relative w-full md:min-h-[150px] md:h-auto h-[100px] ">
|
|
|
|
|
{mobile ? (
|
|
|
|
|
<Image
|
|
|
|
|
fill
|
2025-03-28 12:05:40 +00:00
|
|
|
src={
|
|
|
|
|
data.data.banner_mobile !== null
|
|
|
|
|
? data.data.banner_mobile
|
|
|
|
|
: data.data.banner
|
|
|
|
|
}
|
2024-08-19 12:44:56 +00:00
|
|
|
alt={data.data.title}
|
|
|
|
|
unselectable="off"
|
|
|
|
|
unoptimized
|
|
|
|
|
className="rounded-[40px]"
|
|
|
|
|
/>
|
|
|
|
|
) : (
|
|
|
|
|
<Image
|
|
|
|
|
fill
|
|
|
|
|
src={data.data.banner}
|
|
|
|
|
alt={data.data.title}
|
|
|
|
|
unselectable="off"
|
|
|
|
|
unoptimized
|
|
|
|
|
className="rounded-[40px]"
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
) : null}
|
|
|
|
|
|
|
|
|
|
<div className="flex flex-col gap-[10px] sm:gap-[20px] w-full items-center">
|
|
|
|
|
{/* {data.data.title ? <GradientTitle title={data.data.title} size="big" /> : null} */}
|
|
|
|
|
|
|
|
|
|
{data.data.ends_at && data.data.starts_at ? (
|
2024-09-03 12:35:46 +00:00
|
|
|
<Countdown
|
|
|
|
|
endsAt={data.data.ends_at}
|
|
|
|
|
startsAt={data.data.starts_at}
|
|
|
|
|
setVoteStatus={setVoteStatus}
|
2024-10-17 13:31:55 +00:00
|
|
|
setEventStatus={setEventStatus}
|
|
|
|
|
eventStatus={eventStatus}
|
2024-09-03 12:35:46 +00:00
|
|
|
/>
|
2024-08-19 12:44:56 +00:00
|
|
|
) : null}
|
|
|
|
|
|
|
|
|
|
<div className="flex w-full flex-col items-center gap-[10px] sm:gap-[20px]">
|
2025-03-28 12:05:40 +00:00
|
|
|
{winnersCount > 1 ? (
|
|
|
|
|
<GradientTitle title="победители" size="small" />
|
|
|
|
|
) : null}
|
2024-08-19 12:44:56 +00:00
|
|
|
|
2024-09-03 12:35:46 +00:00
|
|
|
{participantsData && participantsData[0].votes_count > 0 ? (
|
2024-08-19 12:44:56 +00:00
|
|
|
<div className="flex flex-col items-center overflow-hidden bg-fillNavyBlue rounded-[10px] sm:rounded-[30px] max-w-[940px] w-full px-[5px] py-[20px] sm:p-[20px] sm:gap-[20px] gap-[10px]">
|
2024-09-10 12:36:03 +00:00
|
|
|
{participantsData.map((participant, index) =>
|
2025-03-28 12:05:40 +00:00
|
|
|
participant.votes_count ===
|
|
|
|
|
participantsData[0].votes_count ? (
|
2024-09-04 11:08:37 +00:00
|
|
|
participant.url ? (
|
|
|
|
|
<Link
|
2025-03-28 12:05:40 +00:00
|
|
|
href={participant.url ? participant.url : ""}
|
2024-09-04 11:08:37 +00:00
|
|
|
target="_blank"
|
2024-10-15 07:11:25 +00:00
|
|
|
className="w-full"
|
2025-03-28 12:05:40 +00:00
|
|
|
key={v4()}
|
|
|
|
|
>
|
2024-09-04 11:08:37 +00:00
|
|
|
<ParticipantCard
|
2024-09-10 12:36:03 +00:00
|
|
|
index={index}
|
2024-09-05 11:31:36 +00:00
|
|
|
hasUrl={true}
|
2025-03-28 12:05:40 +00:00
|
|
|
voteStatus={voteStatus ? voteStatus : ""}
|
2024-09-10 12:36:03 +00:00
|
|
|
isFirst={index === 0 ? true : false}
|
2024-09-04 11:08:37 +00:00
|
|
|
name={participant.title}
|
|
|
|
|
progress={participant.votes_percents}
|
|
|
|
|
votes={participant.votes_count}
|
|
|
|
|
voteCode={participant.vote_code}
|
2024-09-10 12:36:03 +00:00
|
|
|
number={index + 1}
|
2024-09-04 11:08:37 +00:00
|
|
|
photo={participant.photo}
|
|
|
|
|
smsNumber={data.data.sms_number}
|
|
|
|
|
winner={true}
|
|
|
|
|
/>
|
|
|
|
|
</Link>
|
|
|
|
|
) : (
|
2024-09-03 12:35:46 +00:00
|
|
|
<ParticipantCard
|
|
|
|
|
key={v4()}
|
2024-09-10 12:36:03 +00:00
|
|
|
index={index}
|
2024-09-05 11:31:36 +00:00
|
|
|
hasUrl={false}
|
2025-03-28 12:05:40 +00:00
|
|
|
voteStatus={voteStatus ? voteStatus : ""}
|
2024-09-10 12:36:03 +00:00
|
|
|
isFirst={index === 0 ? true : false}
|
2024-09-03 12:35:46 +00:00
|
|
|
name={participant.title}
|
|
|
|
|
progress={participant.votes_percents}
|
|
|
|
|
votes={participant.votes_count}
|
|
|
|
|
voteCode={participant.vote_code}
|
2024-09-10 12:36:03 +00:00
|
|
|
number={index + 1}
|
2024-09-03 12:35:46 +00:00
|
|
|
photo={participant.photo}
|
|
|
|
|
smsNumber={data.data.sms_number}
|
|
|
|
|
winner={true}
|
|
|
|
|
/>
|
2024-09-04 11:08:37 +00:00
|
|
|
)
|
2025-03-28 12:05:40 +00:00
|
|
|
) : null
|
2024-08-19 12:44:56 +00:00
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
) : null}
|
|
|
|
|
|
2025-03-28 12:05:40 +00:00
|
|
|
{winnersCount > 1 ? (
|
|
|
|
|
<div className="w-full h-[1px] bg-[#3636A3]"></div>
|
|
|
|
|
) : null}
|
2024-08-19 12:44:56 +00:00
|
|
|
</div>
|
2024-09-10 12:36:03 +00:00
|
|
|
|
2024-09-04 11:08:37 +00:00
|
|
|
<div className="flex flex-col items-center max-w-[940px] w-full gap-5 justify-center mx-auto">
|
|
|
|
|
{participantsData
|
2024-09-10 12:36:03 +00:00
|
|
|
? participantsData.map((participant, index) =>
|
2024-09-19 12:17:04 +00:00
|
|
|
!hasVotes ? (
|
2024-09-04 11:08:37 +00:00
|
|
|
participant.url ? (
|
|
|
|
|
<Link
|
2025-03-28 12:05:40 +00:00
|
|
|
href={participant.url ? participant.url : ""}
|
2024-09-04 11:08:37 +00:00
|
|
|
target="_blank"
|
2024-10-15 07:11:25 +00:00
|
|
|
className="w-full mx-auto"
|
2025-03-28 12:05:40 +00:00
|
|
|
key={v4()}
|
|
|
|
|
>
|
2024-09-04 11:08:37 +00:00
|
|
|
<ParticipantCard
|
2024-09-10 12:36:03 +00:00
|
|
|
index={index}
|
2024-09-05 11:31:36 +00:00
|
|
|
hasUrl={true}
|
2025-03-28 12:05:40 +00:00
|
|
|
voteStatus={voteStatus ? voteStatus : ""}
|
2024-09-10 12:36:03 +00:00
|
|
|
isFirst={index === 0 ? true : false}
|
2024-09-04 11:08:37 +00:00
|
|
|
name={participant.title}
|
|
|
|
|
progress={participant.votes_percents}
|
|
|
|
|
votes={participant.votes_count}
|
|
|
|
|
voteCode={participant.vote_code}
|
2024-09-10 12:36:03 +00:00
|
|
|
number={index + 1}
|
2024-09-04 11:08:37 +00:00
|
|
|
photo={participant.photo}
|
|
|
|
|
smsNumber={data.data.sms_number}
|
|
|
|
|
winner={false}
|
|
|
|
|
/>
|
|
|
|
|
</Link>
|
|
|
|
|
) : (
|
|
|
|
|
<ParticipantCard
|
2024-09-05 11:31:36 +00:00
|
|
|
hasUrl={false}
|
2024-09-04 11:08:37 +00:00
|
|
|
key={v4()}
|
2024-09-10 12:36:03 +00:00
|
|
|
index={index}
|
2025-03-28 12:05:40 +00:00
|
|
|
voteStatus={voteStatus ? voteStatus : ""}
|
2024-09-10 12:36:03 +00:00
|
|
|
isFirst={index === 0 ? true : false}
|
2024-09-04 11:08:37 +00:00
|
|
|
name={participant.title}
|
|
|
|
|
progress={participant.votes_percents}
|
|
|
|
|
votes={participant.votes_count}
|
|
|
|
|
voteCode={participant.vote_code}
|
2024-09-10 12:36:03 +00:00
|
|
|
number={index + 1}
|
2024-09-04 11:08:37 +00:00
|
|
|
photo={participant.photo}
|
|
|
|
|
smsNumber={data.data.sms_number}
|
|
|
|
|
winner={false}
|
|
|
|
|
/>
|
|
|
|
|
)
|
2024-09-19 12:17:04 +00:00
|
|
|
) : (
|
2025-03-28 12:05:40 +00:00
|
|
|
participant.votes_count !==
|
|
|
|
|
participantsData[0].votes_count &&
|
2024-09-19 12:17:04 +00:00
|
|
|
(participant.url ? (
|
|
|
|
|
<Link
|
2025-03-28 12:05:40 +00:00
|
|
|
href={participant.url ? participant.url : ""}
|
2024-09-19 12:17:04 +00:00
|
|
|
target="_blank"
|
2024-10-15 07:11:25 +00:00
|
|
|
className="w-full mx-auto"
|
2025-03-28 12:05:40 +00:00
|
|
|
key={v4()}
|
|
|
|
|
>
|
2024-09-19 12:17:04 +00:00
|
|
|
<ParticipantCard
|
|
|
|
|
index={index}
|
|
|
|
|
hasUrl={true}
|
2025-03-28 12:05:40 +00:00
|
|
|
voteStatus={voteStatus ? voteStatus : ""}
|
2024-09-19 12:17:04 +00:00
|
|
|
isFirst={index === 0 ? true : false}
|
|
|
|
|
name={participant.title}
|
|
|
|
|
progress={participant.votes_percents}
|
|
|
|
|
votes={participant.votes_count}
|
|
|
|
|
voteCode={participant.vote_code}
|
|
|
|
|
number={index + 1}
|
|
|
|
|
photo={participant.photo}
|
|
|
|
|
smsNumber={data.data.sms_number}
|
|
|
|
|
winner={false}
|
|
|
|
|
/>
|
|
|
|
|
</Link>
|
|
|
|
|
) : (
|
|
|
|
|
<ParticipantCard
|
|
|
|
|
hasUrl={false}
|
|
|
|
|
key={v4()}
|
|
|
|
|
index={index}
|
2025-03-28 12:05:40 +00:00
|
|
|
voteStatus={voteStatus ? voteStatus : ""}
|
2024-09-19 12:17:04 +00:00
|
|
|
isFirst={index === 0 ? true : false}
|
|
|
|
|
name={participant.title}
|
|
|
|
|
progress={participant.votes_percents}
|
|
|
|
|
votes={participant.votes_count}
|
|
|
|
|
voteCode={participant.vote_code}
|
|
|
|
|
number={index + 1}
|
|
|
|
|
photo={participant.photo}
|
|
|
|
|
smsNumber={data.data.sms_number}
|
|
|
|
|
winner={false}
|
|
|
|
|
/>
|
|
|
|
|
))
|
2025-03-28 12:05:40 +00:00
|
|
|
)
|
2024-09-04 11:08:37 +00:00
|
|
|
)
|
|
|
|
|
: null}
|
|
|
|
|
</div>
|
2024-08-19 12:44:56 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
return (
|
|
|
|
|
<main className="h-full py-[100px]">
|
|
|
|
|
<div className="container">
|
|
|
|
|
<Loader />
|
|
|
|
|
</div>
|
|
|
|
|
</main>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default ParticipantsList;
|