#24-directory-structure #26
							
								
								
									
										15
									
								
								webapp/src/components/DropdownList.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								webapp/src/components/DropdownList.jsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
 | 
			
		||||
export default function DropdownList({ selected, onSelect, optionsList }) {
 | 
			
		||||
    const handleSelect = (event) => {
 | 
			
		||||
        onSelect(event.target.value)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <form className='SelectPlayer'>
 | 
			
		||||
            <select value={selected} onChange={handleSelect}>
 | 
			
		||||
                {optionsList}
 | 
			
		||||
            </select>
 | 
			
		||||
        </form>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +0,0 @@
 | 
			
		||||
.game-message {
 | 
			
		||||
    border-radius: 3px;
 | 
			
		||||
    border-color: lightgray;
 | 
			
		||||
    background-color:violet;
 | 
			
		||||
    width: 70%;
 | 
			
		||||
}
 | 
			
		||||
@ -1,15 +0,0 @@
 | 
			
		||||
import './GameMessage.css'
 | 
			
		||||
import React from 'react'
 | 
			
		||||
 | 
			
		||||
// import { AppContext } from '../../context/app'
 | 
			
		||||
 | 
			
		||||
export default function GameMessage() {
 | 
			
		||||
 | 
			
		||||
  // const [ctx] = React.useContext(AppContext)
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className='game-message'>
 | 
			
		||||
      TBD: Game Message
 | 
			
		||||
    </div>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
@ -1,42 +0,0 @@
 | 
			
		||||
.Games {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    justify-content: center; 
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Games .li {
 | 
			
		||||
    border: 1px solid black;
 | 
			
		||||
    margin-bottom: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Games .li p {
 | 
			
		||||
    margin: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Games .li p q {
 | 
			
		||||
    color: gray;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Games .li p i {
 | 
			
		||||
    font-size: 70%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Games .li button.action {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Games .li:hover button.action {
 | 
			
		||||
    display: initial;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.separator {
 | 
			
		||||
    /* width: 20%;  */
 | 
			
		||||
    /* height: 20px;  */
 | 
			
		||||
    border-bottom: 1px dotted black; 
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    font-size: 50%;
 | 
			
		||||
    padding-left: 50%;
 | 
			
		||||
    margin-bottom: 7px;
 | 
			
		||||
}
 | 
			
		||||
@ -1,44 +0,0 @@
 | 
			
		||||
import './GameSelector.css';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { useLocation, matchPath } from "react-router";
 | 
			
		||||
 | 
			
		||||
import { AppData } from "../../context/data"
 | 
			
		||||
import { AppContext } from "../../context/app"
 | 
			
		||||
import Proposal from './GameSelector/GameProposal';
 | 
			
		||||
 | 
			
		||||
export default function GameSelector() {
 | 
			
		||||
  const [data] = React.useContext(AppData)
 | 
			
		||||
  const [/*ctx*/, dispatchCtx] = React.useContext(AppContext)
 | 
			
		||||
 | 
			
		||||
  const { pathname } = useLocation();
 | 
			
		||||
  const isProposalPath = matchPath("/game/proposal/*", pathname);
 | 
			
		||||
  const isActivelPath  = matchPath("/game/active/*", pathname);
 | 
			
		||||
  const isArchivePath  = matchPath("/game/archive/*", pathname);
 | 
			
		||||
 | 
			
		||||
  // console.log("GameSelector appCtx", ctx)
 | 
			
		||||
 | 
			
		||||
  const onClick_proposal = (selectedGame) => {
 | 
			
		||||
    dispatchCtx({ component: "game-selector", selectedGameProposal: selectedGame })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // const onClick_active = (selectedGame) => {
 | 
			
		||||
  //   dispatchCtx({ component: "game-selector", selectedActiveGame: selectedGame })
 | 
			
		||||
  // }
 | 
			
		||||
  
 | 
			
		||||
  // const onClick_archive = (selectedGame) => {
 | 
			
		||||
  //   dispatchCtx({ component: "game-selector", selectedArchiveGame: selectedGame })
 | 
			
		||||
  // }
 | 
			
		||||
 | 
			
		||||
  if (!data.games)
 | 
			
		||||
    return <div>Loading..</div>
 | 
			
		||||
 | 
			
		||||
  console.log("Games", data.games)
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className='game-selector'>
 | 
			
		||||
      {isProposalPath && <Proposal games={data.games} onClick={onClick_proposal} />}
 | 
			
		||||
      {isActivelPath && <div>TBD #1</div>}
 | 
			
		||||
      {isArchivePath && <div>TBD #2</div>}
 | 
			
		||||
    </div>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
@ -1,32 +0,0 @@
 | 
			
		||||
import './ProposalSelector.css'
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import Selectable from './Selectable';
 | 
			
		||||
 | 
			
		||||
export default function ProposalSelector({ games }) {
 | 
			
		||||
 | 
			
		||||
  const waitForYou = games
 | 
			
		||||
    .filter(game => game.status === Status.WaitForYou)
 | 
			
		||||
    .map(game => <Selectable game={game} />)
 | 
			
		||||
 | 
			
		||||
  const WaitForOpponent = games
 | 
			
		||||
    .filter(game => game.status === Status.WaitForOpponent)
 | 
			
		||||
    .map(game => <Selectable game={game} />)
 | 
			
		||||
 | 
			
		||||
  return <div className="Container">
 | 
			
		||||
    <div className="Games">
 | 
			
		||||
      {waitForYou}
 | 
			
		||||
      {WaitForOpponent.length > 0 &&
 | 
			
		||||
        <div className="separator">
 | 
			
		||||
          waiting for opponent ({WaitForOpponent.length})
 | 
			
		||||
        </div>
 | 
			
		||||
      }
 | 
			
		||||
      {WaitForOpponent}
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const Status = {
 | 
			
		||||
  WaitForOpponent: "GAME_PROPOSAL_WAIT_FOR_OPPONENT",
 | 
			
		||||
  WaitForYou: "GAME_PROPOSAL_WAIT_FOR_YOU",
 | 
			
		||||
}
 | 
			
		||||
@ -1,32 +0,0 @@
 | 
			
		||||
import './ProposalSelector.css'
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import Selectable from './Selectable';
 | 
			
		||||
 | 
			
		||||
export default function ProposalSelector({ games }) {
 | 
			
		||||
 | 
			
		||||
  const waitForYou = games
 | 
			
		||||
    .filter(game => game.status === Status.WaitForYou)
 | 
			
		||||
    .map(game => <Selectable game={game} />)
 | 
			
		||||
 | 
			
		||||
  const WaitForOpponent = games
 | 
			
		||||
    .filter(game => game.status === Status.WaitForOpponent)
 | 
			
		||||
    .map(game => <Selectable game={game} />)
 | 
			
		||||
 | 
			
		||||
  return <div className="Container">
 | 
			
		||||
    <div className="Games">
 | 
			
		||||
      {waitForYou}
 | 
			
		||||
      {WaitForOpponent.length > 0 &&
 | 
			
		||||
        <div className="separator">
 | 
			
		||||
          waiting for opponent ({WaitForOpponent.length})
 | 
			
		||||
        </div>
 | 
			
		||||
      }
 | 
			
		||||
      {WaitForOpponent}
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const Status = {
 | 
			
		||||
  WaitForOpponent: "GAME_PROPOSAL_WAIT_FOR_OPPONENT",
 | 
			
		||||
  WaitForYou: "GAME_PROPOSAL_WAIT_FOR_YOU",
 | 
			
		||||
}
 | 
			
		||||
@ -1,30 +0,0 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import Selectable from './Selectable';
 | 
			
		||||
 | 
			
		||||
export default function ProposalSelector({ games, onClick }) {
 | 
			
		||||
 | 
			
		||||
  const waitForYou = games
 | 
			
		||||
    .filter(game => game.status === Status.WaitForYou)
 | 
			
		||||
    .map(game => <Selectable game={game} key={game.uuid} onClick={onClick} />)
 | 
			
		||||
 | 
			
		||||
  const WaitForOpponent = games
 | 
			
		||||
    .filter(game => game.status === Status.WaitForOpponent)
 | 
			
		||||
    .map(game => <Selectable game={game} key={game.uuid} onClick={onClick} />)
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="Games">
 | 
			
		||||
      {waitForYou}
 | 
			
		||||
      {WaitForOpponent.length > 0 &&
 | 
			
		||||
        <div className="separator">
 | 
			
		||||
          waiting for opponent ({WaitForOpponent.length})
 | 
			
		||||
        </div>
 | 
			
		||||
      }
 | 
			
		||||
      {WaitForOpponent}
 | 
			
		||||
    </div>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Status = {
 | 
			
		||||
  WaitForOpponent: "GAME_PROPOSAL_WAIT_FOR_OPPONENT",
 | 
			
		||||
  WaitForYou: "GAME_PROPOSAL_WAIT_FOR_YOU",
 | 
			
		||||
}
 | 
			
		||||
@ -1,43 +0,0 @@
 | 
			
		||||
.selectable {
 | 
			
		||||
    border: 1px solid black;
 | 
			
		||||
    margin-bottom: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.selectable q {
 | 
			
		||||
    color: gray;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.selectable i {
 | 
			
		||||
    font-size: 70%;
 | 
			
		||||
    margin-left: 5px;
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.selectable:hover {
 | 
			
		||||
    background-color: #d3d3d360;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* .Games .li button.action {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.Games .li:hover button.action {
 | 
			
		||||
    display: initial;
 | 
			
		||||
} */
 | 
			
		||||
 | 
			
		||||
.separator {
 | 
			
		||||
    /* width: 20%;  */
 | 
			
		||||
    /* height: 20px;  */
 | 
			
		||||
    border-bottom: 1px dotted black; 
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    font-size: 50%;
 | 
			
		||||
    padding-left: 50%;
 | 
			
		||||
    margin-bottom: 7px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.selectable .title {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
}
 | 
			
		||||
@ -1,24 +0,0 @@
 | 
			
		||||
import './Selectable.css'
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { oppositeColor } from '../Stone';
 | 
			
		||||
import { Player } from '../../Player';
 | 
			
		||||
 | 
			
		||||
export default function Selectable({ game, onClick }) {
 | 
			
		||||
 | 
			
		||||
  const myColor = game.myColor
 | 
			
		||||
 | 
			
		||||
  const opponentColor = oppositeColor(myColor)
 | 
			
		||||
  const opponentName = game.opponentName
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className='selectable'>
 | 
			
		||||
      <div className='title' onClick={() => onClick(game)}>
 | 
			
		||||
        <Player color={myColor} />
 | 
			
		||||
        <i>vs</i>
 | 
			
		||||
        <Player color={opponentColor} name={opponentName} />
 | 
			
		||||
      </div>
 | 
			
		||||
      <q>{game.message}</q>
 | 
			
		||||
    </div>
 | 
			
		||||
  )
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -1,30 +0,0 @@
 | 
			
		||||
.game-view {
 | 
			
		||||
    margin-bottom: 10px;
 | 
			
		||||
    background-color: lightgrey;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    padding-top: 8px;
 | 
			
		||||
    padding-bottom: 8px;
 | 
			
		||||
    color: black;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.game-view a {
 | 
			
		||||
    color:darkgrey;
 | 
			
		||||
    text-decoration: none;
 | 
			
		||||
    transition: .25s ease;
 | 
			
		||||
    margin-left: 5px;
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.game-view .active {
 | 
			
		||||
    color: white;
 | 
			
		||||
    border-radius: 2px;
 | 
			
		||||
    background-color: cadetblue;
 | 
			
		||||
    opacity: 80%;
 | 
			
		||||
    padding-top: 8px;
 | 
			
		||||
    padding-bottom: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.game-view a:hover:not(.active) {
 | 
			
		||||
    color: cadetblue; 
 | 
			
		||||
    box-shadow: 0 1.5px 0 0 currentColor;
 | 
			
		||||
}
 | 
			
		||||
@ -1,15 +0,0 @@
 | 
			
		||||
import './GameView.css';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { NavLink } from "react-router-dom";
 | 
			
		||||
 | 
			
		||||
export default function GameView() {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <nav className='game-view'>
 | 
			
		||||
      <NavLink to="/game/new">New</NavLink>
 | 
			
		||||
      <NavLink to="/game/proposal">Proposal</NavLink>
 | 
			
		||||
      <NavLink to="/game/active">Active</NavLink>
 | 
			
		||||
      <NavLink to="/game/archive">Archive</NavLink>
 | 
			
		||||
    </nav>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
@ -1,17 +0,0 @@
 | 
			
		||||
.new-game {
 | 
			
		||||
    margin-top: 60px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.new-game * {
 | 
			
		||||
    width: 230px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.new-game>div { /* first level childs only*/
 | 
			
		||||
    margin-top: 25px;
 | 
			
		||||
    margin-bottom: 25px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.new-game .stone {
 | 
			
		||||
    font-size: 150%;
 | 
			
		||||
    vertical-align: -3px;
 | 
			
		||||
}
 | 
			
		||||
@ -1,72 +0,0 @@
 | 
			
		||||
import './NewGame.css';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { AppData } from '../../context/data'
 | 
			
		||||
import { AppContext } from '../../context/app'
 | 
			
		||||
import { useLocation, matchPath } from "react-router";
 | 
			
		||||
import { SelectPlayer } from '../Player';
 | 
			
		||||
import { WhiteStone, BlackStone } from './Stone';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default function NewGame() {
 | 
			
		||||
  const [ctx, dispatchCtx] = React.useContext(AppContext)
 | 
			
		||||
  const [data] = React.useContext(AppData)
 | 
			
		||||
  const { pathname } = useLocation();
 | 
			
		||||
  const isMyPath = matchPath("/game/new", pathname);
 | 
			
		||||
 | 
			
		||||
  if (!isMyPath)
 | 
			
		||||
    return
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Name options
 | 
			
		||||
   */
 | 
			
		||||
  const nameOptions = data.leaderboard ? Object.keys(data.leaderboard).map(playerName =>
 | 
			
		||||
      <option key={playerName} value={playerName}>
 | 
			
		||||
        {data.isCurrentUser(playerName) ? 'You' : playerName}
 | 
			
		||||
      </option>)
 | 
			
		||||
    : [<option key='loading' value='…'>…loading</option>]
 | 
			
		||||
 | 
			
		||||
  const whiteOptions = Array(nameOptions)
 | 
			
		||||
  whiteOptions.push(<option key='default' value=''>{'white player …'}</option>)
 | 
			
		||||
 | 
			
		||||
  const blackOptions = Array(nameOptions)
 | 
			
		||||
  blackOptions.push(<option key='default' value=''>{'black player …'}</option>)
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Radiobutton
 | 
			
		||||
   */
 | 
			
		||||
  const radioButton = (whitePlayer, blackPlayer) => {
 | 
			
		||||
    if (whitePlayer !== '' && whitePlayer === ctx.newGame.blackPlayer) {
 | 
			
		||||
      blackPlayer = ''
 | 
			
		||||
    }
 | 
			
		||||
    if (blackPlayer !== '' && blackPlayer === ctx.newGame.whitePlayer) {
 | 
			
		||||
      whitePlayer = ''
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dispatchCtx({ update: "newGame", whitePlayer, blackPlayer })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const setWhitePlayer = (name) => {
 | 
			
		||||
    radioButton(name, ctx.newGame.blackPlayer)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const setBlackPlayer = (name) => {
 | 
			
		||||
    radioButton(ctx.newGame.whitePlayer, name)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /*
 | 
			
		||||
   * Component
 | 
			
		||||
   */
 | 
			
		||||
  return (
 | 
			
		||||
    <div className='new-game'>
 | 
			
		||||
      <div>
 | 
			
		||||
        <WhiteStone />
 | 
			
		||||
        <SelectPlayer name={ctx.newGame.whitePlayer} setName={setWhitePlayer} nameOptions={whiteOptions} />
 | 
			
		||||
      </div>
 | 
			
		||||
      <div>- vs -</div>
 | 
			
		||||
      <div>
 | 
			
		||||
        <SelectPlayer name={ctx.newGame.blackPlayer} setName={setBlackPlayer} nameOptions={blackOptions} />
 | 
			
		||||
        <BlackStone />
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
@ -17,29 +17,25 @@ import Forward from './games/action/Forward';
 | 
			
		||||
 | 
			
		||||
import GameBoard from './games/GameBoard';
 | 
			
		||||
 | 
			
		||||
import { GamesContext, GamesDispatchContext, GamesApiContext } from '../context/games';
 | 
			
		||||
import { GamesContext } from '../context/games';
 | 
			
		||||
 | 
			
		||||
export default function Games({ context }) {
 | 
			
		||||
export default function Games({ context, players }) {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <GamesContext.Provider value={context.games} >
 | 
			
		||||
      <GamesDispatchContext.Provider value={context.dispatchGames} >
 | 
			
		||||
        <GamesApiContext.Provider value={context.gamesApi} >
 | 
			
		||||
          <div className='Games'>
 | 
			
		||||
            <div className='left-side'>
 | 
			
		||||
              <ViewSelector />
 | 
			
		||||
              <ViewProvider />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div className='right-side'>
 | 
			
		||||
              <ActionPanel />
 | 
			
		||||
              <GameBoard />
 | 
			
		||||
              {/*
 | 
			
		||||
      <div className='Games'>
 | 
			
		||||
        <div className='left-side'>
 | 
			
		||||
          <ViewSelector />
 | 
			
		||||
          <ViewProvider players={players} dispatchGames={context.dispatchGames} />
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className='right-side'>
 | 
			
		||||
          <ActionPanel />
 | 
			
		||||
          <GameBoard />
 | 
			
		||||
          {/*
 | 
			
		||||
          <GameMessage />
 | 
			
		||||
          <Message2Opponent /> */}
 | 
			
		||||
            </div>
 | 
			
		||||
          </div >
 | 
			
		||||
        </GamesApiContext.Provider>
 | 
			
		||||
      </GamesDispatchContext.Provider>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div >
 | 
			
		||||
    </GamesContext.Provider>
 | 
			
		||||
  )
 | 
			
		||||
};
 | 
			
		||||
@ -57,11 +53,17 @@ function ViewSelector() {
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ViewProvider(/*todo: dispatchGame*/) {
 | 
			
		||||
function ViewProvider({ players, dispatchGames }) {
 | 
			
		||||
  return (
 | 
			
		||||
    <div className='ViewProvider'>
 | 
			
		||||
      <Routes>
 | 
			
		||||
        <Route path='new' element={<NewGame />} />
 | 
			
		||||
 | 
			
		||||
        <Route path='new' element={
 | 
			
		||||
          <NewGame
 | 
			
		||||
            players={players}
 | 
			
		||||
            onSelectPlayer={(whitePlayer, blackPlayer) => dispatchGames({ type: "next", newGame: { whitePlayer, blackPlayer } })}
 | 
			
		||||
          />
 | 
			
		||||
        } />
 | 
			
		||||
 | 
			
		||||
        <Route path='proposal' element={
 | 
			
		||||
          <GameSelector
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,13 @@
 | 
			
		||||
.SelectPlayer {
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
    border: 0.5px solid darkgrey;
 | 
			
		||||
.NewGame * {
 | 
			
		||||
    /* all childs */
 | 
			
		||||
    width: 200px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-flow: column;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.SelectPlayer select:hover {
 | 
			
		||||
    background: lightgray;
 | 
			
		||||
.NewGame>i {
 | 
			
		||||
    /* first level childs only*/
 | 
			
		||||
    margin-top: 25px;
 | 
			
		||||
    margin-bottom: 25px;
 | 
			
		||||
}
 | 
			
		||||
@ -1,30 +1,62 @@
 | 
			
		||||
import './NewGame.css'
 | 
			
		||||
import React, { useContext } from 'react';
 | 
			
		||||
import { GamesContext } from '../../../context/games';
 | 
			
		||||
 | 
			
		||||
export default function NewGame() {
 | 
			
		||||
import DropdownList from '../../../components/DropdownList';
 | 
			
		||||
import { WhiteStone, BlackStone } from '../../../components/Checkers';
 | 
			
		||||
 | 
			
		||||
export default function NewGame({ players, onSelectPlayer }) {
 | 
			
		||||
    const games = useContext(GamesContext);
 | 
			
		||||
 | 
			
		||||
    console.log("NewGame", games);
 | 
			
		||||
    /*
 | 
			
		||||
     * Name options
 | 
			
		||||
     */
 | 
			
		||||
    const nameOptions = !players.leaderboard
 | 
			
		||||
        ? [<option key='loading' value='…'>…loading</option>]
 | 
			
		||||
        : Object.keys(players.leaderboard).map(playerName =>
 | 
			
		||||
            <option key={playerName} value={playerName}>
 | 
			
		||||
                {players.isCurrentUser(playerName) ? 'You' : playerName}
 | 
			
		||||
            </option>)
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <div>View: NewGame</div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
    const whiteOptions = Array(nameOptions)
 | 
			
		||||
    whiteOptions.push(<option key='default' value=''>{'white player …'}</option>)
 | 
			
		||||
 | 
			
		||||
    const blackOptions = Array(nameOptions)
 | 
			
		||||
    blackOptions.push(<option key='default' value=''>{'black player …'}</option>)
 | 
			
		||||
 | 
			
		||||
// Move to components as DropSelector
 | 
			
		||||
function SelectPlayer({ name, setName, nameOptions }) {
 | 
			
		||||
    const handleSelectChange = (event) => {
 | 
			
		||||
        setName(event.target.value)
 | 
			
		||||
    /*
 | 
			
		||||
     * Radiobutton
 | 
			
		||||
     */
 | 
			
		||||
    const radioButton = (whitePlayer, blackPlayer) => {
 | 
			
		||||
        if (whitePlayer !== '' && whitePlayer === games.newGame.blackPlayer) {
 | 
			
		||||
            blackPlayer = '';
 | 
			
		||||
        }
 | 
			
		||||
        if (blackPlayer !== '' && blackPlayer === games.newGame.whitePlayer) {
 | 
			
		||||
            whitePlayer = '';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        console.log("WhitePlayer", whitePlayer, "BlackPlayer", blackPlayer);
 | 
			
		||||
        onSelectPlayer(whitePlayer, blackPlayer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const setWhitePlayer = (name) => {
 | 
			
		||||
        radioButton(name, games.newGame.blackPlayer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const setBlackPlayer = (name) => {
 | 
			
		||||
        radioButton(games.newGame.whitePlayer, name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * The Component
 | 
			
		||||
     */
 | 
			
		||||
    return (
 | 
			
		||||
        <div className='SelectPlayer'>
 | 
			
		||||
            <form>
 | 
			
		||||
                <select value={name} onChange={handleSelectChange}>
 | 
			
		||||
                    {nameOptions}
 | 
			
		||||
                </select>
 | 
			
		||||
            </form>
 | 
			
		||||
        <div className='NewGame'>
 | 
			
		||||
            <WhiteStone />
 | 
			
		||||
            <DropdownList selected={games.newGame.whitePlayer} onSelect={setWhitePlayer} optionsList={whiteOptions} />
 | 
			
		||||
            <i>- vs -</i>
 | 
			
		||||
            <DropdownList selected={games.newGame.blackPlayer} onSelect={setBlackPlayer} optionsList={blackOptions} />
 | 
			
		||||
            <BlackStone />
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
@ -1,8 +1,6 @@
 | 
			
		||||
import { createContext } from 'react';
 | 
			
		||||
 | 
			
		||||
export const GamesContext = createContext(null);
 | 
			
		||||
export const GamesDispatchContext = createContext(null);
 | 
			
		||||
export const GamesApiContext = createContext(null);
 | 
			
		||||
 | 
			
		||||
// export const Games = React.createContext({
 | 
			
		||||
//   state: initialState,
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,11 @@ import { nextState } from '../util/StateHelper';
 | 
			
		||||
 | 
			
		||||
export const gamesInitialState = {
 | 
			
		||||
  list: null,
 | 
			
		||||
 | 
			
		||||
  newGame: {
 | 
			
		||||
    whitePlayer: '',
 | 
			
		||||
    blackPlayer: ''
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function gamesReducer(state, action) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user