About page
This commit is contained in:
parent
756f95a28c
commit
e70d540632
@ -1,11 +1,11 @@
|
||||
import './App.css';
|
||||
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 Wobler from './components/Wobler';
|
||||
|
||||
import About from "./components/About"
|
||||
import About from "./container/About"
|
||||
import Games from './container/Games';
|
||||
import Leaderboard from './container/Leaderboard';
|
||||
|
||||
@ -41,10 +41,11 @@ export default function App() {
|
||||
<BrowserRouter>
|
||||
<Header configReducer={[config, dispatcConfig]} isPolling={isPolling}/>
|
||||
<Routes>
|
||||
<Route path='/' element={<About />} />
|
||||
<Route path='/about' element={<About />} />
|
||||
<Route path='/games/*' element={<Games games={games} players={players} />} />
|
||||
<Route path='/leaderboard' element={<Leaderboard players={players} />} />
|
||||
<Route path="*" element={<Navigate to="/games" replace />}
|
||||
/>
|
||||
</Routes>
|
||||
</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 { 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 { GameProposalSelector, ActiveGameSelector, GameArchiveSelector } from './games/GameSelector';
|
||||
@ -82,6 +82,8 @@ function ViewProvider({ dispatchGuide, players }) {
|
||||
<GameArchiveSelector onSelect={(uuid) => dispatchGuide({ type: 'selectedUUID', archive: uuid })} />
|
||||
} />
|
||||
|
||||
<Route path="*" element={<Navigate to="/games/active" replace />} />
|
||||
|
||||
</Routes>
|
||||
</div>
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user