Bad Move error message displayed over the board
This commit is contained in:
parent
3bcf5ced76
commit
a2a7ea2e54
@ -73,11 +73,12 @@ export default function useGamesApi() {
|
|||||||
|
|
||||||
const pushGameMove = ({ uuid, move, message }) => {
|
const pushGameMove = ({ uuid, move, message }) => {
|
||||||
doPushing(`/api/game/${uuid}/move`, 'PUT', { move, message }, {
|
doPushing(`/api/game/${uuid}/move`, 'PUT', { move, message }, {
|
||||||
onPushing: (isPushing) => dispatchGuide({ type: 'UUIDpushing', uuid, what: isPushing && {moveFrom: move[0], moveTo: move[1]} }),
|
onPushing: (isPushing) => dispatchGuide({ type: 'UUIDpushing', uuid, what: isPushing && { moveFrom: move[0], moveTo: move[1] } }),
|
||||||
|
onBadReq: (message) => dispatchGuide({ type: 'UUIDerror', uuid, error: { message, moveFrom: move[0], moveTo: move[1] } }),
|
||||||
onSuccess: (game) => {
|
onSuccess: (game) => {
|
||||||
dispatchState({ type: 'update', game });
|
dispatchState({ type: 'update', game });
|
||||||
dispatchGuide({ type: 'UUIDmessage', uuid, message: ''});
|
dispatchGuide({ type: 'UUIDmessage', uuid, message: '' });
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,10 +97,25 @@
|
|||||||
|
|
||||||
.GameBoard {
|
.GameBoard {
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
|
width: 275px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Message2Opponent {
|
.Message2Opponent {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
margin-left: 30px;
|
margin-left: 30px;
|
||||||
width: 270px;
|
width: 275px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.BadMove {
|
||||||
|
position: fixed;
|
||||||
|
width: 275px;
|
||||||
|
top: 250px;
|
||||||
|
cursor: default; /* disable 'I beam' cursor change */
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: rgba(255, 80, 80, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.BadMove:hover {
|
||||||
|
background-color: rgba(255, 80, 80, 0.7);
|
||||||
}
|
}
|
@ -34,7 +34,6 @@ export default function Games({ games, players }) {
|
|||||||
<ActionPanel gamesApi={games.api} />
|
<ActionPanel gamesApi={games.api} />
|
||||||
<GameBoardRoutes dispatchGuide={gamesDispatchGuide} gamesApi={games.api} username={players.user.name} />
|
<GameBoardRoutes dispatchGuide={gamesDispatchGuide} gamesApi={games.api} username={players.user.name} />
|
||||||
<Message2OpponentRoutes dispatchGuide={gamesDispatchGuide} />
|
<Message2OpponentRoutes dispatchGuide={gamesDispatchGuide} />
|
||||||
{/* <GameMessage /> */}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div >
|
</div >
|
||||||
@ -156,10 +155,11 @@ function GameBoardRoutes({ dispatchGuide, gamesApi, username }) {
|
|||||||
const games = useContext(GamesStateContext);
|
const games = useContext(GamesStateContext);
|
||||||
const guide = useContext(GamesGuideContext);
|
const guide = useContext(GamesGuideContext);
|
||||||
|
|
||||||
const fromUUID = (uuid) => (!uuid) ? [{}, null] :
|
const fromUUID = (uuid) => (!uuid) ? [{}, null, null] :
|
||||||
[
|
[
|
||||||
games.find((game) => game.uuid === uuid) || {}, // game
|
games.find((game) => game.uuid === uuid) || {}, // game
|
||||||
guide.UUIDpushing[uuid] // pushing
|
guide.UUIDpushing[uuid], // pushing
|
||||||
|
guide.UUIDerror[uuid] // error (aka bad move)
|
||||||
];
|
];
|
||||||
|
|
||||||
const onStoneClick = (uuid, cellId) => {
|
const onStoneClick = (uuid, cellId) => {
|
||||||
@ -191,6 +191,7 @@ function GameBoardRoutes({ dispatchGuide, gamesApi, username }) {
|
|||||||
username={username}
|
username={username}
|
||||||
getGame={() => fromUUID(guide.selectedUUID.active)}
|
getGame={() => fromUUID(guide.selectedUUID.active)}
|
||||||
onStoneMove={(uuid, move) => gamesApi.pushGameMove({ uuid, move, message: guide.UUIDmessage[uuid] })}
|
onStoneMove={(uuid, move) => gamesApi.pushGameMove({ uuid, move, message: guide.UUIDmessage[uuid] })}
|
||||||
|
dispatchGuide={dispatchGuide}
|
||||||
/>
|
/>
|
||||||
} />
|
} />
|
||||||
|
|
||||||
|
14
webapp/src/container/games/BadMove.jsx
Normal file
14
webapp/src/container/games/BadMove.jsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default function BadMove({ dispatchGuide, uuid, message }) {
|
||||||
|
if (!dispatchGuide || !uuid || !message)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='BadMove'
|
||||||
|
onClick={() => dispatchGuide({ type: 'UUIDerror', uuid, error: {} })}
|
||||||
|
>
|
||||||
|
{message}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { Color, Player, Board } from '../../components/Checkers';
|
import { Color, Player, Board } from '../../components/Checkers';
|
||||||
import './GameBoard.css';
|
import './GameBoard.css';
|
||||||
|
import BadMove from './BadMove';
|
||||||
|
|
||||||
export default function GameBoard({ username, getGame, onStoneClick, onStoneMove }) {
|
export default function GameBoard({ dispatchGuide, username, getGame, onStoneClick, onStoneMove }) {
|
||||||
const [game, isPushing] = getGame();
|
const [game, isPushing, error] = getGame();
|
||||||
|
|
||||||
const myName = game.opponentName ? username : '';
|
const myName = game.opponentName ? username : '';
|
||||||
const opponentColor = Color.opposite(game.myColor);
|
const opponentColor = Color.opposite(game.myColor);
|
||||||
@ -14,11 +14,17 @@ export default function GameBoard({ username, getGame, onStoneClick, onStoneMove
|
|||||||
(cellId) => onStoneClick(game.uuid, cellId);
|
(cellId) => onStoneClick(game.uuid, cellId);
|
||||||
|
|
||||||
const optionalOnStoneMove = (typeof onStoneMove !== 'function' || isPushing) ? null :
|
const optionalOnStoneMove = (typeof onStoneMove !== 'function' || isPushing) ? null :
|
||||||
(move) => {
|
(move) => {
|
||||||
if (move[0] !== move[1] && game.board[move[1]] === undefined)
|
if (move[0] !== move[1] && game.board[move[1]] === undefined)
|
||||||
onStoneMove(game.uuid, move)
|
onStoneMove(game.uuid, move)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const currMove = (() => {
|
||||||
|
if (isPushing) return [isPushing.moveFrom, isPushing.moveTo];
|
||||||
|
if (error?.moveFrom && error?.moveTo) return [error.moveFrom, error.moveTo];
|
||||||
|
return [];
|
||||||
|
})(); // <<-- execute
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='GameBoard'>
|
<div className='GameBoard'>
|
||||||
<Player
|
<Player
|
||||||
@ -29,7 +35,7 @@ export default function GameBoard({ username, getGame, onStoneClick, onStoneMove
|
|||||||
board={game.board}
|
board={game.board}
|
||||||
flip={flipBoard}
|
flip={flipBoard}
|
||||||
prevMove={game.previousMove}
|
prevMove={game.previousMove}
|
||||||
currMove={[isPushing?.moveFrom, isPushing?.moveTo]}
|
currMove={currMove}
|
||||||
onStoneClick={optionalOnStoneClick}
|
onStoneClick={optionalOnStoneClick}
|
||||||
onStoneMove={optionalOnStoneMove}
|
onStoneMove={optionalOnStoneMove}
|
||||||
/>
|
/>
|
||||||
@ -37,6 +43,7 @@ export default function GameBoard({ username, getGame, onStoneClick, onStoneMove
|
|||||||
color={game.myColor || Color.white}
|
color={game.myColor || Color.white}
|
||||||
name={myName}
|
name={myName}
|
||||||
/>
|
/>
|
||||||
|
<BadMove dispatchGuide={dispatchGuide} uuid={game?.uuid} message={error?.message} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -62,7 +62,7 @@ export function usePolling(uri, { onSuccess, onPolling }, mode = null) {
|
|||||||
}, [initialPoll, mode, intervalTimerId, isPolling, pollData, stopPollInterval]);
|
}, [initialPoll, mode, intervalTimerId, isPolling, pollData, stopPollInterval]);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function doPushing(uri, method, data, { onSuccess, onPushing }) {
|
export async function doPushing(uri, method, data, { onSuccess, onBadReq, onPushing }) {
|
||||||
if (onPushing)
|
if (onPushing)
|
||||||
onPushing(true);
|
onPushing(true);
|
||||||
|
|
||||||
@ -75,14 +75,22 @@ export async function doPushing(uri, method, data, { onSuccess, onPushing }) {
|
|||||||
body: JSON.stringify(data), // body data type must match "Content-Type" header
|
body: JSON.stringify(data), // body data type must match "Content-Type" header
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (response.status === 400 && onBadReq) {
|
||||||
|
const content = (response.headers.get('Content-Type') === "application/json")
|
||||||
|
? await response.json()
|
||||||
|
: {};
|
||||||
|
|
||||||
|
return onBadReq(content.message);
|
||||||
|
}
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
return console.warn(`Unexpected response status: ${response.status}`, response);
|
return console.warn(`Unexpected response status: ${response.status}`, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
var content = (response.headers.get('Content-Type') === "application/json")
|
const content = (response.headers.get('Content-Type') === "application/json")
|
||||||
? await response.json()
|
? await response.json()
|
||||||
: null;
|
: {};
|
||||||
|
|
||||||
onSuccess(content);
|
onSuccess(content);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,9 @@ export const gamesGuideTemplate = {
|
|||||||
UUIDpushing: { // UUIDpushing[uuid]
|
UUIDpushing: { // UUIDpushing[uuid]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
UUIDerror: { // UUIDerror[uuid]
|
||||||
|
},
|
||||||
|
|
||||||
isPolling: false,
|
isPolling: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,6 +119,12 @@ function gamesGuideReducer(state, action) {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'UUIDerror': {
|
||||||
|
const next = { ...state };
|
||||||
|
next.UUIDerror[action.uuid] = action.error;
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw Error('GamesGuide: unknown action.type: ' + action.type);
|
throw Error('GamesGuide: unknown action.type: ' + action.type);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user