Last fixes before MVP
This week, we’ll be tidying up before deploying our app to production (next week!!!).
There are a few things that we didn’t implement to make the game actually playable:
- Users shouldn’t see other players votes before the end of the vote
- Only the owner of the game should be able to reveal the votes
- Adding the ability to name a game (technically not compulsory, but it’s a nice addition anyway)
Supporting face-down cards (commit)
To hide the votes of other players until the votes are revealed, we need to design a face-down card:
In this case, we are Alice, and we can’t see Bob’s vote until the creator of the game chooses to reveal all votes.
To achieve that, we simply add a new prop on our Card component: faceDown. This prop is a boolean, and if true, the card will be shown face down without showing its actual value.
For the stripes on the back of the card, we are using the repeating-linear-gradient from CSS 3.
We then add the logic that decides whether a card should be face down here. It will be face down if the story is not flipped (i.e. all votes are revealed), AND if the vote was not your own vote. Indeed, we should always show your own votes.
Allowing the game owner to reveal all votes (commit)
This feature requires both server and client changes.
We first need to add a new action, FLIP_STORY, and a corresponding handler on the server.
The handler logic is pretty standard, we find the corresponding story from its ID, then turn the “flipped” property to true. We then send this change to all the other players.
On the client side, we add a new button on the story Card, allowing the owner of the game to flip the story. Note here that we are checking if the current player is the owner before showing the button.
Placeholder when there are no stories (commit)
When a user creates a game, the game doesn’t have any story to vote on yet.
This is often referred as a “null state”, when the UI has no data to display.
When that happens, the UI must display some kind of message, helping the user with what they need to do next. In our case, we want to tell the user to create stories.
On line 92, we add a <NoStory /> component, only displayed when there’s no story selected (which means no stories are available).
The other change we made on this commit was, when a user creates his first story, that this new story is automatically selected and becomes the current story.
Adding a name to the game (commit)
When creating a game, we want to be able to give it a name. A typical name would be your team’s name followed by the today’s date for instance.
This name should be easily editable, and synchronised across all players.
It also requires both server and client side changes.
We first create two new actions:
- RENAME_GAME: this is the one triggered by the user renaming. This is going from the client to the server.
- RECEIVE_GAME_NAME_CHANGE: this is the one sent by the server to all the other clients, so they can update their own name. We could have used the SEND_ALL_GAME_DATA one, but it would have sent the entire set of data, on each keystroke, which would have not be great, performance-wise.
The handler on the server is very trivial, just editing the game’s name property and sending it back to all the other players.
The UI side is a bit more interesting: we need to create a new component that allows inline editing: the EditableLabel.
A good component should have a very simple API, a simple interface. For an editable label, the only two prop we need is a value, and an onChange event when that value is edited. The rest (the fact that it’s in edit mode or not for instance), should be managed internally, and should be part of the state.
Also, when we click on the label to switch to edit mode, we want to focus on the input (a textarea in this case) automatically, to avoid the user having to click twice.
To achieve this, we need to use a React ref. I recommend to read the documentation (https://reactjs.org/docs/refs-and-the-dom.html) on the subject.
Here is how it works (in our case):
- Create a reference object (on the component constructor)
- Set this reference on the component you want to act upon (the textarea here)
- Use this reference to access the DOM node you wanted, so you can call methods on it. In this particular line, we focus on the textarea after the editMode was set to true (making said textarea visible).
Next Week
Next week will be a major milestone, we are going to deploy our app to a brand new server and it will be live! Stay tuned.