In part 3 we added Material-UI and and components layout and play a full game. In this part, we will add the remaining components and styles needed to complete the game.

TitleBar and Menu components

To give us the ability to start a new game without having to play an entire game first, we will need to add a title bar and a menu component.

The TitleBar component is the container component that will display the title and hold the Menu component for the game. We consider it a container component because it will hold local state and respond to events from the menu interaction.

The Menu component is a presentational component that shows a menu and calls the event handlers that are passed to it from the TitleBar component.

I chose the fiber_new icon because it has, “new,” in it. You can choose whatever icon from Material-Icons you want as a placeholder for the new game item.

Updating App component

Now that we have the TitleBar and Menu components created, we will update the App component by replacing the placeholder header with our TitleBar.

If we run the game now, we should see a blue title bar with a hamburger menu to the left where we can toggle the ‘New game’ menu.

PlayerInfo and GameoverDialog components

Next, we will add the PlayerInfo and GameoverDialog. This will allow us to see who the current player is and show a dialog when the game is over. The dialog will also allow us to trigger a new game without having to close it and use the ‘New game’ menu.

The PlayerInfo component is a simple presentational component that takes a player and gameover and displays the current player or a game over message.

The Gameover dialog, also a presentational component, will show either a winning player or a draw game message and trigger events based on the player’s action to start a new game or to close the dialog.

Updating operations

Since we are going to show the game over dialog from the Game component, we need to update the checkWinner operation to return a boolean if there is a winner.

In the test.js file for the game duck, update the tests we wrote for checkWinner by assigning the return value of the checkWinner function to a variable. Add in expect statements to check that the correct value is returned for each test.

Open the operations.js file and add a variable for hasWinner , set it to either true or false and return it to the caller.

Run yarn test to make sure all of our tests are still passing.

Updating Game component

The last step is to update the Game component with the PlayerInfo and Gameover dialog components.

Like the TitleBar, we are going to keep some local state to track whether or not to show and hide the game over dialog when a game has ended. We will add two new event handlers to handle when the dialog wants to close and when a player clicks on ‘yes’ or ‘no.’

When the player clicks ‘no’ or in the gray space (tablet or larger screens) outside of the dialog, we handle it by setting the local state, showDialog , to false . If the player clicks ‘yes’ we dispatch the newGame action to start a new game.

Finally, we replace the old player information with the PlayerInfo component.

Mobile game over dialog

Tablet or larger game over dialog

Playing the full game

Run yarn start to launch the completed game.

Since we focused on mobile first, let’s try and play on a mobile device using Chrome’s device emulation.

Optional: deploy to Surge.sh

If you really wanted to play the game on a mobile device, you can create a free account on surge.sh, install the surge npm module then deploy the ./dist directory out to a custom surge domain.

I will update the package.json file with a new script for doing this, all you need to do is run it with to publish it once your account is created.

// install surge globally so you can use it anywhere

yarn global add surge // then we run the script to publish

yarn surge // console output:

$ yarn build && surge ./dist

$ yarn clean && webpack --config webpack.config.js --progress

$ rimraf ./dist // build output:

// ...

// ... // surge sample output:

Running as <your_account> project: ./dist domain: <autogenerated-domain>.surge.sh upload: [====================] 100% eta: 0.0s (9 files, 3238471 bytes) CDN: [====================] 100% IP: <surge_ip_address> Success! - Published to <autogenerated-domain>.surge.sh

Running, yarn surge , will build the app and then publish it to surge. I’ve published the code from part 4 to the url below using surge.

To be continued…

That is it, see you in the next and final part.

Source for this part: https://github.com/vanister/medium.com/tree/part-4