125 lines
3.4 KiB
TypeScript
125 lines
3.4 KiB
TypeScript
import {
|
|
faCheck,
|
|
faHandPointer,
|
|
faHourglass1,
|
|
faHourglass2,
|
|
faHourglass3,
|
|
faHourglassClock,
|
|
} from "@fortawesome/pro-solid-svg-icons"
|
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
|
|
import { faCaretDown } from "@fortawesome/sharp-solid-svg-icons"
|
|
import { useGameProps } from "@hooks/useGameProps"
|
|
import { socket } from "@lib/socket"
|
|
import classNames from "classnames"
|
|
import { CSSProperties, useEffect, useMemo, useState } from "react"
|
|
import Button from "./Button"
|
|
|
|
function HourGlass() {
|
|
const [count, setCount] = useState(3)
|
|
|
|
useEffect(() => {
|
|
const interval = setInterval(() => setCount((e) => (e + 1) % 4), 1000)
|
|
return () => clearInterval(interval)
|
|
}, [])
|
|
|
|
const icon = useMemo(() => {
|
|
switch (count) {
|
|
case 0:
|
|
return faHourglass3
|
|
case 1:
|
|
return faHourglass1
|
|
case 2:
|
|
return faHourglass2
|
|
case 3:
|
|
return faHourglass3
|
|
default:
|
|
return faHourglassClock
|
|
}
|
|
}, [count])
|
|
|
|
return (
|
|
<FontAwesomeIcon icon={icon} className="ml-4 w-12" spin={count === 0} />
|
|
)
|
|
}
|
|
|
|
function Player({
|
|
src,
|
|
i,
|
|
userId,
|
|
}: {
|
|
src: string
|
|
i: number
|
|
userId?: string
|
|
}) {
|
|
const { payload, userStates, setIsReady } = useGameProps()
|
|
const player = useMemo(() => payload?.users[i], [i, payload?.users])
|
|
const { isReady, isConnected } = useMemo(() => userStates[i], [i, userStates])
|
|
const primary = useMemo(
|
|
() => userId && userId === payload?.users[i]?.id,
|
|
[i, payload?.users, userId],
|
|
)
|
|
|
|
return (
|
|
<div className="flex w-96 flex-col items-center gap-4 p-4">
|
|
<p
|
|
className={classNames(
|
|
"font-farro w-max text-5xl",
|
|
primary ? "font-semibold" : "font-normal",
|
|
)}
|
|
>
|
|
{player?.name ?? "Spieler " + (player?.index === 2 ? "2" : "1")}
|
|
</p>
|
|
<div className="relative">
|
|
<img className="pixelart w-64" src={"/assets/" + src} alt={src} />
|
|
{primary ? (
|
|
<button className="absolute right-4 top-4 h-14 w-14 rounded-lg border-2 border-dashed border-warn bg-gray-800 bg-opacity-90">
|
|
<FontAwesomeIcon
|
|
className="h-full w-full text-warn"
|
|
icon={faCaretDown}
|
|
/>
|
|
</button>
|
|
) : null}
|
|
</div>
|
|
<Button
|
|
type={isConnected ? (isReady ? "green" : "orange") : "gray"}
|
|
latching
|
|
isLatched={!!isReady}
|
|
onClick={() => {
|
|
if (!player) return
|
|
setIsReady({
|
|
i,
|
|
isReady: !isReady,
|
|
})
|
|
socket.emit("isReady", !isReady)
|
|
}}
|
|
disabled={!primary}
|
|
>
|
|
Ready
|
|
{isReady && isConnected ? (
|
|
<FontAwesomeIcon icon={faCheck} className="ml-4 w-12" />
|
|
) : primary ? (
|
|
<FontAwesomeIcon
|
|
icon={faHandPointer}
|
|
className="ml-4 w-12"
|
|
style={
|
|
{
|
|
"--fa-bounce-start-scale-x": 1.05,
|
|
"--fa-bounce-start-scale-y": 0.95,
|
|
"--fa-bounce-jump-scale-x": 0.95,
|
|
"--fa-bounce-jump-scale-y": 1.05,
|
|
"--fa-bounce-land-scale-x": 1.025,
|
|
"--fa-bounce-land-scale-y": 0.975,
|
|
"--fa-bounce-height": "-0.125em",
|
|
} as CSSProperties
|
|
}
|
|
bounce
|
|
/>
|
|
) : (
|
|
<HourGlass />
|
|
)}
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default Player
|