GameSlector split into thre sub components

This commit is contained in:
djmil 2023-11-15 18:10:44 +01:00
parent 3063146a76
commit 6343f70851
3 changed files with 117 additions and 21 deletions

View File

@ -3,7 +3,7 @@ import { GamesContext } from '../context/games';
import { NavLink, Routes, Route } from 'react-router-dom';
import NewGame from './games/view/NewGame';
import GameSelector from './games/view/GameSelector';
import { GameProposalSelector, ActiveGameSelector, GameArchiveSelector } from './games/view/GameSelector';
import Create from './games/action/Create';
import Reject from './games/action/Reject';
@ -58,30 +58,29 @@ function ViewSelector({ games }) {
}
function ViewProvider({ gamesReducer, players }) {
const [games, dispatchGames] = gamesReducer;
const [/*games*/, dispatchGames] = gamesReducer;
return (
<div className='ViewProvider'>
<Routes>
<Route path='new' element={
<NewGame
onSelectPlayer={(whitePlayer, blackPlayer) => dispatchGames({ type: 'nextNewGame', whitePlayer, blackPlayer })}
<NewGame onSelectPlayer={(whitePlayer, blackPlayer) => dispatchGames({ type: 'nextNewGame', whitePlayer, blackPlayer })}
players={players}
/>
} />
<Route path='proposal' element={
<GameSelector
yours='GAME_PROPOSAL_WAIT_FOR_YOU'
opponents='GAME_PROPOSAL_WAIT_FOR_OPPONENT'
isSelected={(uuid) => uuid === games.proposal.selectedUUID}
onSelect={(selectedUUID) => dispatchGames({ type: 'nextProposal', selectedUUID })}
/>
<GameProposalSelector onSelect={(selectedUUID) => dispatchGames({ type: 'nextProposal', selectedUUID })} />
} />
<Route path='active' element={<GameSelector />} />
<Route path='archive' element={<GameSelector />} />
<Route path='active' element={
<ActiveGameSelector onSelect={(selectedUUID) => dispatchGames({ type: 'nextActive', selectedUUID })} />
} />
<Route path='archive' element={
<GameArchiveSelector onSelect={(selectedUUID) => dispatchGames({ type: 'nextArchive', selectedUUID })} />
} />
</Routes>
</div>
)
@ -99,7 +98,7 @@ function ActionPanel({ players, gamesApi }) {
<Route path='proposal' element={[
<Accept key={1} />,
<Reject key={2} />,
<Cancel key={3} onClick={({uuid}) => gamesApi.pushGameProposalCancel({ uuid })} />
<Cancel key={3} onClick={({ uuid }) => gamesApi.pushGameProposalCancel({ uuid })} />
]} />
<Route path='active' element={[<DrawReq key={1} />, <DrawAcq key={2} />, <Surrender key={3} />]} />
<Route path='archive' element={[<Backward key={1} />, <Forward key={2} />]} />

View File

@ -6,11 +6,13 @@ import { Color, Player } from '../../../components/Checkers';
import Loading from '../../../components/Loading';
import Counter from '../../../components/Counter';
export default function GameSelector({ yours, opponents, isSelected, onSelect }) {
const gamesList = useContext(GamesContext).gamesList;
if (gamesList === null)
export function GameProposalSelector({ onSelect }) {
const games = useContext(GamesContext);
if (games.gamesList === null)
return <Loading />
const isSelected = (uuid) => uuid === games.proposal.selectedUUID;
const onClick = (uuid) => {
if (isSelected(uuid))
onSelect(null); // deselect previously selected game
@ -18,21 +20,95 @@ export default function GameSelector({ yours, opponents, isSelected, onSelect })
onSelect(uuid);
}
const yoursList = gamesList.filter(game => game.status === yours)
const yoursList = games.gamesList.filter(game => game.status === 'GAME_PROPOSAL_WAIT_FOR_YOU')
.map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
const opponentsList = gamesList.filter(game => game.status === opponents)
const opponentsList = games.gamesList.filter(game => game.status === 'GAME_PROPOSAL_WAIT_FOR_OPPONENT')
.map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
return (
<div className='GameSelector'>
{yoursList}
{opponentsList.length > 0 && <Separator counter={opponentsList.length} />}
{opponentsList.length > 0 && <Separator counter={opponentsList.length}>waiting for opponent</Separator>}
{opponentsList}
</div>
)
}
export function ActiveGameSelector({ onSelect }) {
const games = useContext(GamesContext);
if (games.gamesList === null)
return <Loading />
const isSelected = (uuid) => uuid === games.proposal.selectedUUID;
const onClick = (uuid) => {
if (isSelected(uuid))
onSelect(null); // deselect previously selected game
else
onSelect(uuid);
}
const yoursList = games.gamesList.filter(game => game.status === 'GAME_BOARD_WAIT_FOR_YOU')
.map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
const opponentsList = games.gamesList.filter(game => game.status === 'GAME_BOARD_WAIT_FOR_OPPONENT')
.map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
return (
<div className='GameSelector'>
{yoursList}
{opponentsList.length > 0 && <Separator counter={opponentsList.length}>waiting for opponent</Separator>}
{opponentsList}
</div>
)
}
export function GameArchiveSelector({ onSelect }) {
const games = useContext(GamesContext);
if (games.gamesList === null)
return <Loading />
const isSelected = (uuid) => uuid === games.archive.selectedUUID;
const onClick = (uuid) => {
if (isSelected(uuid))
onSelect(null); // deselect previously selected game
else
onSelect(uuid);
}
const rejectedList = games.gamesList.filter(game => game.status === 'GAME_PROPOSAL_REJECTED')
.map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
const canceledList = games.gamesList.filter(game => game.status === 'GAME_PROPOSAL_CANCELED')
.map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
const victoryList = games.gamesList.filter(game => game.status === 'GAME_RESULT_YOU_WON')
.map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
const defeatList = games.gamesList.filter(game => game.status === 'GAME_RESULT_YOU_LOOSE')
.map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
const drawList = games.gamesList.filter(game => game.status === 'GAME_RESULT_DRAW')
.map(game => <Selectable game={game} key={game.uuid} selected={isSelected(game.uuid)} onClick={onClick} />)
return (
<div className='GameSelector'>
{rejectedList.length > 0 && <Separator counter={rejectedList.length}>rejected proposals</Separator>}
{rejectedList}
{canceledList.length > 0 && <Separator counter={canceledList.length}>canceled proposals</Separator>}
{canceledList}
{victoryList.length > 0 && <Separator counter={victoryList.length}>victory</Separator>}
{victoryList}
{defeatList.length > 0 && <Separator counter={defeatList.length}>defeat</Separator>}
{defeatList}
{drawList.length > 0 && <Separator counter={drawList.length}>draw</Separator>}
{drawList}
</div>
)
}
function Selectable({ game, selected, onClick }) {
const myColor = game.myColor;
const opponentColor = Color.opposite(myColor);
@ -54,10 +130,10 @@ function Selectable({ game, selected, onClick }) {
)
};
function Separator({ counter }) {
function Separator({ counter, children }) {
return (
<div className='Separator'>
waiting for opponent
{children}
<Counter number={counter} />
</div>
)

View File

@ -15,6 +15,15 @@ export const gamesInitialState = {
message2opponent: '',
},
active: {
selectedUUID: null,
message2opponent: '',
},
archive: {
selectedUUID: null,
},
// Network
isPollingGamesList: false,
isPushingNewGame: false,
@ -42,6 +51,18 @@ function reducer(state, action) {
proposal: nextState(state.proposal, action)
};
case 'nextActive':
return {
...state,
proposal: nextState(state.proposal, action)
};
case 'nextArchive':
return {
...state,
proposal: nextState(state.proposal, action)
};
default:
throw Error('GamesReducer: unknown action.type', action.type);
}