Add getGame and listGames endpoints, client methods and initial components

This commit is contained in:
Miguel de la Cruz 2021-09-16 00:37:07 +02:00
parent ff455414f8
commit 08ab312f92
8 changed files with 136 additions and 8 deletions

View file

@ -1,3 +1,14 @@
import * as log from './log'
function tokenHeaders(headers) {
return {
'Content-Type': 'application/json',
Authorization: `Bearer ${localStorage.getItem('token')}`,
...headers
}
}
export class Client {
login(username, password) {
// ToDo: handle error
@ -9,13 +20,39 @@ export class Client {
if (r.status === 200) {
return r.text()
}
console.error("INVALID")
throw new Error("invalid credentials")
log.error(`Got invalid response when trying to login. Code ${r.status}`)
throw new Error(`${r.status} invalid response`)
}).then(token => {
localStorage.setItem('token', token)
return token
})
}
listGames() {
return fetch("/api/games", {
method: 'GET',
headers: tokenHeaders(),
}).then(r => {
if (r.status === 200) {
return r.json()
}
log.error(`Got invalid response when trying to list games. Code ${r.status}`)
throw new Error(`${r.status} invalid response`)
})
}
getGame(id) {
return fetch(`/api/games/${id}`, {
method: 'GET',
headers: tokenHeaders(),
}).then(r => {
if (r.status === 200) {
return r.json()
}
log.error(`Got invalid response when trying to get game ${id}. Code ${r.status}`)
throw new Error(`${r.status} invalid response`)
})
}
}
const client = new Client()

View file

@ -13,6 +13,7 @@ import { CssBaseline } from '@material-ui/core';
import { TokenContext } from './context'
import Login from './pages/login'
import Home from './pages/home'
import Game from './pages/game'
const Secure = ({children}) => {
@ -36,7 +37,13 @@ const App = () => {
<Login />
</Route>
<Route path="/">
<Route path="/game/:gameId">
<Secure>
<Game />
</Secure>
</Route>
<Route exact path="/">
<Secure>
<Home />
</Secure>

View file

@ -13,25 +13,25 @@ function nowStr() {
return `${now.getFullYear()}${now.getDate()}${now.getMonth()}.${now.getHours()}${now.getMinutes()}${now.getSeconds()}`
}
export function Debug(msg) {
export function debug(msg) {
if (level <= levelDebug) {
console.log(`[DBG ${nowStr()}] ${msg}`)
}
}
export function Info(msg) {
export function info(msg) {
if (level <= levelInfo) {
console.log(`[INF ${nowStr()}] ${msg}`)
}
}
export function Warn(msg) {
export function warn(msg) {
if (level <= levelWarn) {
console.warn(`[WRN ${nowStr()}] ${msg}`)
}
}
export function Error(msg) {
export function error(msg) {
if (level <= levelError) {
console.error(`[ERR ${nowStr()}] ${msg}`)
}

22
webapp/src/pages/game.js Normal file
View file

@ -0,0 +1,22 @@
import { useState, useEffect } from 'react'
import { useParams } from 'react-router-dom'
import client from '../client'
const Game = () => {
const [game, setGame] = useState({})
const { gameId } = useParams()
useEffect(() => {
client.getGame(gameId).then(game => setGame(game))
}, [gameId])
return (
<div class="game">
<h1>{game.name}</h1>
</div>
)
}
export default Game

View file

@ -1,12 +1,36 @@
import { useContext } from 'react'
import {
useContext,
useEffect,
useState
} from 'react'
import { Link } from 'react-router-dom'
import {
Box,
Button
} from '@material-ui/core';
import { TokenContext } from '../context'
import client from '../client'
const GameList = () => {
const [games, setGames] = useState([])
useEffect(() => {
client.listGames().then(gameList => setGames(gameList))
}, [])
return (
<div class="game-list">
<h3 class="game-list-title">Game List</h3>
<ul>
{games.map(game => (<li><Link to={`/game/${game.id}`}>{game.name}</Link></li>))}
</ul>
</div>
)
}
const Home = () => {
const { token, setToken } = useContext(TokenContext)
@ -20,6 +44,8 @@ const Home = () => {
<Box>
<h1>Home</h1>
<GameList />
<Button
variant="contained"
color="secondary"