diff --git a/src/Contestant.tsx b/src/Contestant.tsx index 108319a..f9c49e2 100644 --- a/src/Contestant.tsx +++ b/src/Contestant.tsx @@ -11,10 +11,23 @@ const Contestant = () => { 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(() => { @@ -30,7 +43,7 @@ const Contestant = () => { cx={50} cy={50} r={30} - fill={canBuzz ? "red" : "grey"} + fill={active ? "green" : canBuzz ? "red" : "grey"} stroke="black" onClick={handleBuzz} /> diff --git a/src/Host.tsx b/src/Host.tsx index deda5ef..8fec7b9 100644 --- a/src/Host.tsx +++ b/src/Host.tsx @@ -2,8 +2,12 @@ import { useEffect } from "react"; import { useParams } from "react-router-dom"; import { socket } from "./socket"; -import { useAppSelector } from "./hooks"; -import { selectCategories, selectActiveClue } from "./store/cluesSlice"; +import { useAppSelector, useAppDispatch } from "./hooks"; +import { + selectCategories, + selectActiveClue, + clearActiveClue, +} from "./store/cluesSlice"; import Pregame from "./host/Pregame"; import ActiveClue from "./host/ActiveClue"; import CluesDisplay from "./host/CluesDisplay"; @@ -11,11 +15,15 @@ import CluesDisplay from "./host/CluesDisplay"; const Host = () => { const { room } = useParams(); + const dispatch = useAppDispatch(); + const activeClue = useAppSelector(selectActiveClue); const categories = useAppSelector(selectCategories); useEffect(() => { socket.emit("host-join", { room }); + socket.on("contestant-scores", () => dispatch(clearActiveClue())); + socket.on("clue-clock-off", () => dispatch(clearActiveClue())); }, []); if (categories.length < 6) { diff --git a/src/host/ActiveClue.tsx b/src/host/ActiveClue.tsx index 36dec1f..eed1877 100644 --- a/src/host/ActiveClue.tsx +++ b/src/host/ActiveClue.tsx @@ -1,22 +1,45 @@ +import { useState, useEffect } from "react"; import { Container, Stack, Button } from "react-bootstrap"; import type { Clue } from "../store/cluesSlice"; import { socket } from "../socket"; +import { debounce } from "../utils"; interface Props { activeClue: Clue; } -// TODO implement timer +type Mode = "reading" | "running" | "buzzed"; const ActiveClue = ({ activeClue }: Props) => { + const [mode, setMode] = useState<Mode>("reading"); + useEffect(() => { + socket.on("clue-clock-on", () => { + setMode("running"); + }); + socket.on("contestant-buzzed", () => { + setMode("buzzed"); + }); + }, []); + const startTimer = debounce(() => socket.emit("start-clue-clock")); + const contestantCorrect = debounce(() => socket.emit("contestant-correct")); + const contestantIncorrect = debounce(() => { + setMode("running"); + socket.emit("contestant-incorrect"); + }); return ( <Container> <p>{activeClue.question}</p> <Stack gap={3} className="text-center"> - <Button onClick={() => socket.emit("start-clue-clock")}> - Start Timer - </Button> + {mode === "reading" && ( + <Button onClick={startTimer}>Start Timer</Button> + )} + {mode === "buzzed" && ( + <> + <Button onClick={contestantCorrect}>Correct</Button> + <Button onClick={contestantIncorrect}>Incorrect</Button> + </> + )} </Stack> </Container> ); diff --git a/src/store/cluesSlice.ts b/src/store/cluesSlice.ts index d57988c..0a6b816 100644 --- a/src/store/cluesSlice.ts +++ b/src/store/cluesSlice.ts @@ -38,10 +38,14 @@ export const cluesSlice = createSlice({ setActiveClue: (state, { payload }: PayloadAction<Clue | null>) => { state.activeClue = payload; }, + clearActiveClue: (state) => { + state.activeClue = null; + }, }, }); -export const { setCategories, setActiveClue } = cluesSlice.actions; +export const { setCategories, setActiveClue, clearActiveClue } = + cluesSlice.actions; export const selectCategories = (state: RootState) => state.clues.categories; export const selectActiveClue = (state: RootState) => state.clues.activeClue;