diff --git a/client/src/BoardPieces.css b/client/src/BoardPieces.css
new file mode 100644
index 0000000..49c1ece
--- /dev/null
+++ b/client/src/BoardPieces.css
@@ -0,0 +1,49 @@
+.BoardPieces {
+ display: flex;
+ flex-direction: column;
+ position: absolute;
+ height: 6rem;
+ left: 1rem;
+ bottom: 8rem; /* 1rem over top of Resource cards in hand */
+ width: 20rem;
+ z-index: 1000;
+ border-bottom: 1px solid black;
+ padding-bottom: 0.5rem;
+ margin-bottom: 0.5rem;
+}
+
+.BoardPieces > div {
+ display: flex;
+ justify-items: flex-start;
+}
+
+.BoardPieces[data-active="true"] > div > div {
+ filter: drop-shadow(0px 0px 5px black);
+ cursor: pointer;
+}
+
+.BoardPieces[data-active="true"] > div > div:hover {
+ filter: drop-shadow(0px 0px 5px white);
+}
+
+.BoardPieces .Shape {
+ margin: 0.25rem;
+ margin-bottom: 0.5rem;
+}
+
+.BoardPieces .Road .Shape {
+ width: 0.5rem;
+ height: 1.5rem;
+}
+
+.BoardPieces .Settlement .Shape {
+ width: 1.25rem;
+ height: 1.25rem;
+ clip-path: polygon(50% 0%,70% 15%,70% 2%,90% 2%,90% 30%,100% 40%,100% 100%,65% 100%,65% 65%,35% 65%,35% 100%,0% 100%,0% 40%);
+}
+
+.BoardPieces .City .Shape {
+ width: 1.25rem;
+ height: 1.25rem;
+ clip-path: polygon(15% 0%,39% 23%,39% 52%,100% 56%,100% 74%,100% 100%,80% 100%,63% 100%,62% 75%,46% 75%,47% 100%,0% 100%,0% 24%);
+}
diff --git a/client/src/BoardPieces.js b/client/src/BoardPieces.js
new file mode 100644
index 0000000..ddffb24
--- /dev/null
+++ b/client/src/BoardPieces.js
@@ -0,0 +1,54 @@
+
+import React from "react";
+
+import "./BoardPieces.css";
+import { useStyles } from './Styles.js';
+
+const Road = ({ color, onClick }) => {
+ const classes = useStyles();
+ return
;
+}
+
+const Settlement = ({ color, onClick }) => {
+ const classes = useStyles();
+ return ;
+}
+
+const City = ({ color, onClick }) => {
+ const classes = useStyles();
+ return ;
+}
+
+const BoardPieces = ({ table, color, onClick }) => {
+ if (!table.game || !table.game.player) {
+ return <>>;
+ }
+
+ const player = table.game.players[color];
+ if (!player) {
+ return <>>;
+ }
+
+ const roads = [];
+ for (let i = 0; i < player.roads; i++) {
+ roads.push();
+ }
+ const settlements = [];
+ for (let i = 0; i < player.settlements; i++) {
+ settlements.push();
+ }
+ const cities = [];
+ for (let i = 0; i < player.cities; i++) {
+ cities.push();
+ }
+
+ return (
+
+
{cities}
+
{settlements}
+
{roads}
+
+ );
+};
+
+export default BoardPieces;
\ No newline at end of file
diff --git a/client/src/PlayersStatus.css b/client/src/PlayersStatus.css
new file mode 100644
index 0000000..6981ba9
--- /dev/null
+++ b/client/src/PlayersStatus.css
@@ -0,0 +1,46 @@
+.PlayersStatus {
+ display: flex;
+ flex-direction: column;
+ position: absolute;
+ left: 1rem;
+ bottom: 15rem;
+ border-bottom: 1px solid black;
+ margin-bottom: 0.5rem;
+ color: #d0d0d0;
+ pointer-events: none;
+}
+
+.PlayersStatus .Player {
+ margin-bottom: 0.5rem;
+}
+
+.PlayersStatus .Player .Who {
+ color: white;
+ display: inline-flex;
+ align-items: center;
+}
+
+.PlayersStatus .What {
+ margin-left: 0.25rem;
+ margin-top: 0.25rem;
+}
+
+.PlayersStatus .PlayerColor {
+ width: 1rem;
+ height: 1rem;
+}
+
+.PlayersStatus .Shrunken {
+ position: relative;
+ height: 5.75rem;
+ display: flex;
+}
+
+.PlayersStatus .Shrunken .BoardPieces {
+ transform-origin: 0 100%;
+ transform: scale(0.75);
+ bottom: 0;
+ left: 0;
+ border-bottom: none;
+ margin-bottom: 0;
+}
\ No newline at end of file
diff --git a/client/src/PlayersStatus.js b/client/src/PlayersStatus.js
new file mode 100644
index 0000000..f6c21f4
--- /dev/null
+++ b/client/src/PlayersStatus.js
@@ -0,0 +1,41 @@
+import React from "react";
+import Resource from './Resource.js';
+import "./PlayersStatus.css";
+import BoardPieces from './BoardPieces.js';
+import { getPlayerName } from './Common.js';
+import PlayerColor from './PlayerColor.js';
+
+const Player = ({ table, color }) => {
+
+ const player = table.game.players[color];
+ return
+
+
{getPlayerName(table.game.sessions, color)}
+
+
+
Victory points: {player.points}
+
Development cards: {player.unplayed}
+
Army: {player.army}
+
+
+
+};
+
+const PlayersStatus = ({ table }) => {
+ if (!table.game) {
+ return <>>;
+ }
+
+ const players = Object.getOwnPropertyNames(table.game.players)
+ .filter(color => table.game.players[color].status === 'Active' && table.game.color !== color)
+ .map(color => {
+ const player = table.game.players[color];
+ return ;
+ });
+ return { players }
;
+}
+
+export default PlayersStatus;
\ No newline at end of file
diff --git a/client/src/Styles.js b/client/src/Styles.js
new file mode 100644
index 0000000..d075d31
--- /dev/null
+++ b/client/src/Styles.js
@@ -0,0 +1,30 @@
+import { makeStyles } from '@material-ui/core/styles';
+import { orange,lightBlue, red, grey } from '@material-ui/core/colors';
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ display: 'flex',
+ '& > *': {
+ margin: theme.spacing(1),
+ },
+ },
+ R: {
+ color: theme.palette.getContrastText(red[500]),
+ backgroundColor: red[500],
+ },
+ O: {
+ color: theme.palette.getContrastText(orange[500]),
+ backgroundColor: orange[500],
+ },
+ W: {
+ color: theme.palette.getContrastText(grey[50]),
+ backgroundColor: grey[50],
+ },
+ B: {
+ color: theme.palette.getContrastText(lightBlue[500]),
+ backgroundColor: lightBlue[500],
+ },
+}));
+
+
+export { useStyles };
\ No newline at end of file
diff --git a/client/src/Table.js b/client/src/Table.js
index 67c4b16..1c703bc 100755
--- a/client/src/Table.js
+++ b/client/src/Table.js
@@ -21,6 +21,7 @@ import { CircularProgress } from "@material-ui/core";
import 'moment-timezone';
import Activities from './Activities.js';
import BoardPieces from './BoardPieces.js';
+import PlayersStatus from './PlayersStatus.js';
/* Start of withRouter polyfill */
// https://reactrouter.com/docs/en/v6/faq#what-happened-to-withrouter-i-need-it
@@ -352,16 +353,10 @@ const Players = ({ table }) => {
if (!inLobby && item.status === 'Not active') {
continue;
}
- const name = getPlayerName(table.game.sessions, color),
+ let name = getPlayerName(table.game.sessions, color),
selectable = table.game.state === 'lobby' && (item.status === 'Not active' || table.game.color === color);
- let toggleText;
- if (name) {
- toggleText = `${name} has ${item.points} VP`;
- if (item.unplayed) {
- toggleText += ` and ${item.unplayed} unplayed DCs`;
- }
- } else {
- toggleText = "Available";
+ if (!name) {
+ name = "Available";
}
players.push((
{
className="PlayerEntry"
onClick={() => { inLobby && selectable && toggleSelected(color) }}
key={`player-${color}`}>
-
-
- { item.status + ' ' }
- { item.status !== 'Not active' && Date.now() ? Date.now() : item.lastActive}/>}
- >)} />
+ {name}
));
}
@@ -431,6 +421,7 @@ class Table extends React.Component {
this.closeCard = this.closeCard.bind(this);
this.playCard = this.playCard.bind(this);
this.selectResources = this.selectResources.bind(this);
+ this.buildItem = this.buildItem.bind(this);
this.mouse = { x: 0, y: 0 };
this.radius = 0.317;
@@ -917,6 +908,10 @@ class Table extends React.Component {
});
}
+ buildItem(item) {
+ return this.sendAction(`buy-${item}`);
+ }
+
componentWillUnmount() {
if (this.ws) {
this.ws.close();
@@ -983,6 +978,10 @@ class Table extends React.Component {
development = <>/>;
}
+ if (!this.game) {
+ return <>>;
+ }
+
return (
{ this.state.loading > 0 &&
}
@@ -994,7 +993,8 @@ class Table extends React.Component {
{ player !== undefined && <>
-
+
+