initial implemention

This commit is contained in:
djmil 2023-11-14 10:03:08 +01:00
parent 04f0b86527
commit ddd5d160a4
7 changed files with 135 additions and 32 deletions

View File

@ -22,7 +22,13 @@ export default function useGamesApi(gamesReducer, config) {
pushNewGame: (reqParams) => doPushing('/api/gameproposal', 'POST', reqParams, { pushNewGame: (reqParams) => doPushing('/api/gameproposal', 'POST', reqParams, {
onPushing: (isPushingNewGame) => dispatchGames({ type: 'next', isPushingNewGame }), onPushing: (isPushingNewGame) => dispatchGames({ type: 'next', isPushingNewGame }),
onSuccess: (game) => dispatchGames({ type: 'next', gamesList: [...games.gamesList, game] }) onSuccess: (game) => dispatchGames({ type: 'next', gamesList: [...games.gamesList, game], newGame: emptyNewGame })
}), }),
} }
}
const emptyNewGame = {
whitePlayer: '',
blackPlayer: '',
message2opponent: ''
} }

View File

@ -16,6 +16,7 @@ import Backward from './games/action/Backward';
import Forward from './games/action/Forward'; import Forward from './games/action/Forward';
import GameBoard from './games/GameBoard'; import GameBoard from './games/GameBoard';
import Message2Opponent from './games/Message2Opponent';
import './Games.css'; import './Games.css';
@ -27,14 +28,15 @@ export default function Games({ context: { gamesReducer, gamesApi }, players })
<div className='Games'> <div className='Games'>
<div className='left-side'> <div className='left-side'>
<ViewSelector /> <ViewSelector />
<ViewProvider players={players} dispatchGames={dispatchGames} /> <ViewProvider gamesReducer={gamesReducer} players={players} />
</div> </div>
<div className='right-side'> <div className='right-side'>
<ActionPanel players={players} gamesApi={gamesApi} /> <ActionPanel gamesApi={gamesApi} players={players} />
<GameBoard /> <GameBoard />
<Message2Opponent dispatchGames={dispatchGames} />
{/* {/*
<GameMessage /> <GameMessage />
<Message2Opponent /> */} */}
</div> </div>
</div > </div >
</GamesContext.Provider> </GamesContext.Provider>
@ -54,15 +56,19 @@ function ViewSelector() {
) )
} }
function ViewProvider({ players, dispatchGames }) { function ViewProvider({ gamesReducer, players }) {
const [/*games*/, dispatchGames] = gamesReducer;
return ( return (
<div className='ViewProvider'> <div className='ViewProvider'>
<Routes> <Routes>
<Route path='new' element={ <Route path='new' element={
<NewGame <NewGame
onSelectPlayer={(whitePlayer, blackPlayer) => {
dispatchGames({ type: 'nextNewGame', whitePlayer, blackPlayer })
}}
players={players} players={players}
onSelectPlayer={(whitePlayer, blackPlayer) => dispatchGames({ type: "next", newGame: { whitePlayer, blackPlayer } })}
/> />
} /> } />

View File

@ -0,0 +1,62 @@
import React, { useContext, /* useEffect,*/ useRef, useState } from 'react';
import { useLocation, matchPath } from 'react-router-dom';
import { GamesContext } from '../../context/games';
//import { useLocationChange } from '../../hook/Location';
export default function Message2Opponent({ dispatchGames }) {
const games = useContext(GamesContext);
const [message2opponent, setMessage2opponent] = useState('');
const { pathname } = useLocation();
const timeoutIdRef = useRef(null);
if (timeoutIdRef.current === null) {
// sync: internal <- external
// Sync external and internsl states only in abnsence of a delay timer
console.log("check message", message2opponent);
if (matchPath('/games/new', pathname)) {
if (message2opponent !== games.newGame.message2opponent)
setMessage2opponent(games.newGame.message2opponent);
}
else
if (message2opponent !== '') {
setMessage2opponent('');
}
}
console.log('timeout.current', timeoutIdRef.current)
/* --- */
const delayedSync = (message2opponent) => {
timeoutIdRef.current = null;
// sync: internl -> external
if (matchPath('/games/new', pathname))
return dispatchGames({ type: 'nextNewGame', message2opponent });
console.warn('unknown path');
}
const onChange = (value) => {
setMessage2opponent(value);
if (timeoutIdRef.current)
clearTimeout(timeoutIdRef.current); // cancel previous sync
timeoutIdRef.current = setTimeout(() => delayedSync(value), 500);
}
//var gpathname;
//useLocationChange(({ pathname }) => {
return (
<input className='Message2Opponent'
placeholder='Message to opponent'
value={message2opponent}
maxLength={150}
onChange={e => onChange(e.target.value)}
/>
)
}

View File

@ -29,7 +29,7 @@ export default function Create({ isCurrentUser, pushNewGame }) {
opponentName, opponentName,
opponentColor, opponentColor,
board: null, // default board configuration board: null, // default board configuration
message: 'default NewGame req message' message: games.newGame.message2opponent
} }
pushNewGame(reqParams); pushNewGame(reqParams);

View File

@ -0,0 +1,46 @@
import { useRef, useEffect } from 'react';
import { useLocation } from 'react-router-dom';
export default function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
/* Usage example
const useLocationChange = (action) => {
const location = useLocation();
const prevLocation = usePrevious(location);
useEffect(() => {
action(location, prevLocation);
}, [location]);
}
*/
// runs action(location) on location, i.e. route, change
export const useLocationChange = (action) => {
const location = useLocation();
const prevLocation = usePrevious(location);
useEffect(() => {
if (location !== prevLocation)
action(location, prevLocation);
}, [action, location, prevLocation]);
}
/*
* Usage example
*/
// const MyComponent1 = () => {
// useLocationChange((location) => {
// console.log('handle route change here', location)
// });
// // other code
// }

View File

@ -1,24 +0,0 @@
import { useRef, useEffect } from 'react';
export default function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
/* Usage example
const useLocationChange = (action) => {
const location = useLocation();
const prevLocation = usePrevious(location);
useEffect(() => {
action(location, prevLocation);
}, [location]);
}
*/

View File

@ -6,7 +6,8 @@ const initialState = {
newGame: { newGame: {
whitePlayer: '', whitePlayer: '',
blackPlayer: '' blackPlayer: '',
message2opponent: '',
}, },
// Network // Network
@ -20,6 +21,12 @@ function reducer(state, action) {
case 'next': case 'next':
return nextState(state, action); return nextState(state, action);
case 'nextNewGame':
return {
...state,
newGame: nextState(state.newGame, action)
};
default: default:
throw Error('GamesReducer: unknown action.type', action.type); throw Error('GamesReducer: unknown action.type', action.type);
} }