diff --git a/assets/css/_game_grid.scss b/assets/css/_game_grid.scss index a2af715..03fc68b 100644 --- a/assets/css/_game_grid.scss +++ b/assets/css/_game_grid.scss @@ -1,7 +1,24 @@ .game-grid { display: grid; grid-gap: $base-spacing; - grid-template-areas: "board moves"; - grid-template-columns: min-content 1fr; - grid-template-rows: var(--board-size); +} + +@media (min-aspect-ratio: 10/11) { + .game-grid { + grid-template-areas: + "board game-info" + "board move-list"; + grid-template-columns: min-content 1fr; + grid-template-rows: min-content 1fr; + } +} + +@media (max-aspect-ratio: 10/11) { + .game-grid { + grid-template-areas: + "game-info" + "board" + "move-list"; + grid-template-rows: min-content min-content min-content; + } } diff --git a/assets/css/_game_info.scss b/assets/css/_game_info.scss new file mode 100644 index 0000000..746bb80 --- /dev/null +++ b/assets/css/_game_info.scss @@ -0,0 +1,3 @@ +.game-info { + grid-area: game-info; +} diff --git a/assets/css/_layout.scss b/assets/css/_layout.scss index 25d5eb5..1c01222 100644 --- a/assets/css/_layout.scss +++ b/assets/css/_layout.scss @@ -20,6 +20,10 @@ h1 { margin: 0; } +main { + margin-top: 5vmin; +} + .container { margin: 0 auto; width: 90%; diff --git a/assets/css/_move_list.scss b/assets/css/_move_list.scss index 235f151..ab3eabb 100644 --- a/assets/css/_move_list.scss +++ b/assets/css/_move_list.scss @@ -1,5 +1,5 @@ .move-list { - grid-area: moves; + grid-area: move-list; overflow-y: auto; } diff --git a/assets/css/app.scss b/assets/css/app.scss index e55b32d..76bbed1 100644 --- a/assets/css/app.scss +++ b/assets/css/app.scss @@ -15,4 +15,5 @@ @import "game_list"; @import "board"; @import "move_list"; +@import "game_info"; @import "game_grid"; diff --git a/assets/js/app.js b/assets/js/app.js index dcb8d3f..adb6cd8 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -14,6 +14,7 @@ import { setGameId } from "./store/actions"; import ChessBoard from "./components/chess-board"; import MoveList from "./components/move-list"; +import GameInfo from "./components/game-info"; const store = createStore(chessBoardReducer); @@ -31,6 +32,11 @@ class App extends React.Component { return store.getState().moves; } + get opponent() { + const { store } = this.props; + return store.getState().opponent; + } + render() { const { store, gameId } = this.props; @@ -42,6 +48,8 @@ class App extends React.Component { channel={this.channel} /> + + ); diff --git a/assets/js/components/game-info.js b/assets/js/components/game-info.js new file mode 100644 index 0000000..904028f --- /dev/null +++ b/assets/js/components/game-info.js @@ -0,0 +1,18 @@ +import React from "react"; +import { connect } from "react-redux"; + +const GameInfo = (props) => { + return ( +
+

Playing {props.opponent}

+
+ ); +}; + +const mapStateToProps = (state) => { + return { + opponent: state.opponent, + }; +}; + +export default connect(mapStateToProps)(GameInfo); diff --git a/assets/js/reducers/chess-board.js b/assets/js/reducers/chess-board.js index beb47eb..298c239 100644 --- a/assets/js/reducers/chess-board.js +++ b/assets/js/reducers/chess-board.js @@ -9,6 +9,11 @@ const chessBoardReducer = (state = defaultState, action) => { .set("player", action.player) .toJS(); + case "SET_OPPONENT": + return Immutable.fromJS(state) + .set("opponent", action.opponent) + .toJS(); + case "SET_GAME": return Immutable.fromJS(state) .set("board", action.board) diff --git a/assets/js/services/channel.js b/assets/js/services/channel.js index 73989c1..6f30a0c 100644 --- a/assets/js/services/channel.js +++ b/assets/js/services/channel.js @@ -1,5 +1,5 @@ import socket from "../socket"; -import { setPlayer, setGame, setAvailableMoves } from "../store/actions"; +import { setPlayer, setOpponent, setGame, setAvailableMoves } from "../store/actions"; class Channel { constructor(store, gameId) { @@ -21,6 +21,7 @@ class Channel { this.channel.on("game:update", data => { if (data.player != undefined) { this.store.dispatch(setPlayer(data.player)); + this.store.dispatch(setOpponent(data.opponent)); } this.store.dispatch(setGame(data)); }); diff --git a/assets/js/store/actions.js b/assets/js/store/actions.js index c4b1b0c..9d6ee7b 100644 --- a/assets/js/store/actions.js +++ b/assets/js/store/actions.js @@ -1,4 +1,5 @@ const SET_PLAYER = "SET_PLAYER"; +const SET_OPPONENT = "SET_OPPONENT"; const SET_GAME = "SET_GAME"; const SET_AVAILABLE_MOVES = "SET_AVAILABLE_MOVES"; const SET_GAME_ID = "SET_GAME_ID"; @@ -11,6 +12,13 @@ export const setPlayer = (player) => { }; }; +export const setOpponent = (opponent) => { + return { + type: SET_OPPONENT, + opponent, + }; +}; + export const setGame = (data) => { return { type: SET_GAME, diff --git a/assets/js/store/default-state.js b/assets/js/store/default-state.js index 0dfc0f2..9fc5c61 100644 --- a/assets/js/store/default-state.js +++ b/assets/js/store/default-state.js @@ -2,6 +2,7 @@ const defaultState = { selectedSquare: null, player: null, + opponent: null, turn: null, state: null, diff --git a/lib/chess_web/channels/game_channel.ex b/lib/chess_web/channels/game_channel.ex index aea15aa..39763f5 100644 --- a/lib/chess_web/channels/game_channel.ex +++ b/lib/chess_web/channels/game_channel.ex @@ -21,10 +21,13 @@ defmodule ChessWeb.GameChannel do socket.assigns.current_user_id |> Game.for_user_id() |> preload(:moves) + |> preload(:user) + |> preload(:opponent) |> Repo.get!(game_id) payload = %{ player: player(socket, game), + opponent: opponent(socket, game), board: Board.transform(game.board), turn: game.turn, state: game.state, @@ -116,4 +119,12 @@ defmodule ChessWeb.GameChannel do "black" end end + + defp opponent(socket, game) do + if game.user_id == socket.assigns.current_user_id do + game.opponent.name + else + game.user.name + end + end end diff --git a/lib/chess_web/templates/game/show.html.eex b/lib/chess_web/templates/game/show.html.eex index 18255f9..9c68a44 100644 --- a/lib/chess_web/templates/game/show.html.eex +++ b/lib/chess_web/templates/game/show.html.eex @@ -1,4 +1,2 @@ -

<%= gettext "Game with %{name}", name: opponent(@conn, @game).name %>

-