Compare commits
	
		
			2 Commits
		
	
	
		
			9439186b8a
			...
			6dea7ae63f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6dea7ae63f | |||
| d8d3406fe1 | 
							
								
								
									
										13
									
								
								webapp/src/components/Counter.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								webapp/src/components/Counter.css
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					.Counter {
 | 
				
			||||||
 | 
					    display: inline-block;
 | 
				
			||||||
 | 
					    line-height: 0px;
 | 
				
			||||||
 | 
					    border-radius: 50%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Counter span {
 | 
				
			||||||
 | 
					    display: inline-block;
 | 
				
			||||||
 | 
					    padding-top: 50%;
 | 
				
			||||||
 | 
					    padding-bottom: 50%;
 | 
				
			||||||
 | 
					    margin-left: 2px;
 | 
				
			||||||
 | 
					    margin-right: 2px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								webapp/src/components/Counter.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								webapp/src/components/Counter.jsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import './Counter.css';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function Counter({ number }) {
 | 
				
			||||||
 | 
					    if (number !== 0)
 | 
				
			||||||
 | 
					        return <span className="Counter"><span>{number}</span></span>
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -59,7 +59,12 @@
 | 
				
			|||||||
    box-shadow: 0 1.5px 0 0 currentColor;
 | 
					    box-shadow: 0 1.5px 0 0 currentColor;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ViewSelector .Counter {
 | 
				
			||||||
 | 
					    background-color:palevioletred;
 | 
				
			||||||
 | 
					    margin-right: 1px;
 | 
				
			||||||
 | 
					    font-size: 60%;
 | 
				
			||||||
 | 
					    vertical-align: 7px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.ViewProvider {
 | 
					.ViewProvider {
 | 
				
			||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
 | 
				
			|||||||
@ -17,6 +17,7 @@ import Forward from './games/action/Forward';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import GameBoard from './games/GameBoard';
 | 
					import GameBoard from './games/GameBoard';
 | 
				
			||||||
import Message2Opponent from './games/Message2Opponent';
 | 
					import Message2Opponent from './games/Message2Opponent';
 | 
				
			||||||
 | 
					import Counter from '../components/Counter';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import './Games.css';
 | 
					import './Games.css';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,7 +28,7 @@ export default function Games({ context: { gamesReducer, gamesApi }, players })
 | 
				
			|||||||
    <GamesContext.Provider value={games} >
 | 
					    <GamesContext.Provider value={games} >
 | 
				
			||||||
      <div className='Games'>
 | 
					      <div className='Games'>
 | 
				
			||||||
        <div className='left-side'>
 | 
					        <div className='left-side'>
 | 
				
			||||||
          <ViewSelector />
 | 
					          <ViewSelector games={games} />
 | 
				
			||||||
          <ViewProvider gamesReducer={gamesReducer} players={players} />
 | 
					          <ViewProvider gamesReducer={gamesReducer} players={players} />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div className='right-side'>
 | 
					        <div className='right-side'>
 | 
				
			||||||
@ -43,21 +44,21 @@ export default function Games({ context: { gamesReducer, gamesApi }, players })
 | 
				
			|||||||
  )
 | 
					  )
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function ViewSelector() {
 | 
					function ViewSelector({ games }) {
 | 
				
			||||||
  // TODO: counter Wating for YOU
 | 
					  const awaiting = countGames(games.gamesList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <nav className='ViewSelector' >
 | 
					    <nav className='ViewSelector' >
 | 
				
			||||||
      <NavLink to='new'>New</NavLink>
 | 
					      <NavLink to='new'>New</NavLink>
 | 
				
			||||||
      <NavLink to='proposal'>Proposal</NavLink>
 | 
					      <NavLink to='proposal'>Proposal<Counter number={awaiting.proposals} /></NavLink>
 | 
				
			||||||
      <NavLink to='active'>Active</NavLink>
 | 
					      <NavLink to='active'  >Active<Counter number={awaiting.active} /></NavLink>
 | 
				
			||||||
      <NavLink to='archive' >Archive</NavLink>
 | 
					      <NavLink to='archive' >Archive</NavLink>
 | 
				
			||||||
    </nav>
 | 
					    </nav>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function ViewProvider({ gamesReducer, players }) {
 | 
					function ViewProvider({ gamesReducer, players }) {
 | 
				
			||||||
  const [/*games*/, dispatchGames] = gamesReducer;
 | 
					  const [games, dispatchGames] = gamesReducer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <div className='ViewProvider'>
 | 
					    <div className='ViewProvider'>
 | 
				
			||||||
@ -65,9 +66,7 @@ function ViewProvider({ gamesReducer, players }) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <Route path='new' element={
 | 
					        <Route path='new' element={
 | 
				
			||||||
          <NewGame
 | 
					          <NewGame
 | 
				
			||||||
            onSelectPlayer={(whitePlayer, blackPlayer) => {
 | 
					            onSelectPlayer={(whitePlayer, blackPlayer) => dispatchGames({ type: 'nextNewGame', whitePlayer, blackPlayer })}
 | 
				
			||||||
              dispatchGames({ type: 'nextNewGame', whitePlayer, blackPlayer })
 | 
					 | 
				
			||||||
            }}
 | 
					 | 
				
			||||||
            players={players}
 | 
					            players={players}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        } />
 | 
					        } />
 | 
				
			||||||
@ -76,7 +75,8 @@ function ViewProvider({ gamesReducer, players }) {
 | 
				
			|||||||
          <GameSelector
 | 
					          <GameSelector
 | 
				
			||||||
            yours='GAME_PROPOSAL_WAIT_FOR_YOU'
 | 
					            yours='GAME_PROPOSAL_WAIT_FOR_YOU'
 | 
				
			||||||
            opponents='GAME_PROPOSAL_WAIT_FOR_OPPONENT'
 | 
					            opponents='GAME_PROPOSAL_WAIT_FOR_OPPONENT'
 | 
				
			||||||
            onClick={(uuid) => console.log("GameProposal", uuid)}
 | 
					            isSelected={(uuid) => uuid === games.proposal.selectedUUID}
 | 
				
			||||||
 | 
					            onSelect={(selectedUUID) => dispatchGames({ type: 'nextProposal', selectedUUID })}
 | 
				
			||||||
          />
 | 
					          />
 | 
				
			||||||
        } />
 | 
					        } />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -103,3 +103,30 @@ function ActionPanel({ players, gamesApi }) {
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  )
 | 
					  )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function countGames(gamesList) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var awaiting = {
 | 
				
			||||||
 | 
					    proposals: 0,
 | 
				
			||||||
 | 
					    active: 0
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!gamesList)
 | 
				
			||||||
 | 
					    return awaiting;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (const game of gamesList) {
 | 
				
			||||||
 | 
					    switch (game.status) {
 | 
				
			||||||
 | 
					      case 'GAME_PROPOSAL_WAIT_FOR_YOU':
 | 
				
			||||||
 | 
					        awaiting.proposals++;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case 'GAME_BOARD_WAIT_FOR_YOU':
 | 
				
			||||||
 | 
					      case 'DRAW_REQUEST_WAIT_FOR_YO':
 | 
				
			||||||
 | 
					        awaiting.active++;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return awaiting;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,13 @@ hr {
 | 
				
			|||||||
    margin-top: 3px;
 | 
					    margin-top: 3px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Selectable .Title {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: row;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    justify-content: center;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.Selectable q {
 | 
					.Selectable q {
 | 
				
			||||||
    color: gray;
 | 
					    color: gray;
 | 
				
			||||||
    font-size: 70%;
 | 
					    font-size: 70%;
 | 
				
			||||||
@ -33,9 +40,14 @@ hr {
 | 
				
			|||||||
.Selectable:hover {
 | 
					.Selectable:hover {
 | 
				
			||||||
    background-color: #d3d3d360;
 | 
					    background-color: #d3d3d360;
 | 
				
			||||||
    border-radius: 2px;
 | 
					    border-radius: 2px;
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Selectable.selected {
 | 
				
			||||||
 | 
					    background-color: #d3d3d3f0;
 | 
				
			||||||
 | 
					    border-radius: 2px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.Separator {
 | 
					.Separator {
 | 
				
			||||||
    /* width: 20%;  */
 | 
					    /* width: 20%;  */
 | 
				
			||||||
    /* height: 20px;  */
 | 
					    /* height: 20px;  */
 | 
				
			||||||
@ -46,9 +58,6 @@ hr {
 | 
				
			|||||||
    margin-bottom: 7px;
 | 
					    margin-bottom: 7px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.Selectable .Title {
 | 
					.Separator .Counter {
 | 
				
			||||||
    display: flex;
 | 
					    background-color: darkgray;
 | 
				
			||||||
    flex-direction: row;
 | 
					 | 
				
			||||||
    align-items: center;
 | 
					 | 
				
			||||||
    justify-content: center;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -4,21 +4,30 @@ import { GamesContext } from '../../../context/games';
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import { Color, Player } from '../../../components/Checkers';
 | 
					import { Color, Player } from '../../../components/Checkers';
 | 
				
			||||||
import Loading from '../../../components/Loading';
 | 
					import Loading from '../../../components/Loading';
 | 
				
			||||||
 | 
					import Counter from '../../../components/Counter';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function GameSelector({ yours, opponents, onClick }) {
 | 
					export default function GameSelector({ yours, opponents, isSelected, onSelect }) {
 | 
				
			||||||
 | 
					    const games = useContext(GamesContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const gamesList = useContext(GamesContext).gamesList;
 | 
					    const gamesList = useContext(GamesContext).gamesList;
 | 
				
			||||||
    if (gamesList === null)
 | 
					    if (gamesList === null)
 | 
				
			||||||
        return <Loading />
 | 
					        return <Loading />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onClick = (uuid) => {
 | 
				
			||||||
 | 
					        if (isSelected(uuid))
 | 
				
			||||||
 | 
					            onSelect(null); // deselect previously selected game
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            onSelect(uuid);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const yoursList = gamesList.filter(game => game.status === yours)
 | 
					    const yoursList = gamesList.filter(game => game.status === yours)
 | 
				
			||||||
        .map(game => <Selectable game={game} key={game.uuid} onClick={onClick} />)
 | 
					        .map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const opponentsList = gamesList.filter(game => game.status === opponents)
 | 
					    const opponentsList = gamesList.filter(game => game.status === opponents)
 | 
				
			||||||
        .map(game => <Selectable game={game} key={game.uuid} onClick={onClick} />)
 | 
					        .map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <div className="GameSelector">
 | 
					        <div className='GameSelector'>
 | 
				
			||||||
            {yoursList}
 | 
					            {yoursList}
 | 
				
			||||||
            {opponentsList.length > 0 && <Separator counter={opponentsList.length} />}
 | 
					            {opponentsList.length > 0 && <Separator counter={opponentsList.length} />}
 | 
				
			||||||
            {opponentsList}
 | 
					            {opponentsList}
 | 
				
			||||||
@ -26,14 +35,15 @@ export default function GameSelector({ yours, opponents, onClick }) {
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function Selectable({ game, onClick }) {
 | 
					function Selectable({ game, selected, onClick }) {
 | 
				
			||||||
    const myColor = game.myColor;
 | 
					    const myColor = game.myColor;
 | 
				
			||||||
    const opponentColor = Color.opposite(myColor);
 | 
					    const opponentColor = Color.opposite(myColor);
 | 
				
			||||||
    const opponentName = game.opponentName;
 | 
					    const opponentName = game.opponentName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <div >
 | 
					        <div >
 | 
				
			||||||
            <div className='Selectable' onClick={() => onClick(game.uuid)}>
 | 
					            <div className={'Selectable' + (selected ? ' selected' : '')}
 | 
				
			||||||
 | 
					                onClick={() => onClick(game.uuid)}>
 | 
				
			||||||
                <div className='Title'>
 | 
					                <div className='Title'>
 | 
				
			||||||
                    <Player color={myColor} />
 | 
					                    <Player color={myColor} />
 | 
				
			||||||
                    <i>vs</i>
 | 
					                    <i>vs</i>
 | 
				
			||||||
@ -48,8 +58,9 @@ function Selectable({ game, onClick }) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function Separator({ counter }) {
 | 
					function Separator({ counter }) {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <div className="Separator">
 | 
					        <div className='Separator'>
 | 
				
			||||||
            waiting for opponent ({counter})
 | 
					            waiting for opponent
 | 
				
			||||||
 | 
					            <Counter number={counter} />
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -10,6 +10,10 @@ const initialState = {
 | 
				
			|||||||
    message2opponent: '',
 | 
					    message2opponent: '',
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  proposal: {
 | 
				
			||||||
 | 
					    selectedUUID: null,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Network
 | 
					  // Network
 | 
				
			||||||
  isPollingGamesList: false,
 | 
					  isPollingGamesList: false,
 | 
				
			||||||
  isPushingNewGame: false,
 | 
					  isPushingNewGame: false,
 | 
				
			||||||
@ -27,6 +31,12 @@ function reducer(state, action) {
 | 
				
			|||||||
        newGame: nextState(state.newGame, action)
 | 
					        newGame: nextState(state.newGame, action)
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 'nextProposal':
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        ...state,
 | 
				
			||||||
 | 
					        proposal: nextState(state.proposal, action)
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
      throw Error('GamesReducer: unknown action.type', action.type);
 | 
					      throw Error('GamesReducer: unknown action.type', action.type);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user