setting up routing, cleaning up context
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
<title>Splendor (clone by Mikayla Dobson)</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
87
package-lock.json
generated
87
package-lock.json
generated
@@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -378,6 +379,17 @@
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
|
||||
"integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/template": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz",
|
||||
@@ -1087,6 +1099,14 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/history": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz",
|
||||
"integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.7.6"
|
||||
}
|
||||
},
|
||||
"node_modules/is-core-module": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
|
||||
@@ -1243,6 +1263,35 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz",
|
||||
"integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==",
|
||||
"dependencies": {
|
||||
"history": "^5.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/react-router-dom": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz",
|
||||
"integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==",
|
||||
"dependencies": {
|
||||
"history": "^5.2.0",
|
||||
"react-router": "6.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8",
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
@@ -1692,6 +1741,14 @@
|
||||
"@babel/helper-plugin-utils": "^7.18.6"
|
||||
}
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.18.9",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
|
||||
"integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@babel/template": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.6.tgz",
|
||||
@@ -2125,6 +2182,14 @@
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"dev": true
|
||||
},
|
||||
"history": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz",
|
||||
"integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.7.6"
|
||||
}
|
||||
},
|
||||
"is-core-module": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
|
||||
@@ -2232,6 +2297,28 @@
|
||||
"integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
|
||||
"dev": true
|
||||
},
|
||||
"react-router": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz",
|
||||
"integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==",
|
||||
"requires": {
|
||||
"history": "^5.2.0"
|
||||
}
|
||||
},
|
||||
"react-router-dom": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz",
|
||||
"integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==",
|
||||
"requires": {
|
||||
"history": "^5.2.0",
|
||||
"react-router": "6.3.0"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.3.0",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
41
src/App.tsx
41
src/App.tsx
@@ -1,36 +1,27 @@
|
||||
import { BrowserRouter, Routes, Route } from 'react-router-dom'
|
||||
import Gameboard from './components/Gameboard/Gameboard'
|
||||
import './App.css'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useCallback, useContext, useEffect, useState } from 'react'
|
||||
import { appState, Context } from './context/Context'
|
||||
import AvailableChips from './components/Resources/AvailableChips';
|
||||
import GameConstructor from './util/GameConstructor';
|
||||
import { PlayerData } from './util/types';
|
||||
|
||||
function App() {
|
||||
const [state, setState] = useState({
|
||||
gameboard: null,
|
||||
store: null,
|
||||
players: null,
|
||||
round: 0
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (!state.players) {
|
||||
console.log('no players!');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const getGameboard = useCallback(() => {
|
||||
|
||||
}, [])
|
||||
let AppContext = useContext(Context);
|
||||
let { players } = AppContext;
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<Gameboard />
|
||||
{/*
|
||||
|
||||
< INVENTORY />
|
||||
< PLAYERS />
|
||||
|
||||
*/}
|
||||
<h1>SPLENDOR</h1>
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
<Route path="/" element={<GameConstructor />} />
|
||||
<Route path="/game" element={<Gameboard />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export default App
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { CardData } from '../../util/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
type CardProps = {
|
||||
data: CardData
|
||||
@@ -14,7 +15,7 @@ export default function Card({ data }: CardProps) {
|
||||
{ Object.keys(data.resourceCost).map((key, value) => {
|
||||
return (
|
||||
// @ts-ignore
|
||||
<p>{key}: {data.resourceCost[key]}</p>
|
||||
<p key={v4()}>{key}: {data.resourceCost[key]}</p>
|
||||
)
|
||||
}) }
|
||||
</div>
|
||||
|
||||
@@ -1,48 +1,37 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { CardData, NobleData } from '../../util/types';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { Context } from '../../context/Context';
|
||||
import GameConstructor from '../../util/GameConstructor';
|
||||
import { NobleData } from '../../util/types';
|
||||
import AvailableChips from '../Resources/AvailableChips';
|
||||
import CardRow from './CardRow';
|
||||
import CardDeck from '../../data/cards.json';
|
||||
import Nobles from '../../data/nobles.json';
|
||||
|
||||
export default function Gameboard() {
|
||||
const [state, setState] = useState({
|
||||
deck: CardDeck,
|
||||
nobles: Nobles.nobles,
|
||||
cardRows: {
|
||||
tierOne: new Array<CardData>,
|
||||
tierTwo: new Array<CardData>,
|
||||
tierThree: new Array<CardData>
|
||||
},
|
||||
tradingResources: {
|
||||
ruby: 7,
|
||||
sapphire: 7,
|
||||
emerald: 7,
|
||||
diamond: 7,
|
||||
onyx: 7,
|
||||
gold: 5
|
||||
}
|
||||
})
|
||||
|
||||
let AppContext = useContext(Context);
|
||||
let { gameboard, players } = AppContext;
|
||||
const [view, setView] = useState(<p>Loading...</p>)
|
||||
|
||||
useEffect(() => {
|
||||
initializeBoard();
|
||||
console.log(state);
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
setView(
|
||||
<>
|
||||
<CardRow tier={3} cards={state.cardRows.tierThree} />
|
||||
<CardRow tier={2} cards={state.cardRows.tierTwo} />
|
||||
<CardRow tier={1} cards={state.cardRows.tierOne} />
|
||||
</>
|
||||
)
|
||||
}, [state.cardRows]);
|
||||
if (!players.length) {
|
||||
setView(<GameConstructor />);
|
||||
} else {
|
||||
setView(
|
||||
<div className="gameboard-rows">
|
||||
<CardRow tier={3} cards={gameboard.cardRows.tierThree} />
|
||||
<CardRow tier={2} cards={gameboard.cardRows.tierTwo} />
|
||||
<CardRow tier={1} cards={gameboard.cardRows.tierOne} />
|
||||
<AvailableChips />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}, [players]);
|
||||
|
||||
const shuffleDeck = () => {
|
||||
if (!state.deck) return;
|
||||
let newDeck = state.deck;
|
||||
if (!gameboard.deck) return;
|
||||
let newDeck = gameboard.deck;
|
||||
|
||||
for (const [key, value] of Object.entries(newDeck)) {
|
||||
for (let i = value.length - 1; i > 0; i--) {
|
||||
@@ -53,11 +42,12 @@ export default function Gameboard() {
|
||||
}
|
||||
}
|
||||
|
||||
setState({ ...state, deck: newDeck });
|
||||
gameboard.deck = newDeck;
|
||||
// setState({ ...gameboard, deck: newDeck });
|
||||
}
|
||||
|
||||
const setNobles = () => {
|
||||
let newNobles = state.nobles;
|
||||
let newNobles = gameboard.nobles;
|
||||
let shuffledNobles = new Array<NobleData>;
|
||||
|
||||
while (shuffledNobles.length < 4) {
|
||||
@@ -66,16 +56,17 @@ export default function Gameboard() {
|
||||
shuffledNobles.push(randNoble);
|
||||
}
|
||||
|
||||
setState({ ...state, nobles: shuffledNobles });
|
||||
// setState({ ...gameboard, nobles: shuffledNobles });
|
||||
gameboard.nobles = shuffledNobles;
|
||||
}
|
||||
|
||||
const initializeBoard = () => {
|
||||
shuffleDeck();
|
||||
setNobles();
|
||||
|
||||
let newState = state;
|
||||
let newState = gameboard;
|
||||
|
||||
for (const [key, value] of Object.entries(state.deck)) {
|
||||
for (const [key, value] of Object.entries(gameboard.deck)) {
|
||||
// @ts-ignore
|
||||
while (newState.cardRows[key].length < 4) {
|
||||
const nextCard = value.shift();
|
||||
@@ -84,13 +75,8 @@ export default function Gameboard() {
|
||||
}
|
||||
}
|
||||
|
||||
setState(newState);
|
||||
gameboard = newState;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>SPLENDOR</h1>
|
||||
{ view }
|
||||
</div>
|
||||
)
|
||||
return view;
|
||||
}
|
||||
11
src/components/Player/AllPlayers.tsx
Normal file
11
src/components/Player/AllPlayers.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { useContext } from "react"
|
||||
import { Context } from "../../context/Context"
|
||||
|
||||
export default function AllPlayers() {
|
||||
const AppContext = useContext(Context);
|
||||
|
||||
return (
|
||||
<>
|
||||
</>
|
||||
)
|
||||
}
|
||||
22
src/components/Resources/AvailableChips.tsx
Normal file
22
src/components/Resources/AvailableChips.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { useContext } from "react"
|
||||
import { Context } from "../../context/Context"
|
||||
import { v4 } from "uuid";
|
||||
|
||||
export default function AvailableChips() {
|
||||
const { gameboard } = useContext(Context);
|
||||
|
||||
return (
|
||||
<div className="available-chips">
|
||||
{
|
||||
Object.keys(gameboard.tradingResources).map((key: string) => {
|
||||
return (
|
||||
<div key={v4()} className={`chips-${key}`}>
|
||||
{/* @ts-ignore */}
|
||||
<p>{key}: {gameboard.tradingResources[key]}</p>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
28
src/context/Context.ts
Normal file
28
src/context/Context.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { CardData, NobleData, PlayerData } from '../util/types';
|
||||
import CardDeck from '../data/cards.json';
|
||||
import { createContext } from 'react';
|
||||
import { AppState } from './types';
|
||||
|
||||
export const appState: AppState = {
|
||||
gameboard: {
|
||||
nobles: new Array<NobleData>,
|
||||
cardRows: {
|
||||
tierOne: new Array<CardData>,
|
||||
tierTwo: new Array<CardData>,
|
||||
tierThree: new Array<CardData>,
|
||||
},
|
||||
tradingResources: {
|
||||
ruby: 7,
|
||||
sapphire: 7,
|
||||
emerald: 7,
|
||||
diamond: 7,
|
||||
onyx: 7,
|
||||
gold: 5
|
||||
},
|
||||
deck: CardDeck,
|
||||
},
|
||||
round: 0,
|
||||
players: new Array<PlayerData>,
|
||||
}
|
||||
|
||||
export const Context = createContext(appState);
|
||||
16
src/context/types.d.ts
vendored
Normal file
16
src/context/types.d.ts
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { CardData, FullDeck, NobleData, PlayerData, ResourceCost } from "../util/types"
|
||||
|
||||
export interface AppState {
|
||||
gameboard: {
|
||||
nobles: Array<NobleData>,
|
||||
cardRows: {
|
||||
tierOne: Array<CardData>
|
||||
tierTwo: Array<CardData>
|
||||
tierThree: Array<CardData>
|
||||
},
|
||||
tradingResources: ResourceCost
|
||||
deck: FullDeck,
|
||||
},
|
||||
round: number,
|
||||
players: Array<PlayerData>
|
||||
}
|
||||
70
src/util/GameConstructor.tsx
Normal file
70
src/util/GameConstructor.tsx
Normal file
@@ -0,0 +1,70 @@
|
||||
import { useContext, useState } from "react"
|
||||
import { useNavigate } from "react-router-dom"
|
||||
import { Context } from "../context/Context";
|
||||
import { CardData, NobleData, PlayerData } from "./types";
|
||||
|
||||
export default function GameConstructor() {
|
||||
const AppContext = useContext(Context);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [input, setInput] = useState({
|
||||
playerOne: '',
|
||||
playerTwo: '',
|
||||
playerThree: '',
|
||||
playerFour: '',
|
||||
})
|
||||
|
||||
const newGame = () => {
|
||||
if (!input.playerOne || !input.playerTwo) return;
|
||||
if (input.playerFour && !input.playerThree) return;
|
||||
|
||||
const newPlayers = Object.values(input).map((name: string): PlayerData => {
|
||||
return {
|
||||
name: name,
|
||||
starter: false,
|
||||
points: 0,
|
||||
nobles: new Array<NobleData>,
|
||||
cards: new Array<CardData>,
|
||||
inventory: {
|
||||
ruby: 0,
|
||||
sapphire: 0,
|
||||
emerald: 0,
|
||||
diamond: 0,
|
||||
onyx: 0,
|
||||
gold: 0
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
for (let player of newPlayers) {
|
||||
if (!player.name) newPlayers.splice(newPlayers.indexOf(player));
|
||||
}
|
||||
|
||||
AppContext.players = newPlayers;
|
||||
|
||||
console.log(AppContext)
|
||||
navigate('/game');
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="game-constructor App">
|
||||
<h1>Configure a new game:</h1>
|
||||
|
||||
<div>
|
||||
<label htmlFor="P1-NAME">Player 1 Name:</label>
|
||||
<input type="text" id="P1-NAME" required onChange={(e) => setInput({ ...input, playerOne: e.target.value})}></input>
|
||||
<label htmlFor="P2-NAME">Player 2 Name:</label>
|
||||
<input type="text" id="P2-NAME" required onChange={(e) => setInput({ ...input, playerTwo: e.target.value})}></input>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="P3-NAME">Player 3 Name:</label>
|
||||
<input type="text" id="P3-NAME" onChange={(e) => setInput({ ...input, playerThree: e.target.value})}></input>
|
||||
<label htmlFor="P4-NAME">Player 4 Name:</label>
|
||||
<input type="text" id="P4-NAME" onChange={(e) => setInput({ ...input, playerFour: e.target.value})}></input>
|
||||
</div>
|
||||
|
||||
<button onClick={newGame}>Start Game</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
0
src/util/types.ts → src/util/types.d.ts
vendored
0
src/util/types.ts → src/util/types.d.ts
vendored
Reference in New Issue
Block a user