From 671e13a41d0a5594a19ce911bf7450d7da3e65ec Mon Sep 17 00:00:00 2001 From: djmil Date: Thu, 16 Nov 2023 11:49:12 +0100 Subject: [PATCH] Game Draw: req/acq/rej --- .../cordacheckers/api/GameController.java | 42 +++++++++++++ webapp/src/api/games.js | 22 ++++++- webapp/src/container/Games.css | 33 ++++++++++ webapp/src/container/Games.jsx | 30 ++++++---- .../src/container/games/Message2Opponent.jsx | 2 +- webapp/src/container/games/action/Draw.jsx | 60 +++++++++++++++++++ webapp/src/container/games/action/DrawAcq.jsx | 6 -- webapp/src/container/games/action/DrawReq.jsx | 6 -- .../src/container/games/action/Surrender.jsx | 4 +- .../src/container/games/view/GameSelector.jsx | 4 +- webapp/src/reducer/games.js | 7 ++- 11 files changed, 186 insertions(+), 30 deletions(-) create mode 100644 webapp/src/container/games/action/Draw.jsx delete mode 100644 webapp/src/container/games/action/DrawAcq.jsx delete mode 100644 webapp/src/container/games/action/DrawReq.jsx diff --git a/backend/src/main/java/djmil/cordacheckers/api/GameController.java b/backend/src/main/java/djmil/cordacheckers/api/GameController.java index 301e012..25aaa16 100644 --- a/backend/src/main/java/djmil/cordacheckers/api/GameController.java +++ b/backend/src/main/java/djmil/cordacheckers/api/GameController.java @@ -50,4 +50,46 @@ public class GameController { return ResponseEntity .ok(finishedGame); } + + @PutMapping("/{uuid}/drawreq") + public ResponseEntity drawRequest( + @AuthenticationPrincipal User issuer, + @PathVariable UUID uuid + ) { + final GameView drawReqGame = cordaClient.gameDrawRequest( + issuer.getHoldingIdentity(), + uuid + ); + + return ResponseEntity + .ok(drawReqGame); + } + + @PutMapping("/{uuid}/drawacc") + public ResponseEntity drawAccept( + @AuthenticationPrincipal User issuer, + @PathVariable UUID uuid + ) { + final GameView drawAccGame = cordaClient.gameDrawAccept( + issuer.getHoldingIdentity(), + uuid + ); + + return ResponseEntity + .ok(drawAccGame); + } + + @PutMapping("/{uuid}/drawrej") + public ResponseEntity drawReject( + @AuthenticationPrincipal User issuer, + @PathVariable UUID uuid + ) { + final GameView drawRejGame = cordaClient.gameDrawReject( + issuer.getHoldingIdentity(), + uuid + ); + + return ResponseEntity + .ok(drawRejGame); + } } diff --git a/webapp/src/api/games.js b/webapp/src/api/games.js index 41d4712..4d45ce8 100644 --- a/webapp/src/api/games.js +++ b/webapp/src/api/games.js @@ -44,11 +44,29 @@ export default function useGamesApi(gamesReducer, config) { onSuccess: (acceptedGame) => dispatchGames({ type: 'next', gamesList: games.nextGameList(acceptedGame), proposal: gamesInitialState.proposal }) }), - pushGameSurrender: ({ uuid }) => ifNot(games.isPushingActiveGameSurrender) && + pushGameSurrender: ({ uuid }) => ifNot(games.isPushingGameSurrender) && doPushing(`/api/game/${uuid}/surrender`, 'PUT', null, { - onPushing: (isPushingActiveGameSurrender) => dispatchGames({ type: 'next', isPushingActiveGameSurrender }), + onPushing: (isPushingGameSurrender) => dispatchGames({ type: 'next', isPushingGameSurrender }), onSuccess: (finishedGame) => dispatchGames({ type: 'next', gamesList: games.nextGameList(finishedGame), proposal: gamesInitialState.active }) }), + + pushGameDrawRequest: ({ uuid }) => ifNot(games.isPushingGameDrawRequest) && + doPushing(`/api/game/${uuid}/drawreq`, 'PUT', null, { + onPushing: (isPushingGameDrawRequest) => dispatchGames({ type: 'next', isPushingGameDrawRequest }), + onSuccess: (drawReqGame) => dispatchGames({ type: 'next', gamesList: games.nextGameList(drawReqGame), proposal: gamesInitialState.active }) + }), + + pushGameDrawAccept: ({ uuid }) => ifNot(games.isPushingGameDrawAccept) && + doPushing(`/api/game/${uuid}/drawacc`, 'PUT', null, { + onPushing: (isPushingGameDrawAccept) => dispatchGames({ type: 'next', isPushingGameDrawAccept }), + onSuccess: (drawAccGame) => dispatchGames({ type: 'next', gamesList: games.nextGameList(drawAccGame), proposal: gamesInitialState.active }) + }), + + pushGameDrawReject: ({ uuid }) => ifNot(games.isPushingGameDrawReject) && + doPushing(`/api/game/${uuid}/drawrej`, 'PUT', null, { + onPushing: (isPushingGameDrawReject) => dispatchGames({ type: 'next', isPushingGameDrawReject }), + onSuccess: (drawRejGame) => dispatchGames({ type: 'next', gamesList: games.nextGameList(drawRejGame), proposal: gamesInitialState.active }) + }), } } diff --git a/webapp/src/container/Games.css b/webapp/src/container/Games.css index dba6872..efe32ae 100644 --- a/webapp/src/container/Games.css +++ b/webapp/src/container/Games.css @@ -145,4 +145,37 @@ .ActionPanel .Accept.ready:active { background-color:#00af00a0; +} + +/* + * Draw + */ +.ActionPanel .Draw.ready, +.ActionPanel .Draw.accept, +.ActionPanel .Draw.reject { + background-color: #ffff0018; +} + +.ActionPanel .Draw.ready:hover { + background-color:#ffff0040; +} + +.ActionPanel .Draw.ready:active { + background-color:#ffff00a0; +} + +.ActionPanel .Draw.accept:hover { + background-color:#a4ff4a50; +} + +.ActionPanel .Draw.accept:active { + background-color:#10ff0080; +} + +.ActionPanel .Draw.reject:hover { + background-color:#ffaaaa60; +} + +.ActionPanel .Draw.reject:active { + background-color:#ff000090; } \ No newline at end of file diff --git a/webapp/src/container/Games.jsx b/webapp/src/container/Games.jsx index da3e41c..ae7cc80 100644 --- a/webapp/src/container/Games.jsx +++ b/webapp/src/container/Games.jsx @@ -9,9 +9,8 @@ import Create from './games/action/Create'; import Reject from './games/action/Reject'; import Cancel from './games/action/Cancel'; import Accept from './games/action/Accept'; -import DrawReq from './games/action/DrawReq'; -import DrawAcq from './games/action/DrawAcq'; import Surrender from './games/action/Surrender'; +import { DrawRequest, DrawAccept, DrawReject } from './games/action/Draw'; import Backward from './games/action/Backward'; import Forward from './games/action/Forward'; @@ -27,18 +26,19 @@ export default function Games({ context: { gamesReducer, gamesApi }, players }) return (
+
+
+ {/* */} - {/* - - */}
+
) @@ -81,6 +81,7 @@ function ViewProvider({ gamesReducer, players }) { dispatchGames({ type: 'nextArchive', selectedUUID })} /> } /> + ) @@ -90,22 +91,31 @@ function ActionPanel({ players, gamesApi }) { return (
+ gamesApi.pushNewGame(reqParams)} /> } /> + gamesApi.pushGameProposalAccept({ uuid })} />, gamesApi.pushGameProposalReject({ uuid })} />, gamesApi.pushGameProposalCancel({ uuid })} /> ]} /> + , - , - gamesApi.pushGameSurrender({ uuid })}/> + gamesApi.pushGameDrawRequest({ uuid })} />, + gamesApi.pushGameDrawAccept({ uuid })} />, + gamesApi.pushGameDrawReject({ uuid })} />, + gamesApi.pushGameSurrender({ uuid })} /> ]} /> - , ]} /> + + , + + ]} /> +
) @@ -127,7 +137,7 @@ function countGames(gamesList) { awaiting.proposals++; break; case 'GAME_BOARD_WAIT_FOR_YOU': - case 'DRAW_REQUEST_WAIT_FOR_YO': + case 'DRAW_REQUEST_WAIT_FOR_YOU': awaiting.active++; break; default: diff --git a/webapp/src/container/games/Message2Opponent.jsx b/webapp/src/container/games/Message2Opponent.jsx index e19e984..32d1d97 100644 --- a/webapp/src/container/games/Message2Opponent.jsx +++ b/webapp/src/container/games/Message2Opponent.jsx @@ -56,7 +56,7 @@ export default function Message2Opponent({ dispatchGames }) { return ( update(e.target.value)} diff --git a/webapp/src/container/games/action/Draw.jsx b/webapp/src/container/games/action/Draw.jsx new file mode 100644 index 0000000..89cf44d --- /dev/null +++ b/webapp/src/container/games/action/Draw.jsx @@ -0,0 +1,60 @@ +import React, { useContext } from 'react'; +import Wobler from '../../../components/Wobler'; +import { GamesContext } from '../../../context/games'; + +export function DrawRequest({ onClick }) { + const games = useContext(GamesContext); + + const selectedGame = games.findGame({ uuid: games.active.selectedUUID }); + const gameStatus = selectedGame?.status; + const isReady = gameStatus === 'GAME_BOARD_WAIT_FOR_YOU' ? true : ''; + + const checkStatus = () => { + if (!selectedGame) + return alert('You have to select a game'); + + if (gameStatus === 'DRAW_REQUEST_WAIT_FOR_OPPONENT') + return alert('A draw was alredy offered to the opponent'); + + if (!isReady) + return alert('You can ask for a draw only during your turn'); + + onClick(selectedGame.uuid); + } + + if (gameStatus === 'DRAW_REQUEST_WAIT_FOR_YOU') + return; // You can not send counter draw request + + return ( + + ) +} + +export function DrawAccept({ onClick }) { + const games = useContext(GamesContext); + + const selectedGame = games.findGame({ uuid: games.active.selectedUUID }); + const gameStatus = selectedGame?.status; + + if (gameStatus === 'DRAW_REQUEST_WAIT_FOR_YOU') + return ( + + ) +} + +export function DrawReject({ onClick }) { + const games = useContext(GamesContext); + + const selectedGame = games.findGame({ uuid: games.active.selectedUUID }); + + if (selectedGame?.status === 'DRAW_REQUEST_WAIT_FOR_YOU') + return ( + + ) +} \ No newline at end of file diff --git a/webapp/src/container/games/action/DrawAcq.jsx b/webapp/src/container/games/action/DrawAcq.jsx deleted file mode 100644 index 26b9a99..0000000 --- a/webapp/src/container/games/action/DrawAcq.jsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; - -export default function DrawAcq() { - - return -} diff --git a/webapp/src/container/games/action/DrawReq.jsx b/webapp/src/container/games/action/DrawReq.jsx deleted file mode 100644 index 11cac07..0000000 --- a/webapp/src/container/games/action/DrawReq.jsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; - -export default function DrawReq() { - - return -} diff --git a/webapp/src/container/games/action/Surrender.jsx b/webapp/src/container/games/action/Surrender.jsx index 9cedf0d..32cd54a 100644 --- a/webapp/src/container/games/action/Surrender.jsx +++ b/webapp/src/container/games/action/Surrender.jsx @@ -14,9 +14,9 @@ export default function Surrender({ onClick }) { return ( ) } \ No newline at end of file diff --git a/webapp/src/container/games/view/GameSelector.jsx b/webapp/src/container/games/view/GameSelector.jsx index 43dc176..ad9a429 100644 --- a/webapp/src/container/games/view/GameSelector.jsx +++ b/webapp/src/container/games/view/GameSelector.jsx @@ -49,10 +49,10 @@ export function ActiveGameSelector({ onSelect }) { onSelect(uuid); } - const yoursList = games.gamesList.filter(game => game.status === 'GAME_BOARD_WAIT_FOR_YOU') + const yoursList = games.gamesList.filter(game => (game.status === 'GAME_BOARD_WAIT_FOR_YOU' || game.status === 'DRAW_REQUEST_WAIT_FOR_YOU')) .map(game => ) - const opponentsList = games.gamesList.filter(game => game.status === 'GAME_BOARD_WAIT_FOR_OPPONENT') + const opponentsList = games.gamesList.filter(game => (game.status === 'GAME_BOARD_WAIT_FOR_OPPONENT' || game.status === 'DRAW_REQUEST_WAIT_FOR_OPPONENT')) .map(game => ) return ( diff --git a/webapp/src/reducer/games.js b/webapp/src/reducer/games.js index 528beae..b5ae12e 100644 --- a/webapp/src/reducer/games.js +++ b/webapp/src/reducer/games.js @@ -27,10 +27,15 @@ export const gamesInitialState = { // Network isPollingGamesList: false, isPushingNewGame: false, + isPushingGameProposalCancel: false, isPushingGameProposalReject: false, isPushingGameProposalAccept: false, - isPushingActiveGameSurrender: false, + + isPushingGameSurrender: false, + isPushingGameDrawRequest: false, + isPushingGameDrawAccept: false, + isPushingGameDrawReject: false, findGame, nextGameList,