mirror of
https://github.com/randyjc/Rahoot.git
synced 2026-09-08 12:13:15 +02:00
142 lines
3.9 KiB
TypeScript
142 lines
3.9 KiB
TypeScript
"use client"
|
|
|
|
import { CommonStatusDataMap } from "@rahoot/common/types/game/status"
|
|
import AnswerButton from "@rahoot/web/components/AnswerButton"
|
|
import QuestionMedia from "@rahoot/web/components/game/QuestionMedia"
|
|
import { useEvent, useSocket } from "@rahoot/web/contexts/socketProvider"
|
|
import { usePlayerStore } from "@rahoot/web/stores/player"
|
|
import {
|
|
ANSWERS_COLORS,
|
|
ANSWERS_ICONS,
|
|
SFX_ANSWERS_MUSIC,
|
|
SFX_ANSWERS_SOUND,
|
|
} from "@rahoot/web/utils/constants"
|
|
import clsx from "clsx"
|
|
import { useParams } from "next/navigation"
|
|
import { useEffect, useState } from "react"
|
|
import useSound from "use-sound"
|
|
|
|
type Props = {
|
|
data: CommonStatusDataMap["SELECT_ANSWER"]
|
|
}
|
|
|
|
const Answers = ({
|
|
data: { question, answers, image, media, time, totalPlayer },
|
|
}: Props) => {
|
|
const { gameId }: { gameId?: string } = useParams()
|
|
const { socket } = useSocket()
|
|
const { player } = usePlayerStore()
|
|
|
|
const [cooldown, setCooldown] = useState(time)
|
|
const [paused, setPaused] = useState(false)
|
|
const [totalAnswer, setTotalAnswer] = useState(0)
|
|
const [isMediaPlaying, setIsMediaPlaying] = useState(false)
|
|
|
|
const [sfxPop] = useSound(SFX_ANSWERS_SOUND, {
|
|
volume: 0.1,
|
|
})
|
|
|
|
const [playMusic, { stop: stopMusic, sound: answersMusic }] = useSound(
|
|
SFX_ANSWERS_MUSIC,
|
|
{
|
|
volume: 0.2,
|
|
interrupt: true,
|
|
loop: true,
|
|
},
|
|
)
|
|
|
|
const handleAnswer = (answerKey: number) => () => {
|
|
if (!player) {
|
|
return
|
|
}
|
|
|
|
socket?.emit("player:selectedAnswer", {
|
|
gameId,
|
|
data: {
|
|
answerKey,
|
|
},
|
|
})
|
|
sfxPop()
|
|
}
|
|
|
|
useEffect(() => {
|
|
playMusic()
|
|
|
|
return () => {
|
|
stopMusic()
|
|
}
|
|
}, [playMusic])
|
|
|
|
useEffect(() => {
|
|
if (!answersMusic) {
|
|
return
|
|
}
|
|
|
|
answersMusic.volume(isMediaPlaying ? 0.05 : 0.2)
|
|
}, [answersMusic, isMediaPlaying])
|
|
|
|
useEvent("game:cooldown", (sec) => {
|
|
setCooldown(sec)
|
|
})
|
|
|
|
useEvent("game:cooldownPause", (isPaused) => {
|
|
setPaused(isPaused)
|
|
})
|
|
|
|
useEvent("game:playerAnswer", (count) => {
|
|
setTotalAnswer(count)
|
|
sfxPop()
|
|
})
|
|
|
|
return (
|
|
<div className="flex h-full flex-1 flex-col justify-between">
|
|
<div className="mx-auto inline-flex h-full w-full max-w-7xl flex-1 flex-col items-center justify-center gap-5">
|
|
<h2 className="text-center text-2xl font-bold text-white drop-shadow-lg md:text-4xl lg:text-5xl">
|
|
{question}
|
|
</h2>
|
|
|
|
<QuestionMedia
|
|
media={media || (image ? { type: "image", url: image } : undefined)}
|
|
alt={question}
|
|
onPlayChange={(playing) => setIsMediaPlaying(playing)}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<div className="mx-auto mb-4 flex w-full max-w-7xl justify-between gap-1 px-2 text-lg font-bold text-white md:text-xl">
|
|
<div className="flex flex-col items-center rounded-full bg-black/40 px-4 text-lg font-bold">
|
|
<span className="translate-y-1 text-sm">Time</span>
|
|
<span>{cooldown}</span>
|
|
{paused && (
|
|
<span className="text-xs font-semibold uppercase text-amber-200">
|
|
Paused
|
|
</span>
|
|
)}
|
|
</div>
|
|
<div className="flex flex-col items-center rounded-full bg-black/40 px-4 text-lg font-bold">
|
|
<span className="translate-y-1 text-sm">Answers</span>
|
|
<span>
|
|
{totalAnswer}/{totalPlayer}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mx-auto mb-4 grid w-full max-w-7xl grid-cols-2 gap-1 rounded-full px-2 text-lg font-bold text-white md:text-xl">
|
|
{answers.map((answer, key) => (
|
|
<AnswerButton
|
|
key={key}
|
|
className={clsx(ANSWERS_COLORS[key])}
|
|
icon={ANSWERS_ICONS[key]}
|
|
onClick={handleAnswer(key)}
|
|
>
|
|
{answer}
|
|
</AnswerButton>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default Answers
|