About page

This commit is contained in:
djmil 2023-12-06 22:28:41 +01:00
parent 756f95a28c
commit e70d540632
9 changed files with 31 additions and 155 deletions

View File

@ -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>
)

View File

@ -1,5 +0,0 @@
.Leaderboard {
display: flex;
justify-content: center;
align-items: center;
}

View File

@ -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>
};

View File

@ -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 {}
}

View File

@ -1,3 +0,0 @@
.message2opponent input{
width: 270px;
}

View File

@ -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>
)
}

View File

@ -0,0 +1,8 @@
.About {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 60px;
width: 500px;
}

View 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>
};

View File

@ -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>
)