State Management, Simplifying Some Components #1
34
src/App.tsx
34
src/App.tsx
@@ -1,45 +1,21 @@
|
||||
import { BrowserRouter, Routes, Route } from 'react-router-dom'
|
||||
import { useState } from 'react'
|
||||
import { BrowserRouter, Routes, Route } from 'react-router-dom'
|
||||
import Gameboard from './components/Gameboard/Gameboard'
|
||||
import GameConstructor from './util/GameConstructor';
|
||||
import { PlayerData, NobleData, CardData } from './util/types';
|
||||
import CardDeck from './data/cards.json';
|
||||
import { initialState } from './util/initialState';
|
||||
import './App.css'
|
||||
|
||||
function App() {
|
||||
const [state, setState] = useState({
|
||||
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: 1,
|
||||
players: new Array<PlayerData>,
|
||||
actions: {
|
||||
buyCard: { active: false },
|
||||
getChips: { active: false },
|
||||
reserveCard: { active: false }
|
||||
}
|
||||
})
|
||||
const [state, setState] = useState(initialState);
|
||||
|
||||
return (
|
||||
<div className="App">
|
||||
<h1>SPLENDOR</h1>
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
{/* @ts-ignore */}
|
||||
<Route path="/" element={<GameConstructor state={state} setState={setState} />} />
|
||||
{/* @ts-ignore */}
|
||||
<Route path="/game" element={<Gameboard state={state} setState={setState} />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { AppState, ResourceCost, StateProps } from '../../util/types';
|
||||
import { AppState, PlayerData, ResourceCost, SetActionType, StateProps } from '../../util/types';
|
||||
import initializeBoard from '../../util/initializeBoard';
|
||||
import AvailableChips from '../Resources/AvailableChips';
|
||||
import AllPlayers from '../Player/AllPlayers';
|
||||
@@ -8,9 +8,8 @@ import Nobles from './Nobles';
|
||||
|
||||
export default function Gameboard({ state, setState }: StateProps) {
|
||||
const [view, setView] = useState(<p>Loading...</p>);
|
||||
const [selection, setSelection] = useState<string>();
|
||||
|
||||
// callback for lifting state
|
||||
// callbacks for lifting state
|
||||
const liftSelection = useCallback((value: keyof ResourceCost) => {
|
||||
console.log(value)
|
||||
|
||||
@@ -35,6 +34,11 @@ export default function Gameboard({ state, setState }: StateProps) {
|
||||
console.log(state);
|
||||
}, []);
|
||||
|
||||
const setActionState = useCallback((value: SetActionType, player: PlayerData) => {
|
||||
if (!player?.turnActive) return;
|
||||
console.log(player.name + SetActionType[value]);
|
||||
}, []);
|
||||
|
||||
// util functions to set up initial board
|
||||
useEffect(() => {
|
||||
initializeBoard(state, setState);
|
||||
@@ -58,7 +62,8 @@ export default function Gameboard({ state, setState }: StateProps) {
|
||||
<CardRow tier={2} cards={state.gameboard.cardRows.tierTwo} />
|
||||
<CardRow tier={1} cards={state.gameboard.cardRows.tierOne} />
|
||||
<AvailableChips state={state} setState={setState} liftSelection={liftSelection} />
|
||||
<AllPlayers state={state} setState={setState} />
|
||||
{/* @ts-ignore */}
|
||||
<AllPlayers state={state} setState={setState} setActionState={setActionState} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
31
src/components/Player/ActionMethods.ts
Normal file
31
src/components/Player/ActionMethods.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { AppState, PlayerData, ResourceCost, setStateType } from "../../util/types";
|
||||
import { TurnOrderUtil } from "../../util/TurnOrderUtil";
|
||||
|
||||
export const getChips = (resource: string, dynamic: PlayerData | undefined, setState: setStateType) => {
|
||||
if (!dynamic || !dynamic?.turnActive) return;
|
||||
|
||||
setState((prev: AppState) => {
|
||||
const { newPlayers, roundIncrement } = TurnOrderUtil(prev, dynamic);
|
||||
|
||||
return {
|
||||
...prev,
|
||||
round: (roundIncrement ? prev.round + 1 : prev.round),
|
||||
gameboard: {
|
||||
...prev.gameboard,
|
||||
tradingResources: {
|
||||
...prev.gameboard.tradingResources,
|
||||
[resource as keyof ResourceCost]: prev.gameboard.tradingResources[resource as keyof ResourceCost] -= 1
|
||||
}
|
||||
},
|
||||
players: newPlayers
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const buyCard = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
export const reserveCard = () => {
|
||||
return;
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
import Player from "./Player";
|
||||
import { v4 } from "uuid";
|
||||
import "./AllPlayers.css"
|
||||
import { PlayerData, StateProps } from "../../util/types";
|
||||
import { PlayerData, SetActionType, StateProps } from "../../util/types";
|
||||
|
||||
export default function AllPlayers({ state, setState }: StateProps) {
|
||||
interface AllPlayersProps extends StateProps {
|
||||
setActionState: (value: SetActionType, player?: PlayerData) => void
|
||||
}
|
||||
|
||||
export default function AllPlayers({ state, setState, setActionState }: AllPlayersProps) {
|
||||
return (
|
||||
<div className="all-players">
|
||||
{
|
||||
state.players?.map((player: PlayerData) => <Player key={v4()} player={player} state={state} setState={setState} />)
|
||||
state.players?.map((player: PlayerData) => <Player key={v4()} player={player} state={state} setState={setState} setActionState={setActionState} />)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,38 +1,31 @@
|
||||
import { AppState, PlayerData, ResourceCost, StateProps } from "../../util/types"
|
||||
import { v4 } from "uuid";
|
||||
import { PlayerData, SetActionType, StateProps } from "../../util/types"
|
||||
import { useEffect, useState } from "react";
|
||||
import { TurnOrderUtil } from "../../util/TurnOrderUtil";
|
||||
import { getChips } from "./ActionMethods";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
interface PlayerProps extends StateProps {
|
||||
player: PlayerData
|
||||
player: PlayerData,
|
||||
setActionState: (value: SetActionType, player?: PlayerData) => void
|
||||
}
|
||||
|
||||
export default function Player({ player, state, setState }: PlayerProps) {
|
||||
export default function Player({ player, state, setState, setActionState }: PlayerProps) {
|
||||
const [dynamic, setDynamic] = useState<PlayerData>();
|
||||
|
||||
useEffect(() => {
|
||||
setDynamic(state.players.find((element: PlayerData) => element.id === player.id));
|
||||
}, [state]);
|
||||
useEffect(() => setDynamic(state.players.find((element: PlayerData) => element.id === player.id)), [state]);
|
||||
|
||||
const getChips = (resource: string) => {
|
||||
if (!dynamic?.turnActive) return;
|
||||
|
||||
setState((prev: AppState) => {
|
||||
const { newPlayers, roundIncrement } = TurnOrderUtil(prev, dynamic);
|
||||
|
||||
return {
|
||||
...prev,
|
||||
round: (roundIncrement ? prev.round + 1 : prev.round),
|
||||
gameboard: {
|
||||
...prev.gameboard,
|
||||
tradingResources: {
|
||||
...prev.gameboard.tradingResources,
|
||||
[resource as keyof ResourceCost]: prev.gameboard.tradingResources[resource as keyof ResourceCost] -= 1
|
||||
}
|
||||
},
|
||||
players: newPlayers
|
||||
}
|
||||
})
|
||||
const handleSelection = (input: number) => {
|
||||
switch (input) {
|
||||
case 0:
|
||||
setActionState(SetActionType.GETCHIPS, player);
|
||||
getChips('ruby', dynamic, setState);
|
||||
break;
|
||||
case 1:
|
||||
setActionState(SetActionType.BUYCARD, player);
|
||||
break;
|
||||
default:
|
||||
setActionState(SetActionType.AWAIT, player);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -44,7 +37,9 @@ export default function Player({ player, state, setState }: PlayerProps) {
|
||||
|
||||
{/* Dynamic data from state */}
|
||||
<p>{dynamic?.turnActive ? "My turn!" : "..."}</p>
|
||||
<button onClick={() => getChips('ruby')}>Get Chips</button>
|
||||
<button onClick={() => handleSelection(0)}>Get Chips</button>
|
||||
<button onClick={() => handleSelection(1)}>Buy Card</button>
|
||||
<button onClick={() => handleSelection(2)}>Reserve Card</button>
|
||||
<div className="player-cards"></div>
|
||||
<div className="player-resources"></div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ResourceCost, StateProps } from "../../util/types";
|
||||
import { useEffect } from "react";
|
||||
import { v4 } from "uuid";
|
||||
import "./AvailableChips.css"
|
||||
import { useEffect } from "react";
|
||||
|
||||
interface ResourceProps extends StateProps {
|
||||
liftSelection: (value: keyof ResourceCost) => void
|
||||
@@ -19,7 +19,7 @@ export default function AvailableChips({ state, setState, liftSelection }: Resou
|
||||
return (
|
||||
<div key={v4()} className={`chips-${key}`}>
|
||||
<button key={v4()} value={key} onClick={() => liftSelection(key as keyof ResourceCost)}>
|
||||
{key}: {state.gameboard.tradingResources[key]}
|
||||
{key}: {state.gameboard.tradingResources[key as keyof ResourceCost]}
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
||||
29
src/util/initialState.ts
Normal file
29
src/util/initialState.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { CardData, NobleData, PlayerData } from "./types";
|
||||
import CardDeck from '../data/cards.json';
|
||||
|
||||
export const initialState = {
|
||||
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: 1,
|
||||
players: new Array<PlayerData>,
|
||||
actions: {
|
||||
buyCard: { active: false },
|
||||
getChips: { active: false },
|
||||
reserveCard: { active: false }
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Dispatch, SetStateAction } from "react";
|
||||
import { AppState, FullDeck, NobleData } from "./types";
|
||||
import { AppState, FullDeck, NobleData, setStateType } from "./types";
|
||||
import NobleStore from '../data/nobles.json';
|
||||
|
||||
const shuffleDeck = (state: AppState, setState: Dispatch<SetStateAction<AppState>>) => {
|
||||
const shuffleDeck = (state: AppState, setState: setStateType) => {
|
||||
if (!state.gameboard.deck) return;
|
||||
let newDeck: FullDeck = state.gameboard.deck;
|
||||
|
||||
@@ -18,7 +17,7 @@ const shuffleDeck = (state: AppState, setState: Dispatch<SetStateAction<AppState
|
||||
setState({ ...state, gameboard: { ...state.gameboard, deck: newDeck }})
|
||||
}
|
||||
|
||||
const setNobles = (state: AppState, setState: Dispatch<SetStateAction<AppState>>) => {
|
||||
const setNobles = (state: AppState, setState: setStateType) => {
|
||||
let newNobles = NobleStore.nobles;
|
||||
let shuffledNobles = new Array<NobleData>;
|
||||
|
||||
@@ -31,7 +30,7 @@ const setNobles = (state: AppState, setState: Dispatch<SetStateAction<AppState>>
|
||||
setState({ ...state, gameboard: { ...state.gameboard, nobles: shuffledNobles }})
|
||||
}
|
||||
|
||||
export default function initializeBoard(state: AppState, setState: Dispatch<SetStateAction<AppState>>) {
|
||||
export default function initializeBoard(state: AppState, setState: setStateType) {
|
||||
shuffleDeck(state, setState);
|
||||
|
||||
let newDeck = state.gameboard.cardRows;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Dispatch, SetStateAction } from "react"
|
||||
import { AppState } from "../context/types"
|
||||
|
||||
export interface AppState {
|
||||
gameboard: {
|
||||
@@ -18,29 +17,39 @@ export interface AppState {
|
||||
}
|
||||
|
||||
interface StateActions {
|
||||
setAction?: (arg: SetActionType) => void
|
||||
getChips: {
|
||||
active: boolean
|
||||
selection?: Array<keyof ResourceCost>
|
||||
valid?: boolean
|
||||
confirm: () => void
|
||||
confirm?: () => void
|
||||
}
|
||||
buyCard: {
|
||||
active: boolean
|
||||
selection?: CardData
|
||||
valid?: boolean
|
||||
confirm: () => void
|
||||
confirm?: () => void
|
||||
}
|
||||
reserveCard: {
|
||||
active: boolean
|
||||
selection?: CardData
|
||||
includeGold?: boolean
|
||||
confirm: () => void
|
||||
confirm?: () => void
|
||||
}
|
||||
}
|
||||
|
||||
export enum SetActionType {
|
||||
GETCHIPS,
|
||||
BUYCARD,
|
||||
RESERVECARD,
|
||||
AWAIT
|
||||
}
|
||||
|
||||
export type setStateType = Dispatch<SetStateAction<AppState>>
|
||||
|
||||
export interface StateProps {
|
||||
state: AppState,
|
||||
setState: Dispatch<SetStateAction<AppState>>
|
||||
setState: setStateType
|
||||
}
|
||||
|
||||
export interface GameInformation {
|
||||
@@ -98,4 +107,4 @@ export enum GemValue {
|
||||
diamond,
|
||||
onyx,
|
||||
gold,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user