Add custom playlists

This commit is contained in:
2025-03-01 16:11:01 +01:00
parent 2fb5af4171
commit aa10b5b2cc
7 changed files with 450 additions and 10 deletions

View File

@@ -15,14 +15,17 @@ export const WaitingRoom = () => {
const [isHost, setIsHost] = useState(false);
const [username, setUsername] = useState("");
const [copied, setCopied] = useState(false);
const [playlists, setPlaylists] = useState({});
const [votes, setVotes] = useState({});
const [selectedPlaylist, setSelectedPlaylist] = useState(null);
const messageEndRef = useRef(null);
useEffect(() => {
// Check if the user is a host and get other initial data
send("check-host-status");
send("get-user-info");
send("get-room-users");
send("get-room-code");
send("get-playlist-options");
const handleHostStatus = (status) => {
setIsHost(status.isHost);
@@ -72,6 +75,14 @@ export const WaitingRoom = () => {
setCurrentState("Game");
};
const handlePlaylistOptions = (options) => {
setPlaylists(options);
};
const handleVotesUpdated = (newVotes) => {
setVotes(newVotes);
};
// Register event listeners
const cleanupHostStatus = on("host-status", handleHostStatus);
const cleanupUserInfo = on("user-info", handleUserInfo);
@@ -82,8 +93,9 @@ export const WaitingRoom = () => {
const cleanupUserDisconnected = on("user-disconnected", handleUserDisconnected);
const cleanupChatMessage = on("chat-message", handleChatMessage);
const cleanupGameStarted = on("game-started", handleGameStarted);
const cleanupPlaylistOptions = on("playlist-options", handlePlaylistOptions);
const cleanupVotesUpdated = on("playlist-votes-updated", handleVotesUpdated);
// Add welcome message
setMessages([{
system: true,
text: "Welcome to the waiting room! Waiting for others to join..."
@@ -99,6 +111,8 @@ export const WaitingRoom = () => {
cleanupUserDisconnected();
cleanupChatMessage();
cleanupGameStarted();
cleanupPlaylistOptions();
cleanupVotesUpdated();
};
}, [on, send, socket, setCurrentState]);
@@ -125,7 +139,6 @@ export const WaitingRoom = () => {
};
const handleLeaveRoom = () => {
// Disconnect from the current room
if (socket) {
socket.disconnect();
}
@@ -138,7 +151,40 @@ export const WaitingRoom = () => {
setTimeout(() => setCopied(false), 2000);
};
const minPlayersToStart = 1; // Set your minimum players requirement here
const handleVote = (playlistId) => {
setSelectedPlaylist(playlistId);
send("vote-playlist", { playlistId });
};
const getVoteCount = (playlistId) => {
return votes[playlistId]?.length || 0;
};
const renderPlaylists = () => (
<div className="playlists-grid">
{Object.entries(playlists).map(([genre, playlist]) => (
<div
key={playlist.id}
className={`playlist-card ${selectedPlaylist === playlist.id ? 'selected' : ''}`}
onClick={() => handleVote(playlist.id)}
>
<div className="playlist-thumbnail">
<img src={playlist.thumbnail.url} alt={playlist.title} />
<div className="vote-count">
<span>{getVoteCount(playlist.id)}</span>
<span className="vote-label">votes</span>
</div>
</div>
<div className="playlist-info">
<h3>{genre.toUpperCase()}</h3>
<p>{playlist.songCount} songs</p>
</div>
</div>
))}
</div>
);
const minPlayersToStart = 1;
const canStartGame = isHost && users.length >= minPlayersToStart;
return (
@@ -227,6 +273,11 @@ export const WaitingRoom = () => {
<button onClick={handleSendMessage}>Senden</button>
</div>
</div>
<div className="playlist-section">
<h2>Vote for Playlist</h2>
{renderPlaylists()}
</div>
</div>
</div>
);

View File

@@ -330,6 +330,86 @@
font-size: 1.4rem
margin: 0
.playlist-section
margin-bottom: 30px
h2
color: $white
text-align: center
margin-bottom: 20px
font-size: 24px
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5)
.playlists-grid
display: grid
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))
gap: 20px
padding: 20px
.playlist-card
background: rgba(255, 255, 255, 0.1)
border-radius: 15px
overflow: hidden
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275)
cursor: pointer
border: 2px solid transparent
&:hover
transform: translateY(-5px)
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3)
background: rgba(255, 255, 255, 0.15)
&.selected
border-color: $yellow
box-shadow: 0 0 30px rgba($yellow, 0.3)
.playlist-thumbnail
position: relative
width: 100%
padding-top: 56.25%
img
position: absolute
top: 0
left: 0
width: 100%
height: 100%
object-fit: cover
.vote-count
position: absolute
top: 10px
right: 10px
background: rgba(0, 0, 0, 0.8)
padding: 8px 12px
border-radius: 20px
display: flex
flex-direction: column
align-items: center
span
color: $white
&:first-child
font-size: 24px
font-weight: bold
&.vote-label
font-size: 12px
opacity: 0.8
.playlist-info
padding: 15px
h3
color: $white
margin-bottom: 5px
font-size: 18px
p
color: rgba(255, 255, 255, 0.7)
font-size: 14px
@keyframes pop
0%
transform: scale(1)