162 lines
4.4 KiB
TypeScript
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 };
|