Compare commits
No commits in common. "a2de2331cf41d5b7d0f2caae634d8409a7ca44c5" and "8056c38ad51ff6e19b3fdde716dff755b716398e" have entirely different histories.
a2de2331cf
...
8056c38ad5
@ -1,11 +1,15 @@
|
|||||||
import './App.css';
|
import './App.css';
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { BrowserRouter, Routes, Route } from "react-router-dom"
|
import {
|
||||||
|
BrowserRouter,
|
||||||
|
Routes,
|
||||||
|
Route,
|
||||||
|
} from "react-router-dom"
|
||||||
|
|
||||||
import Header from "./components/Header"
|
import Header from "./components/Header"
|
||||||
import Leaderboard from "./components/Leaderboard"
|
import Leaderboard from "./components/Leaderboard"
|
||||||
import Game from "./components/Game"
|
import Game from "./components/Game"
|
||||||
import About from "./components/About"
|
import GameProposal from './components/Game/Proposal'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
@ -14,14 +18,9 @@ function App() {
|
|||||||
<Header/>
|
<Header/>
|
||||||
<div className="Container">
|
<div className="Container">
|
||||||
<Routes>
|
<Routes>
|
||||||
{/* https://stackoverflow.com/questions/40541994/multiple-path-names-for-a-same-component-in-react-router */}
|
|
||||||
<Route path="/game" element={<Game/>} />
|
|
||||||
<Route path="/game/proposal" element={<Game/>} />
|
|
||||||
<Route path="/game/active" element={<Game/>} />
|
|
||||||
<Route path="/game/archive" element={<Game/>} />
|
|
||||||
|
|
||||||
<Route path="/leaderboard" element={<Leaderboard/>} />
|
<Route path="/leaderboard" element={<Leaderboard/>} />
|
||||||
<Route path="/about" element={<About/>} />
|
<Route path="/game" element={<Game/>} />
|
||||||
|
<Route path="/game/proposal" element={<GameProposal/>} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</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,11 +1,3 @@
|
|||||||
.board {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
/* scale: 15%; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.tile {
|
.tile {
|
||||||
border: 1px solid #e4e4e4;
|
border: 1px solid #e4e4e4;
|
||||||
float: left;
|
float: left;
|
||||||
@ -18,16 +10,22 @@
|
|||||||
margin-top: -1px;
|
margin-top: -1px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tile.black {
|
.black {
|
||||||
background: lightgray;
|
background: lightgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tile.white:hover {
|
.board {
|
||||||
background-color:azure;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
/* scale: 15%; */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.stone {
|
.white:hover {
|
||||||
font-size: 120%;
|
background-color:azure;
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import './index.css';
|
import './index.css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { WhiteStone, BlackStone } from '../Game/Stone'
|
import { WhiteStone, BlackStone } from '../Stone'
|
||||||
|
|
||||||
export default function Board() {
|
export default function Board() {
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import './GameHeader.css';
|
|
||||||
import React from 'react';
|
|
||||||
import { NavLink } from "react-router-dom";
|
|
||||||
|
|
||||||
export default function GameHeader() {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<nav className='game-header'>
|
|
||||||
<NavLink to="/game/proposal">Proposal</NavLink>
|
|
||||||
<NavLink to="/game/active">Active</NavLink>
|
|
||||||
<NavLink to="/game/archive">Archive</NavLink>
|
|
||||||
</nav>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
import './GameSelector.css';
|
|
||||||
import React from 'react';
|
|
||||||
import { useLocation, matchPath } from "react-router";
|
|
||||||
|
|
||||||
import { AppData } from "../../context/data"
|
|
||||||
import Proposal from './GameSelector/GameProposal';
|
|
||||||
|
|
||||||
export default function Game() {
|
|
||||||
const [data] = React.useContext(AppData)
|
|
||||||
|
|
||||||
const { pathname } = useLocation();
|
|
||||||
const isProposalPath = matchPath("/game/proposal/*", pathname);
|
|
||||||
const isActivelPath = matchPath("/game/active/*", pathname);
|
|
||||||
const isArchivePath = matchPath("/game/archive/*", pathname);
|
|
||||||
|
|
||||||
if (!data.games)
|
|
||||||
return <div>Loading..</div>
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='game-selector'>
|
|
||||||
{isProposalPath && <Proposal games={data.games} />}
|
|
||||||
{isActivelPath && <div>TBD #1</div>}
|
|
||||||
{isArchivePath && <div>TBD #2</div>}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
import './ProposalSelector.css'
|
|
||||||
import React from 'react';
|
|
||||||
import Selectable from './Selectable';
|
|
||||||
|
|
||||||
export default function ProposalSelector({ games }) {
|
|
||||||
|
|
||||||
const waitForYou = games
|
|
||||||
.filter(game => game.status === Status.WaitForYou)
|
|
||||||
.map(game => <Selectable game={game} />)
|
|
||||||
|
|
||||||
const WaitForOpponent = games
|
|
||||||
.filter(game => game.status === Status.WaitForOpponent)
|
|
||||||
.map(game => <Selectable game={game} />)
|
|
||||||
|
|
||||||
return <div className="Container">
|
|
||||||
<div className="Games">
|
|
||||||
{waitForYou}
|
|
||||||
{WaitForOpponent.length > 0 &&
|
|
||||||
<div className="separator">
|
|
||||||
waiting for opponent ({WaitForOpponent.length})
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{WaitForOpponent}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const Status = {
|
|
||||||
WaitForOpponent: "GAME_PROPOSAL_WAIT_FOR_OPPONENT",
|
|
||||||
WaitForYou: "GAME_PROPOSAL_WAIT_FOR_YOU",
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
import './ProposalSelector.css'
|
|
||||||
import React from 'react';
|
|
||||||
import Selectable from './Selectable';
|
|
||||||
|
|
||||||
export default function ProposalSelector({ games }) {
|
|
||||||
|
|
||||||
const waitForYou = games
|
|
||||||
.filter(game => game.status === Status.WaitForYou)
|
|
||||||
.map(game => <Selectable game={game} />)
|
|
||||||
|
|
||||||
const WaitForOpponent = games
|
|
||||||
.filter(game => game.status === Status.WaitForOpponent)
|
|
||||||
.map(game => <Selectable game={game} />)
|
|
||||||
|
|
||||||
return <div className="Container">
|
|
||||||
<div className="Games">
|
|
||||||
{waitForYou}
|
|
||||||
{WaitForOpponent.length > 0 &&
|
|
||||||
<div className="separator">
|
|
||||||
waiting for opponent ({WaitForOpponent.length})
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{WaitForOpponent}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const Status = {
|
|
||||||
WaitForOpponent: "GAME_PROPOSAL_WAIT_FOR_OPPONENT",
|
|
||||||
WaitForYou: "GAME_PROPOSAL_WAIT_FOR_YOU",
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import Selectable from './Selectable';
|
|
||||||
|
|
||||||
export default function ProposalSelector({ games }) {
|
|
||||||
|
|
||||||
const waitForYou = games
|
|
||||||
.filter(game => game.status === Status.WaitForYou)
|
|
||||||
.map(game => <Selectable game={game} />)
|
|
||||||
|
|
||||||
const WaitForOpponent = games
|
|
||||||
.filter(game => game.status === Status.WaitForOpponent)
|
|
||||||
.map(game => <Selectable game={game} />)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="Games">
|
|
||||||
{waitForYou}
|
|
||||||
{WaitForOpponent.length > 0 &&
|
|
||||||
<div className="separator">
|
|
||||||
waiting for opponent ({WaitForOpponent.length})
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{WaitForOpponent}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const Status = {
|
|
||||||
WaitForOpponent: "GAME_PROPOSAL_WAIT_FOR_OPPONENT",
|
|
||||||
WaitForYou: "GAME_PROPOSAL_WAIT_FOR_YOU",
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
.selectable {
|
|
||||||
border: 1px solid black;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selectable q {
|
|
||||||
color: gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.selectable i {
|
|
||||||
font-size: 70%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .Games .li button.action {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Games .li:hover button.action {
|
|
||||||
display: initial;
|
|
||||||
} */
|
|
||||||
|
|
||||||
.separator {
|
|
||||||
/* width: 20%; */
|
|
||||||
/* height: 20px; */
|
|
||||||
border-bottom: 1px dotted black;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 50%;
|
|
||||||
padding-left: 50%;
|
|
||||||
margin-bottom: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stone {
|
|
||||||
vertical-align: -3px;
|
|
||||||
margin: 3px 3px;
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
import './Selectable.css'
|
|
||||||
import React from 'react';
|
|
||||||
import { Stone, oppositeColor } from '../Stone';
|
|
||||||
|
|
||||||
export default function Selectable({game}) {
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='selectable' key={game.uuid}>
|
|
||||||
<div className='tiltle'>
|
|
||||||
{Stone(game.myColor)}
|
|
||||||
<i>vs</i>
|
|
||||||
{Stone(oppositeColor(game.myColor))}
|
|
||||||
{game.opponentName}
|
|
||||||
</div>
|
|
||||||
<q>{game.message}</q>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
0
webapp/src/components/Game/Proposal/index.css
Normal file
0
webapp/src/components/Game/Proposal/index.css
Normal file
22
webapp/src/components/Game/Proposal/index.jsx
Normal file
22
webapp/src/components/Game/Proposal/index.jsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import './index.css';
|
||||||
|
import React from 'react';
|
||||||
|
// import { NavLink } from "react-router-dom";
|
||||||
|
// import { AppData } from "../../../context/data"
|
||||||
|
import GameHeader from '../../GameHeader'
|
||||||
|
import GameSelector from '../../GameSelector'
|
||||||
|
import Board from '../../Board'
|
||||||
|
|
||||||
|
export default function Proposal() {
|
||||||
|
// const [data] = React.useContext(AppData)
|
||||||
|
|
||||||
|
return <div className="split">
|
||||||
|
<div className='split left'>
|
||||||
|
<GameHeader/>
|
||||||
|
<button>+ Create</button>
|
||||||
|
<GameSelector/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='split right'></div>
|
||||||
|
<Board/>
|
||||||
|
</div>
|
||||||
|
};
|
@ -1,3 +0,0 @@
|
|||||||
.stone {
|
|
||||||
cursor: default; /* disable 'I beam' cursor change */
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
import './index.css';
|
import './index.css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import GameHeader from './GameHeader'
|
import GameHeader from '../GameHeader'
|
||||||
import GameSelector from './GameSelector'
|
import GameSelector from '../GameSelector'
|
||||||
import Board from '../Board'
|
import Board from '../Board'
|
||||||
|
|
||||||
// import { AppData } from "../../context/data"
|
// import { AppData } from "../../context/data"
|
||||||
@ -11,13 +11,12 @@ export default function Game() {
|
|||||||
return <div className="split">
|
return <div className="split">
|
||||||
|
|
||||||
<div className='split left'>
|
<div className='split left'>
|
||||||
<GameHeader />
|
<GameHeader/>
|
||||||
<GameSelector />
|
<GameSelector/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='split right'>
|
<div className='split right'></div>
|
||||||
<Board />
|
<Board/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
}
|
};
|
||||||
|
15
webapp/src/components/GameHeader/index.jsx
Normal file
15
webapp/src/components/GameHeader/index.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import './index.css';
|
||||||
|
import React from 'react';
|
||||||
|
import { NavLink } from "react-router-dom";
|
||||||
|
// import { AppData } from "../../context/data"
|
||||||
|
|
||||||
|
export default function GameHeader() {
|
||||||
|
// const [data] = React.useContext(AppData)
|
||||||
|
|
||||||
|
|
||||||
|
return <nav className="game-header">
|
||||||
|
<NavLink to="/game/proposal">Proposal</NavLink>
|
||||||
|
<NavLink to="/game/active">Active</NavLink>
|
||||||
|
<NavLink to="/game/archive">Archive</NavLink>
|
||||||
|
</nav>
|
||||||
|
};
|
@ -40,3 +40,8 @@
|
|||||||
padding-left: 50%;
|
padding-left: 50%;
|
||||||
margin-bottom: 7px;
|
margin-bottom: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stone {
|
||||||
|
font-size: 140%;
|
||||||
|
vertical-align: -3px;
|
||||||
|
}
|
82
webapp/src/components/GameSelector/index.jsx
Normal file
82
webapp/src/components/GameSelector/index.jsx
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import './index.css';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { AppData } from "../../context/data"
|
||||||
|
|
||||||
|
export default function Game() {
|
||||||
|
const [data] = React.useContext(AppData)
|
||||||
|
|
||||||
|
if (!data?.games)
|
||||||
|
return <div>Loading..</div>
|
||||||
|
|
||||||
|
// for (const [key, value] of Object.entries(data.games))
|
||||||
|
// console.log(key, value);
|
||||||
|
|
||||||
|
console.log("data.games", data.games)
|
||||||
|
const waitForYou = data.games
|
||||||
|
.filter(game => game.status === Status.WaitForYou)
|
||||||
|
.map(game => {
|
||||||
|
return <div className="li" key={game.uuid}>
|
||||||
|
<p>
|
||||||
|
You {Stone(game.myColor)} <i>vs</i> {game.opponentName} {Stone(oppositeColor(game.myColor))}
|
||||||
|
<br/>
|
||||||
|
<q>{game.message}</q>
|
||||||
|
<br/>
|
||||||
|
{/* <Accept uuid={game.uuid}/>
|
||||||
|
<Reject uuid={game.uuid}/> */}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
});
|
||||||
|
|
||||||
|
const WaitForOpponent = data.games
|
||||||
|
.filter(game => game.status === Status.WaitForOpponent)
|
||||||
|
.map(game => {
|
||||||
|
return <div className="li" key={game.uuid}>
|
||||||
|
<p>
|
||||||
|
You {Stone(game.myColor)} <i>vs</i> {game.opponentName} {Stone(oppositeColor(game.myColor))}
|
||||||
|
<br/>
|
||||||
|
<q>{game.message}</q>
|
||||||
|
<br/>
|
||||||
|
{/* <Cancel uuid={game.uuid}/> */}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
});
|
||||||
|
|
||||||
|
return <div className="Container">
|
||||||
|
<div className="Games">
|
||||||
|
{waitForYou}
|
||||||
|
{WaitForOpponent.length > 0 &&
|
||||||
|
<div className="separator">
|
||||||
|
waiting for opponent ({WaitForOpponent.length})
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{WaitForOpponent}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Status = {
|
||||||
|
WaitForOpponent: "GAME_PROPOSAL_WAIT_FOR_OPPONENT",
|
||||||
|
WaitForYou: "GAME_PROPOSAL_WAIT_FOR_YOU",
|
||||||
|
}
|
||||||
|
|
||||||
|
function Stone(color) {
|
||||||
|
if (color === "WHITE")
|
||||||
|
return <span className="stone">⛀</span>
|
||||||
|
|
||||||
|
if (color === "BLACK")
|
||||||
|
return <span className="stone">⛂</span>
|
||||||
|
|
||||||
|
return <span className="stone">{color}</span>
|
||||||
|
}
|
||||||
|
|
||||||
|
function oppositeColor(color) {
|
||||||
|
if (color === "WHITE")
|
||||||
|
return "BLACK"
|
||||||
|
|
||||||
|
if (color === "BLACK")
|
||||||
|
return "WHITE"
|
||||||
|
|
||||||
|
return color
|
||||||
|
}
|
7
webapp/src/components/Stone/index.css
Normal file
7
webapp/src/components/Stone/index.css
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.white-stone {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.black-stone {
|
||||||
|
cursor: default;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import './Stone.css';
|
import './index.css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export function Stone( color ) {
|
export function Stone( color ) {
|
||||||
@ -15,11 +15,11 @@ export function Stone( color ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function WhiteStone() {
|
export function WhiteStone() {
|
||||||
return <span className="stone white">⛀</span>
|
return <span className="white-stone">⛀</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BlackStone() {
|
export function BlackStone() {
|
||||||
return <span className="stone black">⛂</span>
|
return <span className="black-stone">⛂</span>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function oppositeColor(color) {
|
export function oppositeColor(color) {
|
Loading…
Reference in New Issue
Block a user