Skip to content

Commit

Permalink
Merge pull request #163 from theredwillow/issue-70-explode-files
Browse files Browse the repository at this point in the history
Exploding files: Part 1 (AdminSettings, Players, utils/debounce)
  • Loading branch information
karlromets authored Jan 23, 2025
2 parents c67f8e4 + b35dcfc commit 37d06bb
Show file tree
Hide file tree
Showing 14 changed files with 255 additions and 224 deletions.
3 changes: 3 additions & 0 deletions public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@
"You have been blindfolded...": "You have been blindfolded...",
"Reset Mistakes": "Reset Mistakes",
"Version": "Version",
"Remove player's blindfold": "Remove player's blindfold",
"Blindfold player": "Blindfold player",
"Remove player from game": "Remove player from game",
"errors": {
"room_not_found": "Room not found",
"host_quit": "Host quit the game",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@
"email": "correo electr\u00f3nico",
"source code": "c\u00f3digo fuente",
"Question": "Pregunta",
"Remove player's blindfold": "Quitarle la venda de los ojos al jugador",
"Blindfold player": "Ponerle una venda en los ojos al jugador",
"Remove player from game": "Eliminar jugador del juego",
"errors": {
"room_not_found": "Sala no encontrada",
"host_quit": "El anfitrión abandonó el juego",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/et/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@
"You have been blindfolded...": "Sind on pimestatud...",
"Reset Mistakes": "Lähtesta vead",
"Version": "Versioon",
"Remove player's blindfold": "Eemalda mängija ekraani kate",
"Blindfold player": "Peitke mängija ekraan",
"Remove player from game": "Eemaldage mängija mängust",
"errors": {
"room_not_found": "Mängu ei leitud",
"host_quit": "Mängu juht lahkus mängust",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
"email": "email",
"source code": "code source",
"Question": "Question",
"Remove player's blindfold": "Retirer le bandeau du joueur",
"Blindfold player": "Mettre un bandeau sur les yeux du joueur",
"Remove player from game": "Supprimer le joueur du jeu",
"errors": {
"room_not_found": "Salle introuvable",
"host_quit": "L'hôte a quitté la partie",
Expand Down
3 changes: 3 additions & 0 deletions public/locales/id/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@
"donate": "menyumbangkan",
"email": "surel",
"source code": "Kode sumber",
"Remove player's blindfold": "Lepaskan penutup mata dari pemain",
"Blindfold player": "Tutup mata pemain",
"Remove player from game": "Hapus pemain dari permainan",
"errors": {
"room_not_found": "Room tidak ditemukan",
"host_quit": "Host keluar dari permainan",
Expand Down
54 changes: 54 additions & 0 deletions src/components/Admin/AdminSettings/BuzzerSoundSettings.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import InfoTooltip from "@/components/ui/tooltip";
import { useTranslation } from "react-i18next";

function BuzzerSoundSettings({game, setGame, send}) {
const { t } = useTranslation();

return (
<div className="flex flex-col space-y-4">
<div className="flex flex-col">
<div className="flex flex-row items-center space-x-5">
<div className="flex flex-row items-center space-x-2">
<InfoTooltip message={t("Allow players to hear sound on their devices when they press their buzzer")} />
<p className="text-xl normal-case text-foreground">{t("Player Buzzer Sounds")}</p>
</div>
<input
className="size-4 rounded placeholder:text-secondary-900"
checked={game.settings.player_buzzer_sound}
onChange={(e) => {
game.settings.player_buzzer_sound = e.target.checked;
if (!e.target.checked) {
game.settings.first_buzzer_sound_only = false;
}
setGame((prv) => ({ ...prv }));
send({ action: "data", data: game });
}}
type="checkbox"
></input>
</div>
</div>

<div className={`flex flex-col ${!game.settings.player_buzzer_sound ? "opacity-50" : ""}`}>
<div className="flex flex-row items-center space-x-5">
<div className="flex flex-row items-center space-x-2">
<InfoTooltip message={t("Only play sound for the first player to buzz in")} />
<p className="text-xl normal-case text-foreground">{t("First Press Only")}</p>
</div>
<input
className="size-4 rounded placeholder:text-secondary-900"
checked={game.settings.first_buzzer_sound_only}
disabled={!game.settings.player_buzzer_sound}
onChange={(e) => {
game.settings.first_buzzer_sound_only = e.target.checked;
setGame((prv) => ({ ...prv }));
send({ action: "data", data: game });
}}
type="checkbox"
></input>
</div>
</div>
</div>
);
}

export default BuzzerSoundSettings;
24 changes: 24 additions & 0 deletions src/components/Admin/AdminSettings/FinalRoundTitleChanger.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { debounce } from "@/lib/utils";
import { useTranslation } from "react-i18next";

function FinalRoundTitleChanger({game, setGame, send}) {
const { t } = useTranslation();
return (
<div className="flex flex-row items-center space-x-5">
<p className="text-xl text-foreground">{t("Final Round Title")}:</p>
<input
id="finalRoundTitleChangerInput"
className="w-32 rounded border-4 bg-secondary-500 p-1 text-xl text-foreground placeholder:text-secondary-900"
onChange={debounce((e) => {
game.settings.final_round_title = e.target.value;
setGame((prv) => ({ ...prv }));
send({ action: "data", data: game });
})}
defaultValue={game.settings.final_round_title}
placeholder={t("fast money")}
></input>
</div>
);
}

export default FinalRoundTitleChanger;
33 changes: 33 additions & 0 deletions src/components/Admin/AdminSettings/HideGameQuestions.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useTranslation } from "react-i18next";

function HideGameQuestions({game, setGame, send}) {
const { t } = useTranslation();

return (
<div className="flex flex-col">
<div className="flex flex-row items-center space-x-5">
<div>
<p className="text-xl normal-case text-foreground">{t("Hide questions")}:</p>
</div>
<input
id="hideQuestionsInput"
className="size-4 rounded placeholder:text-secondary-900"
checked={game.settings.hide_questions}
onChange={(e) => {
game.settings.hide_questions = e.target.checked;
setGame((prv) => ({ ...prv }));
send({ action: "data", data: game });
}}
type="checkbox"
></input>
</div>
<div>
<p className="max-w-xs text-sm normal-case italic text-secondary-900">
{t("hide questions on the game window and player buzzer screens")}
</p>
</div>
</div>
);
}

export default HideGameQuestions;
18 changes: 18 additions & 0 deletions src/components/Admin/AdminSettings/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import "@/i18n/i18n";
import ThemeSwitcher from "@/components/Admin/ThemeSwitcher";
import HideGameQuestions from "./HideGameQuestions";
import FinalRoundTitleChanger from "./FinalRoundTitleChanger";
import BuzzerSoundSettings from "./BuzzerSoundSettings";

export default function AdminSettings({game, setGame, send}) {
return (
<div className="flex flex-col items-center">
<div className="grid grid-cols-2 gap-x-48 gap-y-10">
<HideGameQuestions game={game} setGame={setGame} send={send} />
<ThemeSwitcher game={game} setGame={setGame} send={send} />
<FinalRoundTitleChanger game={game} setGame={setGame} send={send} />
<BuzzerSoundSettings game={game} setGame={setGame} send={send} />
</div>
</div>
);
}
180 changes: 97 additions & 83 deletions src/components/Admin/Players.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,103 +2,117 @@ import { useTranslation } from "react-i18next";
import "@/i18n/i18n";
import { Eye, EyeOff } from "lucide-react";

export default function Players(props) {
let game = props.game;
const { i18n, t } = useTranslation();
let team1 = [];
let team2 = [];
function PlayerActionButtons({ player, game, setGame, ws, room, teamNumber, index }) {
const { t } = useTranslation();

if (game.registeredPlayers) {
for (const [id, player] of Object.entries(game.registeredPlayers)) {
if (player.hasOwnProperty("team")) {
let content = { id: id, name: player.name, hidden: player.hidden };
player.team === 0 ? team1.push(content) : team2.push(content);
}
}
}
const toggleVisibility = () => {
game.registeredPlayers[player.id].hidden = !game.registeredPlayers[player.id].hidden;
setGame((prev) => ({ ...prev }));
ws.current.send(
JSON.stringify({
action: "data",
data: game,
room,
})
);
};

function teamSection(team, teamNumber) {
return (
<div>
{team.map((x, i) => (
<div key={`teamSection-player-${x.id}`} className="m-2 flex flex-row items-center space-x-5 border-2">
{/* information about player */}
<div className="grow">
<p className="uppercase text-foreground">{x.name}</p>
</div>
<div className="flex flex-row space-x-2">
{/* Toggle visibility button */}
<button
className={`border-4 ${x.hidden ? "bg-secondary-300" : "bg-success-300"} rounded-lg p-2 hover:opacity-80`}
id={`player${i}Team${teamNumber}HideGameButton`}
onClick={() => {
game.registeredPlayers[x.id].hidden = !game.registeredPlayers[x.id].hidden;
props.setGame((prv) => ({ ...prv }));
props.ws.current.send(
JSON.stringify({
action: "data",
data: game,
room: props.room,
})
);
}}
>
{x.hidden ? <EyeOff /> : <Eye />}
</button>
{/* Remove player button */}
<button
id={`player${i}Team${teamNumber}QuitButton`}
className="rounded-lg border-4 bg-failure-300 p-2 hover:bg-failure-500"
onClick={() => {
// props.send({action: "quit", id: })
props.ws.current.send(
JSON.stringify({
action: "quit",
host: false,
id: x.id,
room: props.room,
})
);
}}
>
{/* cancel.svg */}
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 717 718"
>
<path
d="M651.22 154c98 139 85 334-40 459s-318 137-458 40c-16-12-34-26-49-40c-15-15-28-32-39-49c-98-139-86-334 39-459s319-137 459-40c16 12 33 26 48 40c15 15 29 32 40 49zm-522 345l370-370c-104-63-242-50-331 39c-90 90-102 228-39 331zm458-280l-370 369c104 63 242 50 331-39c90-90 102-227 39-330z"
fill="#ffffff"
/>
<rect x="0" y="0" width="717" height="718" fill="rgba(0, 0, 0, 0)" />
</svg>
</button>
</div>
</div>
))}
</div>
const removePlayer = () => {
ws.current.send(
JSON.stringify({
action: "quit",
host: false,
id: player.id,
room,
})
);
}
};

return (
<div className="flex flex-row space-x-2">
{/* Toggle visibility button */}
<button
className={`border-4 ${player.hidden ? "bg-secondary-300" : "bg-success-300"} rounded-lg p-2 hover:opacity-80`}
id={`player${index}Team${teamNumber}HideGameButton`}
onClick={toggleVisibility}
title={t(player.hidden ? "Remove player's blindfold" : "Blindfold player")}
>
{player.hidden ? <EyeOff /> : <Eye />}
</button>
{/* Remove player button */}
<button
id={`player${index}Team${teamNumber}QuitButton`}
className="rounded-lg border-4 bg-failure-300 p-2 hover:bg-failure-500"
onClick={removePlayer}
title={t("Remove player from game")}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 717 718"
>
<path
d="M651.22 154c98 139 85 334-40 459s-318 137-458 40c-16-12-34-26-49-40c-15-15-28-32-39-49c-98-139-86-334 39-459s319-137 459-40c16 12 33 26 48 40c15 15 29 32 40 49zm-522 345l370-370c-104-63-242-50-331 39c-90 90-102 228-39 331zm458-280l-370 369c104 63 242 50 331-39c90-90 102-227 39-330z"
fill="#ffffff"
/>
<rect x="0" y="0" width="717" height="718" fill="rgba(0, 0, 0, 0)" />
</svg>
</button>
</div>
);
}

function TeamSection({ team, teamNumber, game, setGame, ws, room }) {
return (
<div>
{team.map((player, index) => (
<div key={`teamSection-player-${player.id}`} className="m-2 flex flex-row items-center space-x-5 border-2">
{/* Player information */}
<div className="grow">
<p className="uppercase text-foreground">{player.name}</p>
</div>
{/* Player action buttons */}
<PlayerActionButtons
player={player}
game={game}
setGame={setGame}
ws={ws}
room={room}
teamNumber={teamNumber}
index={index}
/>
</div>
))}
</div>
);
}

export default function Players({ game, setGame, ws, room }) {
const teams = [[], []];
Object.entries(game.registeredPlayers || []).forEach(([id, player]) => {
if ("team" in player) {
teams[player.team]?.push({ id, name: player.name, hidden: player.hidden });
}
});

return (
<div className="grow ">
<div className="grow">
<div className="flex h-48 grow flex-row overflow-y-scroll rounded border-4 p-2 text-center">
{/* team 1 section */}
{/* Team 1 section */}
<div className="grow">
<p className="text-foreground">{game.teams[0].name}</p>
<hr />
{teamSection(team1, 1)}
<TeamSection team={teams[0]} teamNumber={1} game={game} setGame={setGame} ws={ws} room={room} />
</div>
{/* seperator */}
{/* Separator */}
<div className="h-full border bg-secondary-300" />
{/* team 2 section */}
{/* Team 2 section */}
<div className="grow">
<p className="text-foreground">{game.teams[1].name}</p>
<hr />
{teamSection(team2, 2)}
<TeamSection team={teams[1]} teamNumber={2} game={game} setGame={setGame} ws={ws} room={room} />
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit 37d06bb

Please sign in to comment.