leaky-ships/leaky-ships/components/Lobby/Player.tsx

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