59 lines
1.5 KiB
TypeScript
59 lines
1.5 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { useParams } from "react-router-dom";
|
|
|
|
import { debounce } from "./utils";
|
|
import { socket } from "./socket";
|
|
import { useAppSelector } from "./hooks";
|
|
import { selectSignature } from "./store/contestantSlice";
|
|
|
|
const Contestant = () => {
|
|
const { room } = useParams();
|
|
|
|
const signature = useAppSelector(selectSignature);
|
|
const [canBuzz, setCanBuzz] = useState<boolean>(false);
|
|
const [active, setActive] = useState<boolean>(false);
|
|
|
|
useEffect(() => {
|
|
socket.emit("contestant-join", { room, signature });
|
|
socket.on("clue-clock-on", () => setCanBuzz(true));
|
|
socket.on("clue-clock-off", () => setCanBuzz(false));
|
|
socket.on("contestant-buzzed", ({ sid }) => {
|
|
setCanBuzz(false);
|
|
if (sid === socket.id) {
|
|
setActive(true);
|
|
}
|
|
});
|
|
socket.on("contestant-scores", () => setActive(false));
|
|
socket.on("contestant-penalized", () => {
|
|
setActive(false);
|
|
setCanBuzz(true);
|
|
});
|
|
}, []);
|
|
|
|
const handleBuzz = debounce(() => {
|
|
if (canBuzz) {
|
|
socket.emit("buzz");
|
|
}
|
|
});
|
|
|
|
return (
|
|
<div>
|
|
<svg viewBox={`0 0 100 100`}>
|
|
<circle
|
|
cx={50}
|
|
cy={50}
|
|
r={30}
|
|
fill={active ? "green" : canBuzz ? "red" : "grey"}
|
|
stroke="black"
|
|
onClick={handleBuzz}
|
|
/>
|
|
<text x={50} y={50} textAnchor="middle">
|
|
Buzz
|
|
</text>
|
|
</svg>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Contestant;
|