176 lines
5.3 KiB
JavaScript
176 lines
5.3 KiB
JavaScript
import React, {useEffect, useContext, useMemo, useRef, useState,
|
|
useCallback} from "react";
|
|
import equal from "fast-deep-equal";
|
|
|
|
import Paper from '@material-ui/core/Paper';
|
|
import Button from '@material-ui/core/Button';
|
|
|
|
import "./ViewCard.css";
|
|
import { Resource } from './Resource.js';
|
|
import { GlobalContext } from "./GlobalContext.js";
|
|
|
|
const ViewCard = ({cardActive, setCardActive}) => {
|
|
const { ws } = useContext(GlobalContext);
|
|
const [priv, setPriv] = useState(undefined);
|
|
const [turns, setTurns] = useState(0);
|
|
const fields = useMemo(() => [
|
|
'private', 'turns'
|
|
], []);
|
|
const onWsMessage = (event) => {
|
|
const data = JSON.parse(event.data);
|
|
switch (data.type) {
|
|
case 'game-update':
|
|
console.log(`view-card - game update`);
|
|
if ('private' in data.update && !equal(data.update.private, priv)) {
|
|
setPriv(data.update.private);
|
|
}
|
|
if ('turns' in data.update && data.update.turns !== turns) {
|
|
setTurns(data.update.turns);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
};
|
|
const refWsMessage = useRef(onWsMessage);
|
|
useEffect(() => { refWsMessage.current = onWsMessage; });
|
|
useEffect(() => {
|
|
if (!ws) { return; }
|
|
const cbMessage = e => refWsMessage.current(e);
|
|
ws.addEventListener('message', cbMessage);
|
|
return () => {
|
|
ws.removeEventListener('message', cbMessage);
|
|
}
|
|
}, [ws, refWsMessage]);
|
|
useEffect(() => {
|
|
if (!ws) { return; }
|
|
ws.send(JSON.stringify({
|
|
type: 'get',
|
|
fields
|
|
}));
|
|
}, [ws, fields]);
|
|
|
|
const playCard = useCallback((event) => {
|
|
ws.send(JSON.stringify({
|
|
type: 'play-card',
|
|
card: cardActive
|
|
}));
|
|
}, [ws, cardActive]);
|
|
|
|
const close = (event) => {
|
|
setCardActive(undefined);
|
|
};
|
|
|
|
if (!cardActive) {
|
|
return <></>;
|
|
}
|
|
|
|
const capitalize = (string) => {
|
|
if (string === 'vp') {
|
|
return 'Victory Point';
|
|
}
|
|
if (string === 'army') {
|
|
return 'Knight';
|
|
}
|
|
|
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
|
};
|
|
|
|
let description, lookup;
|
|
if (cardActive.type === 'progress') {
|
|
lookup = `${cardActive.type}-${cardActive.card}`;
|
|
} else {
|
|
lookup = cardActive.type;
|
|
}
|
|
|
|
switch (lookup) {
|
|
case 'army':
|
|
description = <>
|
|
<div>When played, you <b>must</b> move the robber.</div>
|
|
<div>Steal <b>1</b> resource card from the owner of an adjacent settlement or city.</div>
|
|
<div>You may only play one development card during your turn -- either one
|
|
knight or one progress card.</div></>;
|
|
break;
|
|
case 'vp':
|
|
description = <><div><b>1</b> victory point.</div>
|
|
<div>You only reveal your victory point cards when the game is over, either
|
|
when you or an opponent
|
|
reaches <b>10+</b> victory points on their turn and declares
|
|
victory!</div></>;
|
|
break;
|
|
case 'progress-road-1':
|
|
case 'progress-road-2':
|
|
description = <>
|
|
<div>Play <b>2</b> new roads as if you had just built them.</div>
|
|
<div>This is still limited by the number of roads you have. If you do not have enough roads
|
|
remaining, or if there are no valid road building locations, the number of roads
|
|
you can place will be reduced.</div>
|
|
<div>You currently have <b>{priv.roads}</b> roads remaining.</div>
|
|
</>;
|
|
break;
|
|
case 'progress-monopoly':
|
|
description = <>
|
|
<div>When you play this card, you will select <b>1</b> type of resource.
|
|
All other players must give you all their resource cards of that type.</div>
|
|
</>;
|
|
break;
|
|
case 'progress-year-of-plenty':
|
|
description = <>
|
|
<div>Take any <b>2</b> resources from the bank. Add them to your hand. They can be
|
|
<b>2</b> of the same resource or <b>1</b> of two differ resources.</div>
|
|
</>;
|
|
break;
|
|
default:
|
|
description = <>Unknown card type {lookup}</>;
|
|
break;
|
|
};
|
|
|
|
let canPlay = false;
|
|
if (cardActive.type === 'vp') {
|
|
let points = priv.points;
|
|
priv.development.forEach(item => {
|
|
if (item.type === 'vp') {
|
|
points++;
|
|
}
|
|
});
|
|
canPlay = points >= 10;
|
|
if (!canPlay && !cardActive.played) {
|
|
description = <>{description}<div>You do not have enough victory points to play this card yet. You can currently reach <b>{points}</b> points.</div></>;
|
|
}
|
|
} else {
|
|
canPlay = cardActive.turn < turns;
|
|
if (!canPlay) {
|
|
description = <>{description}<div>You can not play this card until your next turn.</div></>;
|
|
}
|
|
if (canPlay) {
|
|
canPlay = priv.playedCard !== turns;
|
|
if (!canPlay) {
|
|
description = <>{description}<div>You have already played a development card this turn.</div></>;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cardActive.played) {
|
|
description = <>{description}<div>You have already played this card.</div></>;
|
|
canPlay = false;
|
|
}
|
|
|
|
return (
|
|
<div className="ViewCard">
|
|
<Paper>
|
|
<div className="Title">{capitalize(cardActive.type)}</div>
|
|
<div style={{display: 'flex', flexDirection: 'row'}}>
|
|
<Resource type={`${cardActive.type}-${cardActive.card}`} disabled count={1}/>
|
|
<div className="Description">{description}</div>
|
|
</div>
|
|
{ !cardActive.played &&
|
|
<Button disabled={!canPlay}
|
|
onClick={playCard}>play</Button>
|
|
}
|
|
<Button onClick={close}>close</Button>
|
|
</Paper>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export {ViewCard}; |