Some checks failed
Publish Docker image / Push Docker image to Docker Hub (push) Failing after 6m59s
199 lines
6.5 KiB
JavaScript
199 lines
6.5 KiB
JavaScript
import { useEffect, useState } from 'react';
|
|
import { useGame } from '../context/GameContext';
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
import { faTrophy, faMusic, faCrown, faClock } from '@fortawesome/free-solid-svg-icons';
|
|
import YouTubeEmbed from './YouTubeEmbed';
|
|
import { getDisplayName } from '../utils/playerUtils';
|
|
|
|
const BattleResultScreen = () => {
|
|
const { lobby, currentPlayer, isHost, proceedToNextBattle } = useGame();
|
|
const [countdown, setCountdown] = useState(10); // Auto-advance after 10 seconds
|
|
const [showConfetti, setShowConfetti] = useState(true);
|
|
|
|
// Use previousBattle from the lobby state
|
|
const previousBattle = lobby?.previousBattle;
|
|
|
|
// Extract winning song
|
|
const winnerSongId = previousBattle?.winner;
|
|
const winningSong = winnerSongId === previousBattle?.song1?.id
|
|
? previousBattle?.song1
|
|
: previousBattle?.song2;
|
|
|
|
const losingSong = winnerSongId === previousBattle?.song1?.id
|
|
? previousBattle?.song2
|
|
: previousBattle?.song1;
|
|
|
|
const winningVotes = winnerSongId === previousBattle?.song1?.id
|
|
? previousBattle?.song1Votes
|
|
: previousBattle?.song2Votes;
|
|
|
|
const losingVotes = winnerSongId === previousBattle?.song1?.id
|
|
? previousBattle?.song2Votes
|
|
: previousBattle?.song1Votes;
|
|
|
|
// Get the player who submitted the winning song
|
|
const findSubmitter = (song) => {
|
|
if (!lobby || !song) return null;
|
|
|
|
const submitter = lobby.players.find(p => p.id === song.submittedById);
|
|
return submitter;
|
|
};
|
|
|
|
const winnerSubmitter = findSubmitter(winningSong);
|
|
|
|
// YouTube video ID extraction for the winner
|
|
const getYouTubeId = (url) => {
|
|
if (!url) return null;
|
|
|
|
const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/;
|
|
const match = url.match(regExp);
|
|
|
|
return (match && match[2].length === 11) ? match[2] : null;
|
|
};
|
|
|
|
const winnerVideoId = getYouTubeId(winningSong?.youtubeLink);
|
|
|
|
// Auto-advance countdown
|
|
useEffect(() => {
|
|
if (countdown > 0) {
|
|
const timer = setInterval(() => {
|
|
setCountdown(prev => {
|
|
if (prev <= 1) {
|
|
clearInterval(timer);
|
|
// Only auto-advance if host, otherwise wait for host
|
|
if (isHost) {
|
|
proceedToNextBattle();
|
|
}
|
|
return 0;
|
|
}
|
|
return prev - 1;
|
|
});
|
|
}, 1000);
|
|
|
|
return () => clearInterval(timer);
|
|
}
|
|
}, [countdown, isHost, proceedToNextBattle]);
|
|
|
|
// Confetti effect
|
|
useEffect(() => {
|
|
if (showConfetti) {
|
|
const createConfetti = () => {
|
|
const confettiContainer = document.createElement('div');
|
|
confettiContainer.className = 'confetti';
|
|
|
|
// Random position, size, and color
|
|
const left = Math.random() * 100;
|
|
const colors = ['#f94144', '#f3722c', '#f8961e', '#f9c74f', '#90be6d', '#43aa8b', '#577590'];
|
|
const color = colors[Math.floor(Math.random() * colors.length)];
|
|
const size = Math.random() * 0.5 + 0.3; // Between 0.3 and 0.8rem
|
|
const rotation = Math.random() * 360; // Random rotation
|
|
const duration = Math.random() * 2 + 1; // Between 1 and 3 seconds
|
|
|
|
confettiContainer.style.left = `${left}%`;
|
|
confettiContainer.style.backgroundColor = color;
|
|
confettiContainer.style.width = `${size}rem`;
|
|
confettiContainer.style.height = `${size * 0.6}rem`;
|
|
confettiContainer.style.transform = `rotate(${rotation}deg)`;
|
|
confettiContainer.style.animation = `confetti-fall ${duration}s linear forwards`;
|
|
|
|
document.querySelector('.battle-result-screen').appendChild(confettiContainer);
|
|
|
|
// Remove after animation
|
|
setTimeout(() => {
|
|
confettiContainer.remove();
|
|
}, duration * 1000);
|
|
};
|
|
|
|
// Create confetti pieces
|
|
const confettiInterval = setInterval(() => {
|
|
for (let i = 0; i < 3; i++) {
|
|
createConfetti();
|
|
}
|
|
}, 300);
|
|
|
|
// Stop confetti after a few seconds
|
|
setTimeout(() => {
|
|
clearInterval(confettiInterval);
|
|
setShowConfetti(false);
|
|
}, 4000);
|
|
|
|
return () => {
|
|
clearInterval(confettiInterval);
|
|
};
|
|
}
|
|
}, [showConfetti]);
|
|
|
|
if (!previousBattle || !winningSong) {
|
|
return (
|
|
<div className="battle-result-screen">
|
|
<h2>Nächster Kampf wird vorbereitet...</h2>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="battle-result-screen">
|
|
<header>
|
|
<h1><FontAwesomeIcon icon={faTrophy} /> Gewinner dieser Runde</h1>
|
|
{countdown > 0 && (
|
|
<div className="countdown">
|
|
<FontAwesomeIcon icon={faClock} />
|
|
Nächster Kampf in {countdown}s
|
|
</div>
|
|
)}
|
|
</header>
|
|
|
|
<div className="winner-announcement">
|
|
<div className="song-cards">
|
|
<div className="song-card winner">
|
|
<div className="victory-badge">
|
|
<FontAwesomeIcon icon={faCrown} /> Gewinner
|
|
</div>
|
|
|
|
<div className="song-info">
|
|
<h2>{winningSong.title}</h2>
|
|
<p className="artist">{winningSong.artist}</p>
|
|
|
|
{!lobby?.settings?.hidePlayerNames && winnerSubmitter && (
|
|
<p className="submitter">
|
|
Eingereicht von: {getDisplayName(winnerSubmitter, lobby, currentPlayer)}
|
|
</p>
|
|
)}
|
|
|
|
<div className="vote-count">
|
|
<span className="votes">{winningVotes} Stimmen</span>
|
|
</div>
|
|
</div>
|
|
|
|
{winnerVideoId ? (
|
|
<div className="winner-video">
|
|
<YouTubeEmbed videoId={winnerVideoId} autoplay={true} />
|
|
</div>
|
|
) : (
|
|
<div className="no-video">
|
|
<FontAwesomeIcon icon={faMusic} className="pulse-icon" />
|
|
<span>Kein Video verfügbar</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{losingSong && (
|
|
<div className="song-card loser">
|
|
<div className="versus">VS</div>
|
|
<div className="song-info">
|
|
<h3>{losingSong.title}</h3>
|
|
<p className="artist">{losingSong.artist}</p>
|
|
<div className="vote-count">
|
|
<span className="votes">{losingVotes} Stimmen</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default BattleResultScreen;
|