1
0
peddlers-of-ketran/client/src/ChooseCard.tsx

162 lines
4.4 KiB
TypeScript

import React, { useState, useCallback, useEffect, useMemo, useRef, useContext } from "react";
import equal from "fast-deep-equal";
import Paper from "@mui/material/Paper";
import Button from "@mui/material/Button";
import "./ChooseCard.css";
import { Resource } from "./Resource";
import { GlobalContext } from "./GlobalContext";
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-explicit-any */
const ChooseCard: React.FC = () => {
const { ws, sendJsonMessage } = useContext(GlobalContext);
const [turn, setTurn] = useState<any>(undefined);
const [color, setColor] = useState<string | undefined>(undefined);
const [state, setState] = useState<string | undefined>(undefined);
const [cards, setCards] = useState<string[]>([]);
const fields = useMemo(() => ["turn", "color", "state"], []);
const onWsMessage = (event: MessageEvent) => {
const data = JSON.parse(event.data);
switch (data.type) {
case "game-update":
console.log(`choose-card - game-update: `, data.update);
if ("turn" in data.update && !equal(turn, data.update.turn)) {
setTurn(data.update.turn);
}
if ("color" in data.update && data.update.color !== color) {
setColor(data.update.color);
}
if ("state" in data.update && data.update.state !== state) {
setState(data.update.state);
}
break;
default:
break;
}
};
const refWsMessage = useRef(onWsMessage);
useEffect(() => {
refWsMessage.current = onWsMessage;
});
useEffect(() => {
if (!ws) {
return;
}
const cbMessage = (e: MessageEvent) => refWsMessage.current(e);
ws.addEventListener("message", cbMessage);
return () => {
ws.removeEventListener("message", cbMessage);
};
}, [ws, refWsMessage]);
useEffect(() => {
if (!sendJsonMessage) {
return;
}
sendJsonMessage({
type: "get",
fields,
});
}, [sendJsonMessage, fields]);
const selectResources = useCallback(() => {
if (!sendJsonMessage) return;
sendJsonMessage({
type: "select-resources",
cards,
});
}, [sendJsonMessage, cards]);
let count = 0;
if (turn && turn.actions && turn.actions.indexOf("select-resources") !== -1) {
if (turn.active) {
if (turn.color === color) {
count = turn.active === "monopoly" ? 1 : 2;
}
}
if (state === "volcano") {
if (!turn.select) {
count = 0;
} else if (color && color in turn.select) {
count = turn.select[color];
} else {
count = 0;
}
}
}
const selectCard = useCallback(() => {
const selected = document.querySelectorAll(".ChooseCard .Selected");
if (selected.length > count) {
for (let i = 0; i < selected.length; i++) {
selected[i].classList.remove("Selected");
}
setCards([]);
return;
}
const tmp: string[] = [];
for (let i = 0; i < selected.length; i++) {
const type = selected[i].getAttribute("data-type");
if (type) tmp.push(type);
}
setCards(tmp);
}, [setCards, count]);
if (count === 0) {
return <></>;
}
const resources = ["wheat", "brick", "stone", "sheep", "wood"].map((type) => {
return <Resource key={type} type={type} count={count} onClick={selectCard} />;
});
let title: React.ReactElement;
switch (turn.active) {
case "monopoly":
title = (
<>
<b>Monopoly</b>! Tap the resource type you want everyone to give you!
</>
);
break;
case "year-of-plenty":
title = (
<>
<b>Year of Plenty</b>! Tap the two resources you want to receive from the bank!
</>
);
break;
case "volcano":
title = (
<>
<b>Volcano has minerals</b>! Tap the {count} resources you want to receive from the bank!
</>
);
break;
default:
title = <>Unknown card type {turn.active}.</>;
break;
}
return (
<div className="ChooseCard">
<Paper>
<div className="Title">{title}</div>
<div style={{ display: "flex", flexDirection: "row", justifyContent: "center" }}>{resources}</div>
<div className="Actions">
<Button disabled={cards.length !== count} onClick={selectResources}>
submit
</Button>
</div>
</Paper>
</div>
);
};
export { ChooseCard };