This commit is contained in:
Kakabay 2025-01-03 18:33:10 +05:00
parent 9c560f9c99
commit 2222275fc0
2 changed files with 49 additions and 50 deletions

View File

@ -38,6 +38,7 @@ const LotteryWinnersSection = ({ lotteryStatus }: { lotteryStatus: string }) =>
const pingIntervalRef = useRef<NodeJS.Timeout | null>(null); const pingIntervalRef = useRef<NodeJS.Timeout | null>(null);
const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null); const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const mountedRef = useRef(false); const mountedRef = useRef(false);
let reconnectAttempts: number;
// Initialize winners from lottery data // Initialize winners from lottery data
useEffect(() => { useEffect(() => {
@ -52,56 +53,58 @@ const LotteryWinnersSection = ({ lotteryStatus }: { lotteryStatus: string }) =>
} }
}, [lotteryData]); }, [lotteryData]);
// WebSocket Setup
useEffect(() => { useEffect(() => {
mountedRef.current = true; mountedRef.current = true;
const setupWebSocket = () => { const setupWebSocket = () => {
if (wsRef.current) return; // Prevent duplicate connections if (wsRef.current) return;
try { try {
const socket = new WebSocket(WEBSOCKET_URL); const socket = new WebSocket(WEBSOCKET_URL);
wsRef.current = socket; wsRef.current = socket;
socket.addEventListener('open', () => { socket.addEventListener('open', () => {
console.log('WebSocket Connected'); console.log('WebSocket Connected');
setWsStatus('connected'); setWsStatus('connected');
reconnectAttempts = 0; // Reset reconnect attempts
pingIntervalRef.current = setInterval(() => {
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({ type: 'ping' }));
}
}, PING_INTERVAL);
}); });
socket.addEventListener('message', handleWebSocketMessage); socket.addEventListener('message', handleWebSocketMessage);
socket.addEventListener('error', () => { socket.addEventListener('error', (error) => {
console.error('WebSocket Error'); console.error('WebSocket Error:', error);
setWsStatus('error'); setWsStatus('error');
reconnectWebSocket();
}); });
socket.addEventListener('close', () => { socket.addEventListener('close', (event) => {
console.log('WebSocket Closed'); console.log('❌ WebSocket Closed:', event);
console.log(`Code: ${event.code}, Reason: ${event.reason}`);
setWsStatus('error'); setWsStatus('error');
reconnectWebSocket();
// Only reconnect if closure is abnormal
if (event.code !== 1000) {
reconnectWebSocket();
}
}); });
} catch (error) { } catch (error) {
console.error('Error creating WebSocket:', error); console.error('Error creating WebSocket:', error);
setWsStatus('error'); setWsStatus('error');
reconnectWebSocket(); reconnectWebSocket();
} }
}; };
const reconnectWebSocket = () => { const reconnectWebSocket = () => {
if (reconnectTimeoutRef.current) return; // Prevent multiple reconnect attempts if (!mountedRef.current) return;
const delay = Math.min(1000 * 2 ** reconnectAttempts, 30000); // Exponential backoff
reconnectAttempts += 1;
console.log(`Reconnecting in ${delay / 1000} seconds...`);
reconnectTimeoutRef.current = setTimeout(() => { reconnectTimeoutRef.current = setTimeout(() => {
console.log('Reconnecting WebSocket...');
setupWebSocket(); setupWebSocket();
reconnectTimeoutRef.current = null; }, delay);
}, RECONNECT_INTERVAL);
}; };
setupWebSocket(); setupWebSocket();
@ -201,30 +204,28 @@ const LotteryWinnersSection = ({ lotteryStatus }: { lotteryStatus: string }) =>
<div <div
className="flex flex-col items-center rounded-[32px] gap-[40px]" className="flex flex-col items-center rounded-[32px] gap-[40px]"
style={{ background: 'linear-gradient(180deg, #F0ECF4 0%, #E1E0FF 43.5%)' }}> style={{ background: 'linear-gradient(180deg, #F0ECF4 0%, #E1E0FF 43.5%)' }}>
<AnimatePresence mode="wait"> <div className="flex items-center justify-center w-full min-h-[240px]">
<div className="flex items-center justify-center w-full min-h-[240px]"> {winnerSelectingStatus === 'not-selected' ||
{winnerSelectingStatus === 'not-selected' || winnerSelectingStatus === 'is-selecting' ? (
winnerSelectingStatus === 'is-selecting' ? ( <AnimatedText
text={displayText}
className="text-center flex items-center justify-center text-[100px] leading-[108px] text-[#E65E19]"
/>
) : (
<div className="flex flex-col items-center justify-center">
<AnimatedText <AnimatedText
text={displayText} text={displayText}
className="text-center flex items-center justify-center text-[100px] leading-[108px] text-[#E65E19]" className="text-center text-[56px] leading-[64px] text-[#E65E19]"
/> />
) : ( {winnerText && (
<div className="flex flex-col items-center justify-center">
<AnimatedText <AnimatedText
text={displayText} text={winnerText}
className="text-center text-[56px] leading-[64px] text-[#E65E19]" className="text-center text-[80px] leading-[88px] text-[#E65E19]"
/> />
{winnerText && ( )}
<AnimatedText </div>
text={winnerText} )}
className="text-center text-[80px] leading-[88px] text-[#E65E19]" </div>
/>
)}
</div>
)}
</div>
</AnimatePresence>
<div className="z-10"> <div className="z-10">
<LotterySlotCounter numberString={currentNumber} isAnimating={isSlotCounterAnimating} /> <LotterySlotCounter numberString={currentNumber} isAnimating={isSlotCounterAnimating} />
</div> </div>

View File

@ -15,17 +15,15 @@ const LotteryWinnersList = ({ winners }: { winners: LotteryWinnerDataSimplified[
<motion.div <motion.div
layout layout
className="grid md:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-x-2 gap-y-4 w-full "> className="grid md:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-x-2 gap-y-4 w-full ">
<AnimatePresence mode="wait"> {winners.map((item, index) => (
{winners.map((item, index) => ( <LotteryWinner
<LotteryWinner key={v4()}
key={v4()} phone={item.client}
phone={item.client} ticket={item.ticket}
ticket={item.ticket} winnerNumber={item.winner_no}
winnerNumber={item.winner_no} isNew={index === winners.length - 1}
isNew={index === winners.length - 1} />
/> ))}
))}
</AnimatePresence>
</motion.div> </motion.div>
</div> </div>
); );