expand character select

This commit is contained in:
Antti Pilto 2016-07-29 21:39:23 +03:00
parent 721f90aabb
commit a7e521512b
8 changed files with 258 additions and 11 deletions

View file

@ -2,6 +2,7 @@ import React, { Component } from 'react';
import AuthService from '../../utils/AuthService' import AuthService from '../../utils/AuthService'
import './App.scss'; import './App.scss';
import Navbar from '../Navbar/Navbar'; import Navbar from '../Navbar/Navbar';
import GameContainer from '../GameContainer/GameContainer';
const options = {}; const options = {};
const auth = new AuthService(__AUTH0_CLIENT_ID__, __AUTH0_DOMAIN__, options); const auth = new AuthService(__AUTH0_CLIENT_ID__, __AUTH0_DOMAIN__, options);
@ -11,6 +12,7 @@ class App extends Component {
super(props); super(props);
this.state = { this.state = {
isAuthenticated: this.isAuthenticated(), isAuthenticated: this.isAuthenticated(),
gameState: 'chooseCharacters'
/*profile: auth.getProfile()*/ /*profile: auth.getProfile()*/
} }
auth.on('profile_updated', (newProfile) => { auth.on('profile_updated', (newProfile) => {
@ -19,6 +21,8 @@ class App extends Component {
}) })
this.logout = this.logout.bind(this); this.logout = this.logout.bind(this);
this.getNickName = this.getNickName.bind(this); this.getNickName = this.getNickName.bind(this);
this.startGame = this.startGame.bind(this);
this.endGame = this.endGame.bind(this);
} }
isAuthenticated() { isAuthenticated() {
@ -29,19 +33,38 @@ class App extends Component {
return auth.getProfile() && auth.getProfile().hasOwnProperty('nickname')?auth.getProfile().nickname:''; return auth.getProfile() && auth.getProfile().hasOwnProperty('nickname')?auth.getProfile().nickname:'';
} }
startGame() {
this.setState({gameState: 'game'});
}
endGame() {
this.setState({gameState: 'chooseCharacters'});
}
logout() { logout() {
auth.logout(); auth.logout();
this.setState({isAuthenticated: this.isAuthenticated()}); this.setState({isAuthenticated: this.isAuthenticated()});
} }
render() { render() {
let loginButton = !this.state.isAuthenticated ? let loginButton = !this.state.isAuthenticated ?
<button className="btn btn-info login-button" onClick={auth.login.bind(this)}>Log in to save your progress!</button> : ''; <button className="btn btn-info login-button" onClick={auth.login.bind(this)}>Log in to save your progress!</button> : '';
return ( return (
<div> <div>
<Navbar isAuthenticated={this.state.isAuthenticated} nickName={this.getNickName()} handleLogin={auth.login.bind(this)} handleLogout={this.logout} /> <Navbar isAuthenticated={this.state.isAuthenticated}
handleLogin={auth.login.bind(this)}
handleLogout={this.logout}
gameState={this.state.gameState}
handleEndGame={this.endGame}
/>
<div className="container game"> <div className="container game">
<GameContainer
isAuthenticated={this.state.isAuthenticated}
nickName={this.getNickName()}
gameState={this.state.gameState}
handleStartGame={this.startGame}
/>
<div className="row text-center">{loginButton}</div> <div className="row text-center">{loginButton}</div>
</div> </div>
</div> </div>

View file

@ -20,5 +20,5 @@ body {
padding: 6px 15px; padding: 6px 15px;
} }
.game { .game {
padding-top: 80px; padding-top: 70px;
} }

View file

@ -0,0 +1,29 @@
import React, { Component } from 'react';
class CharacterRow extends Component {
render() {
let strCharacters = '';
this.props.characters.map(function(items) {
Object.keys(items).map(function(item) {
if(item!='selected') strCharacters+=item+', ';
});
});
strCharacters = strCharacters.slice(0, -2);
let chooseRow = (
<div className="choose-row">
<span className={this.props.selected ?
'glyphicon glyphicon-small glyphicon-check' :
'glyphicon glyphicon-small glyphicon-unchecked'}></span> {strCharacters}
</div>
);
return (
<div>
{chooseRow}
</div>
);
}
}
export default CharacterRow;

View file

@ -0,0 +1,108 @@
import React, { Component } from 'react';
import './ChooseCharacters.scss';
import CharacterRow from './CharacterRow';
let kanaArray = [
"あ","い","う","え","お",
"か","き","く","け","こ",
"さ","し","す","せ","そ",
"た","ち","つ","て","と",
"な","に","ぬ","ね","の",
"は","ひ","ふ","へ","ほ",
"ま","み","む","め","も",
"や","ゆ","よ",
"ら","り","る","れ","ろ",
"わ","を","ん"
];
let romajiArray = [
"a","i","u","e","o",
"ka","ki","ku","ke","ko",
"sa","shi","su","se","so",
"ta","chi","tsu","te","to",
"na","ni","nu","ne","no",
"ha","hi","fu","he","ho",
"ma","mi","mu","me","mo",
"ya","yu","yo",
"ra","ri","ru","re","ro",
"wa","wo","n"
];
/*let hiraganaItems = {
group1: { a: 'あ', i: 'い', u: 'う', e: 'え', o: 'お' },
group2: { ka: 'か', ki: 'き', ku: 'く', ke: 'け', ko: 'こ' }
}*/
class ChooseCharacters extends Component {
constructor(props) {
super(props);
this.state = {
hiraganaItems: [
{
group1: [
{ selected: true, a: 'あ', i: 'い', u: 'う', e: 'え', o: 'お' }
],
group2: [
{ selected: false, ka: 'か', ki: 'き', ku: 'く', ke: 'け', ko: 'こ' }
]
}
]
}
this.startGame = this.startGame.bind(this);
this.toggleGroup = this.toggleGroup.bind(this);
this.showHiraganaRows = this.showHiraganaRows.bind(this);
}
showHiraganaRows() {
return (this.state.hiraganaItems.map(function(groups) {
return Object.keys(groups).map(function(group) {
return groups[group].map(function(item) {
return <CharacterRow characters={groups[group]} selected={item.selected} />
});
});
}))
}
toggleGroup(e) {
console.log('event: '+e);
}
startGame() {
this.props.handleStartGame('foo');
}
render() {
return (
<div className="choose-characters">
<div className="row">
<div className="col-xs-12">
<div className="panel panel-default">
<div className="panel-body welcome">
<h4>Welcome to Kana Quiz{this.props.nickName !== '' && typeof this.props.nickName !== 'undefined'?', '+this.props.nickName:''}!</h4>
<p>Please choose the groups of characters that you'd like to be studying.</p>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-sm-6">
<div className="panel panel-default">
<div className="panel-heading">Hiragana (ひらがな)</div>
<div className="panel-body selection-areas">
{this.showHiraganaRows()}
</div>
<div className="panel-footer text-center"><a href="javascript:;">All</a> &middot; <a href="javascript:;">None</a></div>
</div>
</div>
<div className="col-sm-6">
<div className="panel panel-default">
<div className="panel-heading">Katakana (カタカナ)</div>
</div>
</div>
<div className="col-xs-12 text-center"><button className="btn btn-danger startgame-button" onClick={this.startGame}>Start the Quiz!</button></div>
</div>
</div>
)
}
}
export default ChooseCharacters;

View file

@ -0,0 +1,38 @@
.welcome {
p:last-child {
margin-bottom: 0;
}
h4 {
margin-top: 0;
}
}
.choose-characters
{
.panel-heading {
font-weight: bold;
}
.choose-row {
font-size: 1.1em;
border-bottom: 1px #eee solid;
padding: 5px;
}
.choose-row:hover {
background-color: #f4f4f4;
cursor: pointer;
}
.choose-row:last-child {
border-bottom: 0px;
}
.glyphicon {
font-size: 0.9em;
}
.glyphicon-check {
color: green;
}
.glyphicon-unchecked {
color: #ccc;
}
.selection-areas {
padding: 7px;
}
}

View file

@ -0,0 +1,25 @@
import React, { Component } from 'react';
import ChooseCharacters from '../ChooseCharacters/ChooseCharacters';
class GameContainer extends Component {
constructor(props) {
super(props);
this.startGame = this.startGame.bind(this);
}
startGame(options) {
this.props.handleStartGame();
}
render() {
let currentScreen = this.props.gameState==='chooseCharacters' ? <ChooseCharacters handleStartGame={this.startGame} nickName={this.props.nickName} /> :
(this.props.gameState==='game' ? '<Game />' : '');
return (
<div>
{currentScreen}
</div>
)
}
}
export default GameContainer;

View file

@ -3,15 +3,24 @@ import './Navbar.scss';
class Navbar extends Component { class Navbar extends Component {
render() { render() {
let leftLink;
switch(this.props.gameState) {
case 'chooseCharacters':
default:
leftLink = <li id="nav-kanaquiz"><a href="javascript:;">Kana Quiz <span>2</span></a></li>
break;
case 'game':
leftLink = <li id="nav-choosecharacters"><a href="#" onClick={this.props.handleEndGame}><span className="glyphicon glyphicon-small glyphicon-arrow-left"></span> Back to menu</a></li>
}
let profileButton = this.props.isAuthenticated ? let profileButton = this.props.isAuthenticated ?
<a href="#" onClick={this.props.handleLogout}><span className="glyphicon glyphicon-small glyphicon-user"></span> {this.props.nickName}</a> : <a href="#" onClick={this.props.handleLogout}><span className="glyphicon glyphicon-small glyphicon-log-out"></span> Log out</a> :
<a href="#" onClick={this.props.handleLogin}><span className="glyphicon glyphicon-small glyphicon-user"></span> Log in</a>; <a href="#" onClick={this.props.handleLogin}><span className="glyphicon glyphicon-small glyphicon-log-in"></span> Log in</a>;
return ( return (
<nav className="navbar navbar-inverse navbar-fixed-top" role="navigation"> <nav className="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div className="container"> <div className="container">
<div id="navbar"> <div id="navbar">
<ul className="nav navbar-nav"> <ul className="nav navbar-nav">
<li id="nav-kanaquiz"><a href="javascript:;">Kana Quiz 2</a></li> {leftLink}
</ul> </ul>
<ul className="nav navbar-nav navbar-right"> <ul className="nav navbar-nav navbar-right">
<li id="nav-settings"><a href="#"><span className="glyphicon glyphicon-small glyphicon-cog"></span> Settings</a></li> <li id="nav-settings"><a href="#"><span className="glyphicon glyphicon-small glyphicon-cog"></span> Settings</a></li>

View file

@ -1,15 +1,30 @@
#nav-profile {
text-transform:capitalize;
}
#navbar ul li { #navbar ul li {
font-size: 1.2em; font-size: 1.2em;
@media (max-width: 768px) {
font-size: 1.0em;
}
.glyphicon { .glyphicon {
font-size: 0.9em; font-size: 0.9em;
color: #62bbff; color: #d9534f;
} }
} }
.navbar-inverse { .navbar-inverse {
background-color: #333; background-color: #444;
}
.nav a {
color: #fff !important;
}
.nav a:hover {
color: #bbb !important;
}
#nav-kanaquiz a, #nav-kanaquiz {
color: #fff !important;
span {
color: #fff !important;
}
}
#nav-kanaquiz a:hover {
cursor: default;
} }
// From http://getbootstrap.com/examples/non-responsive/non-responsive.css // From http://getbootstrap.com/examples/non-responsive/non-responsive.css
.container .navbar-header, .container .navbar-header,