145 lines
4.0 KiB
TypeScript
145 lines
4.0 KiB
TypeScript
import { useState, useEffect, useRef } from "react";
|
|
import { mapOptions } from "../constants";
|
|
import { shuffleArray } from "../utils";
|
|
import { voteService } from "../services/api";
|
|
|
|
export function useVoteLogic() {
|
|
const [cards, setCards] = useState(() => shuffleArray(mapOptions));
|
|
const [selectedCard, setSelectedCard] = useState<number | null>(null);
|
|
const [showConfirmation, setShowConfirmation] = useState(false);
|
|
const [isSubmitted, setIsSubmitted] = useState(false);
|
|
const [voteTimestamp, setVoteTimestamp] = useState<string | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [pollEnded, setPollEnded] = useState(false);
|
|
const dragItem = useRef<number | null>(null);
|
|
const dragOverItem = useRef<number | null>(null);
|
|
|
|
useEffect(() => {
|
|
checkVoteStatus();
|
|
}, []);
|
|
|
|
const checkVoteStatus = async () => {
|
|
try {
|
|
const data = await voteService.checkVoteStatus();
|
|
setPollEnded(data.isPollEnded);
|
|
|
|
if (data.hasVoted && data.vote) {
|
|
setVoteTimestamp(data.timestamp || null);
|
|
setCards(data.vote);
|
|
setIsSubmitted(true);
|
|
}
|
|
} catch (error) {
|
|
console.error("Failed to check vote status:", error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const handleDragStart = (index: number) => {
|
|
if (isSubmitted || pollEnded) return;
|
|
dragItem.current = index;
|
|
};
|
|
|
|
const handleDragEnter = (index: number) => {
|
|
if (isSubmitted || pollEnded) return;
|
|
dragOverItem.current = index;
|
|
};
|
|
|
|
const handleDragEnd = () => {
|
|
if (isSubmitted || pollEnded) return;
|
|
const from = dragItem.current;
|
|
const to = dragOverItem.current;
|
|
if (from === null || to === null || from === to) return;
|
|
const updatedCards = [...cards];
|
|
const [removed] = updatedCards.splice(from, 1);
|
|
updatedCards.splice(to, 0, removed);
|
|
setCards(updatedCards);
|
|
dragItem.current = null;
|
|
dragOverItem.current = null;
|
|
};
|
|
|
|
const handleCardTap = (index: number) => {
|
|
if (isSubmitted || pollEnded) return;
|
|
|
|
if (selectedCard === null) {
|
|
setSelectedCard(index);
|
|
} else if (selectedCard === index) {
|
|
setSelectedCard(null);
|
|
} else {
|
|
const updatedCards = [...cards];
|
|
const [removed] = updatedCards.splice(selectedCard, 1);
|
|
updatedCards.splice(index, 0, removed);
|
|
setCards(updatedCards);
|
|
setSelectedCard(null);
|
|
}
|
|
};
|
|
|
|
const handleSubmit = () => {
|
|
setShowConfirmation(true);
|
|
};
|
|
|
|
const handleConfirmSubmit = async () => {
|
|
try {
|
|
await voteService.submitVote(cards);
|
|
setIsSubmitted(true);
|
|
setShowConfirmation(false);
|
|
setSelectedCard(null);
|
|
setVoteTimestamp(new Date().toISOString());
|
|
} catch (error) {
|
|
if (error instanceof Error) {
|
|
alert(`Error submitting vote: ${error.message}`);
|
|
} else {
|
|
alert("Failed to submit vote. Please try again.");
|
|
}
|
|
}
|
|
};
|
|
|
|
const handleCancelSubmit = () => {
|
|
setShowConfirmation(false);
|
|
};
|
|
|
|
const handleTouchStart = (index: number) => {
|
|
dragItem.current = index;
|
|
};
|
|
|
|
const handleTouchMove = (e: React.TouchEvent) => {
|
|
e.preventDefault();
|
|
const touch = e.touches[0];
|
|
const elementBelow = document.elementFromPoint(
|
|
touch.clientX,
|
|
touch.clientY
|
|
);
|
|
const cardElement = elementBelow?.closest(
|
|
"[data-card-index]"
|
|
) as HTMLElement;
|
|
if (cardElement) {
|
|
const index = parseInt(cardElement.dataset.cardIndex || "0");
|
|
dragOverItem.current = index;
|
|
}
|
|
};
|
|
|
|
const handleTouchEnd = () => {
|
|
handleDragEnd();
|
|
};
|
|
|
|
return {
|
|
cards,
|
|
selectedCard,
|
|
showConfirmation,
|
|
isSubmitted,
|
|
voteTimestamp,
|
|
loading,
|
|
pollEnded,
|
|
handleDragStart,
|
|
handleDragEnter,
|
|
handleDragEnd,
|
|
handleCardTap,
|
|
handleSubmit,
|
|
handleConfirmSubmit,
|
|
handleCancelSubmit,
|
|
handleTouchStart,
|
|
handleTouchMove,
|
|
handleTouchEnd,
|
|
};
|
|
}
|