About page
This commit is contained in:
parent
756f95a28c
commit
e70d540632
@ -1,11 +1,11 @@
|
|||||||
import './App.css';
|
import './App.css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { BrowserRouter, Routes, Route, NavLink } from 'react-router-dom';
|
import { BrowserRouter, Routes, Route, NavLink, Navigate } from 'react-router-dom';
|
||||||
|
|
||||||
import OnlineToggle from './components/OnlineToggle';
|
import OnlineToggle from './components/OnlineToggle';
|
||||||
import Wobler from './components/Wobler';
|
import Wobler from './components/Wobler';
|
||||||
|
|
||||||
import About from "./components/About"
|
import About from "./container/About"
|
||||||
import Games from './container/Games';
|
import Games from './container/Games';
|
||||||
import Leaderboard from './container/Leaderboard';
|
import Leaderboard from './container/Leaderboard';
|
||||||
|
|
||||||
@ -41,10 +41,11 @@ export default function App() {
|
|||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Header configReducer={[config, dispatcConfig]} isPolling={isPolling}/>
|
<Header configReducer={[config, dispatcConfig]} isPolling={isPolling}/>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path='/' element={<About />} />
|
|
||||||
<Route path='/about' element={<About />} />
|
<Route path='/about' element={<About />} />
|
||||||
<Route path='/games/*' element={<Games games={games} players={players} />} />
|
<Route path='/games/*' element={<Games games={games} players={players} />} />
|
||||||
<Route path='/leaderboard' element={<Leaderboard players={players} />} />
|
<Route path='/leaderboard' element={<Leaderboard players={players} />} />
|
||||||
|
<Route path="*" element={<Navigate to="/games" replace />}
|
||||||
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
)
|
)
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
.Leaderboard {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
import React from "react"
|
|
||||||
import './index.css';
|
|
||||||
|
|
||||||
export default function Leaderboard() {
|
|
||||||
|
|
||||||
return <div className="About">
|
|
||||||
A simple american checkers game<br/>
|
|
||||||
</div>
|
|
||||||
};
|
|
@ -1,111 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { AppContext } from '../../../context/app'
|
|
||||||
import { AppData } from '../../../context/data'
|
|
||||||
import { WHITE, BLACK } from '../Stone'
|
|
||||||
import Wobler from '../../Wobler'
|
|
||||||
|
|
||||||
export default function Create() {
|
|
||||||
const ctx = Definitions()
|
|
||||||
|
|
||||||
const onClick = () => {
|
|
||||||
if (!ctx.hasPlayers)
|
|
||||||
return alert("Choose both black and white players");
|
|
||||||
|
|
||||||
if (!ctx.hasCurrentUser)
|
|
||||||
return alert("You must be one of the players");
|
|
||||||
|
|
||||||
if (ctx.fetching === true)
|
|
||||||
return
|
|
||||||
|
|
||||||
const request = ctx.getGameProposalRequest()
|
|
||||||
|
|
||||||
ctx.setFetching(true)
|
|
||||||
|
|
||||||
postData("/api/gameproposal", request)
|
|
||||||
.then((responce) => {
|
|
||||||
console.log("responce", responce) // JSON data parsed by `data.json()` call
|
|
||||||
ctx.clear_Message2Opponent()
|
|
||||||
ctx.setFetching(false)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
className={'game-action create'
|
|
||||||
+ (ctx.enabled ? ' enabled' : ' disabled')
|
|
||||||
+ (ctx.fetching ? ' busy' : '')
|
|
||||||
}
|
|
||||||
onClick={onClick}
|
|
||||||
>
|
|
||||||
<Wobler text="Leaderboard" dance={ctx.fetching} />
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function Definitions() {
|
|
||||||
const [ctx, dispatchCtx] = React.useContext(AppContext)
|
|
||||||
const [data] = React.useContext(AppData)
|
|
||||||
|
|
||||||
const isCurrentUser = data.isCurrentUser
|
|
||||||
const whitePlayerName = ctx.newGame.whitePlayer
|
|
||||||
const blackPlayerName = ctx.newGame.blackPlayer
|
|
||||||
|
|
||||||
const hasPlayers = whitePlayerName !== blackPlayerName
|
|
||||||
&& whitePlayerName !== ''
|
|
||||||
&& blackPlayerName !== ''
|
|
||||||
|
|
||||||
const hasCurrentUser = isCurrentUser(whitePlayerName) || isCurrentUser(blackPlayerName)
|
|
||||||
|
|
||||||
const getGameProposalRequest = () => {
|
|
||||||
const [opponentName, opponentColor] = getOpponent(isCurrentUser, whitePlayerName, blackPlayerName)
|
|
||||||
|
|
||||||
return {
|
|
||||||
opponentName,
|
|
||||||
opponentColor,
|
|
||||||
board: null,
|
|
||||||
message: ctx.newGame.message
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
hasPlayers,
|
|
||||||
hasCurrentUser,
|
|
||||||
enabled: hasPlayers && hasCurrentUser,
|
|
||||||
|
|
||||||
fetching: ctx.newGame.fetching,
|
|
||||||
setFetching: (status) => { dispatchCtx({ update: "newGame", fetching: status }) },
|
|
||||||
|
|
||||||
getGameProposalRequest,
|
|
||||||
clear_Message2Opponent: () => { dispatchCtx({ update: "newGame", message: '' }) },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getOpponent(isCurrentUser, whitePlayerName, blackPlayerName) {
|
|
||||||
if (isCurrentUser(whitePlayerName)) {
|
|
||||||
return [blackPlayerName, BLACK()]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCurrentUser(blackPlayerName)) {
|
|
||||||
return [whitePlayerName, WHITE()]
|
|
||||||
}
|
|
||||||
|
|
||||||
return ['', '']
|
|
||||||
}
|
|
||||||
|
|
||||||
async function postData(url = "", data = {}) {
|
|
||||||
console.log("POST", url, data)
|
|
||||||
|
|
||||||
const response = await fetch(url, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(data), // body data type must match "Content-Type" header
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.ok)
|
|
||||||
return response.json()// parses JSON response into native JavaScript objects
|
|
||||||
|
|
||||||
console.wrn(response)
|
|
||||||
return {}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
.message2opponent input{
|
|
||||||
width: 270px;
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
import './Message2Opponent.css'
|
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import { AppContext } from '../../context/app'
|
|
||||||
|
|
||||||
export default function Message2Opponent() {
|
|
||||||
const [ctx, dispatchCtx] = React.useContext(AppContext)
|
|
||||||
|
|
||||||
const setMessage = (message) => {
|
|
||||||
dispatchCtx({ update: "newGame", message })
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='message2opponent'>
|
|
||||||
<input
|
|
||||||
placeholder='Message to opponent'
|
|
||||||
value={ctx.newGame.message}
|
|
||||||
maxLength={150}
|
|
||||||
onChange={e => setMessage(e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
8
webapp/src/container/About.css
Normal file
8
webapp/src/container/About.css
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.About {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
margin-top: 60px;
|
||||||
|
width: 500px;
|
||||||
|
}
|
16
webapp/src/container/About.jsx
Normal file
16
webapp/src/container/About.jsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import React from "react"
|
||||||
|
import './About.css';
|
||||||
|
|
||||||
|
export default function Leaderboard() {
|
||||||
|
|
||||||
|
return <div className="About">
|
||||||
|
A simple American checkers game, where rules are enforced by Corda Contracts.
|
||||||
|
<br /><br />
|
||||||
|
Click online-offline toggle to manually initiate fetching of fresh game states from server. By default, an update happens every 30 sec for Games and every 5 min for the Leaderboard.
|
||||||
|
<br /><br />
|
||||||
|
The wobly-dancing letters inside navigation elements and command buttons are used as an indication of request processing. Currently, game state update is a lengthy process and usually takes ~20 sec to finish.
|
||||||
|
<br/><i>Hint</i>: You can have multiple game state update requests running at the same time, so there is no particular reason to wait for one to finish before initiating another.
|
||||||
|
<br /><br />
|
||||||
|
Please pay attention to the text entry field below the checkers board. This is not a live chat with an opponent, but rather a 'message' that will become a part of the next game state. So be sure to type your message <i>before</i> submitting a new game state to the system.
|
||||||
|
</div>
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useContext, useEffect } from 'react';
|
import React, { useContext, useEffect } from 'react';
|
||||||
import { GamesStateContext, GamesGuideContext } from '../context/games';
|
import { GamesStateContext, GamesGuideContext } from '../context/games';
|
||||||
import { Routes, Route, NavLink } from 'react-router-dom';
|
import { Routes, Route, NavLink, Navigate } from 'react-router-dom';
|
||||||
|
|
||||||
import NewGame from './games/NewGame';
|
import NewGame from './games/NewGame';
|
||||||
import { GameProposalSelector, ActiveGameSelector, GameArchiveSelector } from './games/GameSelector';
|
import { GameProposalSelector, ActiveGameSelector, GameArchiveSelector } from './games/GameSelector';
|
||||||
@ -82,6 +82,8 @@ function ViewProvider({ dispatchGuide, players }) {
|
|||||||
<GameArchiveSelector onSelect={(uuid) => dispatchGuide({ type: 'selectedUUID', archive: uuid })} />
|
<GameArchiveSelector onSelect={(uuid) => dispatchGuide({ type: 'selectedUUID', archive: uuid })} />
|
||||||
} />
|
} />
|
||||||
|
|
||||||
|
<Route path="*" element={<Navigate to="/games/active" replace />} />
|
||||||
|
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user