diff --git a/webapp/src/App.js b/webapp/src/App.js index 9730e57..db764f8 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -26,6 +26,7 @@ export default function App() { const players = { leaderboard, + currentUser: user.username, isCurrentUser: (playerName) => user?.isCurrentUser(playerName) === true ? true : null }; diff --git a/webapp/src/components/Checkers.jsx b/webapp/src/components/Checkers.jsx index 7d0817c..2cda7d3 100644 --- a/webapp/src/components/Checkers.jsx +++ b/webapp/src/components/Checkers.jsx @@ -26,6 +26,9 @@ export function Stone({ color }) { case Color.black: return BlackStone(); + case '': + return; // no color :) + default: console.warn("Unknown color: ", color) } diff --git a/webapp/src/container/Games.jsx b/webapp/src/container/Games.jsx index ae7cc80..ed2337b 100644 --- a/webapp/src/container/Games.jsx +++ b/webapp/src/container/Games.jsx @@ -4,16 +4,7 @@ import { NavLink, Routes, Route } from 'react-router-dom'; import NewGame from './games/view/NewGame'; import { GameProposalSelector, ActiveGameSelector, GameArchiveSelector } from './games/view/GameSelector'; - -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 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'; - +import { Create, Accept, Reject, Cancel, DrawRequest, DrawAccept, DrawReject, Surrender, Backward, Forward } from './games/ActionPanel'; import GameBoard from './games/GameBoard'; import Message2Opponent from './games/Message2Opponent'; import Counter from '../components/Counter'; @@ -29,11 +20,11 @@ export default function Games({ context: { gamesReducer, gamesApi }, players })
- +
- + {/* */} @@ -57,15 +48,14 @@ function ViewSelector({ games }) { ) } -function ViewProvider({ gamesReducer, players }) { - const [/*games*/, dispatchGames] = gamesReducer; +function ViewProvider({ dispatchGames, players }) { return (
dispatchGames({ type: 'nextNewGame', whitePlayer, blackPlayer })} + dispatchGames({ type: 'nextNewGame', opponentName, opponentColor })} players={players} /> } /> @@ -87,15 +77,13 @@ function ViewProvider({ gamesReducer, players }) { ) } -function ActionPanel({ players, gamesApi }) { +function ActionPanel({ gamesApi }) { return (
gamesApi.pushNewGame(reqParams)} - /> + gamesApi.pushNewGame(reqParams)} /> } /> { + if (!hasOpponent) + return alert("You have to select an opponent"); + + const reqParams = { + opponentName: games.newGame.opponentName, + opponentColor: games.newGame.opponentColor, + board: null, // default board configuration + message: games.newGame.message + } + + onClick(reqParams); + } + + return ( + + ) +} + +/* + * GameProposal actions + */ + +export function Accept({ onClick }) { + const games = useContext(GamesContext); + + const selectedGame = games.findGame({ uuid: games.proposal.selectedUUID }); + const isReady = selectedGame?.status === 'GAME_PROPOSAL_WAIT_FOR_YOU' ? true : ''; + + if (selectedGame?.status !== 'GAME_PROPOSAL_WAIT_FOR_OPPONENT') + return ( + + ) +} + +export function Reject({ onClick }) { + const games = useContext(GamesContext); + + const selectedGame = games.findGame({ uuid: games.proposal.selectedUUID }); + const isReady = selectedGame?.status === 'GAME_PROPOSAL_WAIT_FOR_YOU' ? true : ''; + + if (selectedGame?.status !== 'GAME_PROPOSAL_WAIT_FOR_OPPONENT') + return ( + + ) +} + +export function Cancel({ onClick }) { + const games = useContext(GamesContext); + + const selectedGame = games.findGame({ uuid: games.proposal.selectedUUID }); + const isReady = selectedGame?.status === 'GAME_PROPOSAL_WAIT_FOR_OPPONENT' ? true : ''; + + if (selectedGame?.status === 'GAME_PROPOSAL_WAIT_FOR_OPPONENT') + return ( + + ) +} + +/* + * Game actions + */ + +export function Surrender({ onClick }) { + const games = useContext(GamesContext); + + const selectedGame = games.findGame({ uuid: games.active.selectedUUID }); + const gameStatus = selectedGame?.status; + const isReady = (gameStatus === 'GAME_BOARD_WAIT_FOR_OPPONENT' || gameStatus === 'GAME_BOARD_WAIT_FOR_YOU') ? true : ''; + + if (gameStatus === 'DRAW_REQUEST_WAIT_FOR_YOU' || gameStatus === 'DRAW_REQUEST_WAIT_FOR_OPPONENT') + return; // You shall not surrender if there is an active tie negotiations + + return ( + + ) +} + +/* + * Game actions: Draw + */ + +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 ( + + ) +} + +/* + * GameArchive actions + */ + +export function Backward() { + + return +} + +export function Forward() { + + return +} \ No newline at end of file diff --git a/webapp/src/container/games/GameBoard.jsx b/webapp/src/container/games/GameBoard.jsx index ea73a33..6c849fd 100644 --- a/webapp/src/container/games/GameBoard.jsx +++ b/webapp/src/container/games/GameBoard.jsx @@ -9,19 +9,30 @@ export default function GameBoard() { const games = useContext(GamesContext); const {pathname} = useLocation(); - var whiteName = ''; - var blackName = ''; + let opponentName = ''; + let opponentColor = Color.white; // defaut color if (matchPath('/games/new', pathname)) { - whiteName = games.newGame.whitePlayer; - blackName = games.newGame.blackPlayer; + opponentName = games.newGame.opponentName; + opponentColor = games.newGame.opponentColor; } + // if (matchPath('/games/proposal', pathname)) { + // const selectedGame = games.findGame({ uuid: games.proposal.selectedUUID }); + + // const opponentColor = selectedGame + + // whiteName = selectedGame.newGame.whitePlayer; + // blackName = games.newGame.blackPlayer; + // } + + const myColor = Color.opposite(opponentColor); + return (
- + - +
) } \ No newline at end of file diff --git a/webapp/src/container/games/Message2Opponent.jsx b/webapp/src/container/games/Message2Opponent.jsx index 32d1d97..0d1f258 100644 --- a/webapp/src/container/games/Message2Opponent.jsx +++ b/webapp/src/container/games/Message2Opponent.jsx @@ -18,11 +18,11 @@ export default function Message2Opponent({ dispatchGames }) { var externalValue = ''; if (matchPath('/games/new', pathname)) - externalValue = games.newGame.message2opponent; + externalValue = games.newGame.message; else if (matchPath('/games/proposal', pathname)) - externalValue = games.proposal.message2opponent; + externalValue = games.proposal.message; else if (matchPath('/games/active', pathname)) - externalValue = games.active.message2opponent; + externalValue = games.active.message; if (value !== externalValue) setValue(externalValue); @@ -30,17 +30,17 @@ export default function Message2Opponent({ dispatchGames }) { /* --- */ - const sync = (message2opponent) => { + const sync = (message) => { syncTimeoutRef.current = null; if (matchPath('/games/new', pathname)) - return dispatchGames({ type: 'nextNewGame', message2opponent }); + return dispatchGames({ type: 'nextNewGame', message }); if (matchPath('/games/proposal', pathname)) - return dispatchGames({ type: 'nextProposal', message2opponent }); + return dispatchGames({ type: 'nextProposal', message }); if (matchPath('/games/active', pathname)) - return dispatchGames({ type: 'nextActive', message2opponent }); + return dispatchGames({ type: 'nextActive', message }); console.warn('unknown path'); } diff --git a/webapp/src/container/games/action/Accept.jsx b/webapp/src/container/games/action/Accept.jsx deleted file mode 100644 index a23b0b6..0000000 --- a/webapp/src/container/games/action/Accept.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import React, { useContext } from 'react'; -import Wobler from '../../../components/Wobler'; -import { GamesContext } from '../../../context/games'; - -export default function Accept({ onClick }) { - const games = useContext(GamesContext); - - const selectedGame = games.findGame({ uuid: games.proposal.selectedUUID }); - const isReady = selectedGame?.status === 'GAME_PROPOSAL_WAIT_FOR_YOU' ? true : ''; - - if (selectedGame?.status !== 'GAME_PROPOSAL_WAIT_FOR_OPPONENT') - return ( - - ) -} \ No newline at end of file diff --git a/webapp/src/container/games/action/Backward.jsx b/webapp/src/container/games/action/Backward.jsx deleted file mode 100644 index 4ac5747..0000000 --- a/webapp/src/container/games/action/Backward.jsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; - -export default function Backward() { - - return -} diff --git a/webapp/src/container/games/action/Cancel.jsx b/webapp/src/container/games/action/Cancel.jsx deleted file mode 100644 index 76341f8..0000000 --- a/webapp/src/container/games/action/Cancel.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import React, { useContext } from 'react'; -import Wobler from '../../../components/Wobler'; -import { GamesContext } from '../../../context/games'; - -export default function Cancel({ onClick }) { - const games = useContext(GamesContext); - - const selectedGame = games.findGame({ uuid: games.proposal.selectedUUID }); - const isReady = selectedGame?.status === 'GAME_PROPOSAL_WAIT_FOR_OPPONENT' ? true : ''; - - if (selectedGame?.status === 'GAME_PROPOSAL_WAIT_FOR_OPPONENT') - return ( - - ) -} diff --git a/webapp/src/container/games/action/Create.jsx b/webapp/src/container/games/action/Create.jsx deleted file mode 100644 index 1e91983..0000000 --- a/webapp/src/container/games/action/Create.jsx +++ /dev/null @@ -1,63 +0,0 @@ -import React, { useContext } from 'react'; -import { GamesContext } from '../../../context/games'; -import Wobler from '../../../components/Wobler'; -import { Color } from '../../../components/Checkers'; - - -export default function Create({ isCurrentUser, onClick }) { - const games = useContext(GamesContext); - - const hasPlayers = checkPlayers(games.newGame); - const hasCurrentUser = checkCurrentUser(games.newGame, isCurrentUser); - - const prepareNewGameRequest = () => { - if (!hasPlayers) - return alert("Black and White players must be selected for the game"); - - if (!hasCurrentUser) - return alert("You must be one of the selected players"); - - /* - * Prepare & send NewGame request - */ - const [opponentName, opponentColor] = getOpponent(games.newGame, isCurrentUser); - - const reqParams = { - opponentName, - opponentColor, - board: null, // default board configuration - message: games.newGame.message2opponent - } - - onClick(reqParams); - } - - return ( - - ) -} - -function checkPlayers({ whitePlayer, blackPlayer }) { - return whitePlayer && blackPlayer - && whitePlayer !== blackPlayer; -} - -function checkCurrentUser({ whitePlayer, blackPlayer }, isCurrentUser) { - return isCurrentUser(whitePlayer) || isCurrentUser(blackPlayer); -} - -function getOpponent({whitePlayer, blackPlayer}, isCurrentUser) { - if (isCurrentUser(whitePlayer)) { - return [blackPlayer, Color.black]; - } - - if (isCurrentUser(blackPlayer)) { - return [whitePlayer, Color.white]; - } - - return ['', '']; -} \ No newline at end of file diff --git a/webapp/src/container/games/action/Draw.jsx b/webapp/src/container/games/action/Draw.jsx deleted file mode 100644 index 89cf44d..0000000 --- a/webapp/src/container/games/action/Draw.jsx +++ /dev/null @@ -1,60 +0,0 @@ -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/Forward.jsx b/webapp/src/container/games/action/Forward.jsx deleted file mode 100644 index 0365bfa..0000000 --- a/webapp/src/container/games/action/Forward.jsx +++ /dev/null @@ -1,6 +0,0 @@ -import React from 'react'; - -export default function Forward() { - - return -} diff --git a/webapp/src/container/games/action/Reject.jsx b/webapp/src/container/games/action/Reject.jsx deleted file mode 100644 index b88e28b..0000000 --- a/webapp/src/container/games/action/Reject.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import React, { useContext } from 'react'; -import Wobler from '../../../components/Wobler'; -import { GamesContext } from '../../../context/games'; - -export default function Reject({ onClick }) { - const games = useContext(GamesContext); - - const selectedGame = games.findGame({ uuid: games.proposal.selectedUUID }); - const isReady = selectedGame?.status === 'GAME_PROPOSAL_WAIT_FOR_YOU' ? true : ''; - - if (selectedGame?.status !== 'GAME_PROPOSAL_WAIT_FOR_OPPONENT') - return ( - - ) -} \ No newline at end of file diff --git a/webapp/src/container/games/action/Surrender.jsx b/webapp/src/container/games/action/Surrender.jsx deleted file mode 100644 index 32cd54a..0000000 --- a/webapp/src/container/games/action/Surrender.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React, { useContext } from 'react'; -import Wobler from '../../../components/Wobler'; -import { GamesContext } from '../../../context/games'; - -export default function Surrender({ onClick }) { - const games = useContext(GamesContext); - - const selectedGame = games.findGame({ uuid: games.active.selectedUUID }); - const gameStatus = selectedGame?.status; - const isReady = (gameStatus === 'GAME_BOARD_WAIT_FOR_OPPONENT' || gameStatus === 'GAME_BOARD_WAIT_FOR_YOU') ? true : ''; - - if (gameStatus === 'DRAW_REQUEST_WAIT_FOR_YOU' || gameStatus === 'DRAW_REQUEST_WAIT_FOR_OPPONENT') - return; // You shall not surrender if there is an active tie negotiations - - return ( - - ) -} \ No newline at end of file diff --git a/webapp/src/container/games/view/NewGame.jsx b/webapp/src/container/games/view/NewGame.jsx index a729a70..6085997 100644 --- a/webapp/src/container/games/view/NewGame.jsx +++ b/webapp/src/container/games/view/NewGame.jsx @@ -3,10 +3,20 @@ import React, { useContext } from 'react'; import { GamesContext } from '../../../context/games'; import DropdownList from '../../../components/DropdownList'; -import { WhiteStone, BlackStone } from '../../../components/Checkers'; +import { Color, WhiteStone, BlackStone } from '../../../components/Checkers'; -export default function NewGame({ players, onSelectPlayer }) { +export default function NewGame({ players, setOpponent }) { const games = useContext(GamesContext); + + const [whitePlayer, blackPlayer] = (() => { + if (games.newGame.opponentColor === Color.white) + return [games.newGame.opponentName, players.currentUser]; + + if (games.newGame.opponentColor === Color.black) + return [players.currentUser, games.newGame.opponentName]; + + return ['', '']; + })(); // <<-- Execute! /* * Name options @@ -24,37 +34,22 @@ export default function NewGame({ players, onSelectPlayer }) { const blackOptions = Array(nameOptions) blackOptions.push() - /* - * Radiobutton - */ - const radioButton = (whitePlayer, blackPlayer) => { - if (whitePlayer !== '' && whitePlayer === games.newGame.blackPlayer) { - blackPlayer = ''; - } - if (blackPlayer !== '' && blackPlayer === games.newGame.whitePlayer) { - whitePlayer = ''; - } - - onSelectPlayer(whitePlayer, blackPlayer); - } - - const setWhitePlayer = (name) => { - radioButton(name, games.newGame.blackPlayer); - } - - const setBlackPlayer = (name) => { - radioButton(games.newGame.whitePlayer, name); - } - /* * The Component */ + const onSelect = (name, color) => { + if (players.isCurrentUser(name)) + setOpponent(games.newGame.opponentName, Color.opposite(color)); + else + setOpponent(name, color); + } + return (
- + onSelect(name, Color.white)} optionsList={whiteOptions} /> - vs - - + onSelect(name, Color.black)} optionsList={blackOptions} />
) diff --git a/webapp/src/reducer/games.js b/webapp/src/reducer/games.js index b5ae12e..9dc5f41 100644 --- a/webapp/src/reducer/games.js +++ b/webapp/src/reducer/games.js @@ -5,19 +5,19 @@ export const gamesInitialState = { gamesList: null, newGame: { - whitePlayer: '', - blackPlayer: '', - message2opponent: '', + opponentName: '', + opponentColor: '', + message: '', }, proposal: { selectedUUID: null, - message2opponent: '', + message: '', }, active: { selectedUUID: null, - message2opponent: '', + message: '', }, archive: { diff --git a/webapp/src/reducer/user.js b/webapp/src/reducer/user.js index 1cf1265..b019d0f 100644 --- a/webapp/src/reducer/user.js +++ b/webapp/src/reducer/user.js @@ -15,7 +15,7 @@ function reducer(state, action) { case 'parse': return { ...state, - username: action.userJson.username + username: action.userJson.holdingIdentity.name }; default: