diff --git a/src/App.tsx b/src/App.tsx index 34eb7ba..8507581 100755 --- a/src/App.tsx +++ b/src/App.tsx @@ -11,6 +11,8 @@ import {SERVER_BASE_NAME} from "./index"; interface AppState { userContext: IUserContext; localeContext: ILocaleContext; + loading: boolean; + majorFailure: boolean; } interface AppProps {} @@ -40,6 +42,8 @@ class App extends React.Component { }; this.state = { + majorFailure: false, + loading: true, userContext: { username: "", loggedIn: false, @@ -54,20 +58,35 @@ class App extends React.Component { } componentDidMount(): void { - axios.get("/api/user", {baseURL: SERVER_BASE_NAME}) - .then((res) => { - const data = res.data as any; - this.updateUserContext(data.username, true); - this.changeLang(data.lang); - }) - .catch(err => console.log(err)); + this.loadUserData(); + } + + async loadUserData(): Promise { + try { + const response = (await axios.get("/api/user", {baseURL: SERVER_BASE_NAME})).data; + this.updateUserContext(response.username, true); + this.changeLang(response.lang); + } + catch (e) { + this.handleNoUserData(); + } + finally { + this.setState({loading: false}); + } + } + + handleNoUserData(): void { + this.setState({majorFailure: true}); } render(): ReactNode { return ( - + ); diff --git a/src/Components/Game.tsx b/src/Components/Game.tsx index 7494ae6..b80c26a 100755 --- a/src/Components/Game.tsx +++ b/src/Components/Game.tsx @@ -5,6 +5,7 @@ import GameSetup, {GameSettings} from "./GameSetup" import Settings from "../static/settings.json"; import {SERVER_BASE_NAME} from "../index"; import axios from "axios"; +import {Ruleset} from "../static/rulesets"; export interface Player { id: string; @@ -17,13 +18,15 @@ interface GameState { loading: boolean; availablePlayers: Player[] debug: boolean; + availableRulesets: Ruleset[]; } -interface GameProps {} +interface GameProps { + loading: boolean; + majorFailure: boolean; +} class Game extends React.Component { - state: GameState; - constructor(props: GameProps) { super(props); @@ -38,15 +41,25 @@ class Game extends React.Component { loading: true, availablePlayers: [], debug: Settings.debug, + availableRulesets: [], }; } componentDidMount(): void { - axios.get(SERVER_BASE_NAME + "/api/players") - .then(response => this.addNewPlayers([...response.data.guests, response.data.mainPlayer])) - .catch(error => this.handleError(error)) - .finally(() => this.setState({ loading: false })); - console.log(this.state.availablePlayers); + this.loadData(); + } + + async loadData(): Promise { + try { + await this.loadAllPlayers(); + await this.loadAllRulesets(); + } + catch (e) { + this.handleRequestError(e); + } + finally { + this.setState({loading: false}); + } } addNewPlayers(players: Player[]): void { @@ -55,8 +68,8 @@ class Game extends React.Component { this.setState({availablePlayers}); } - handleError(error: any): void { - + handleRequestError(error: any): void { + console.log(error); }; onSetupComplete: (gameSettings: GameSettings) => void = (gameSettings) => { @@ -66,29 +79,48 @@ class Game extends React.Component { }); }; - returnToSetup: () => void = () => { + returnToSetup(): void { this.setState({settingUp: true}); }; + async loadAllRulesets(): Promise { + const rulesetsSlug = (await axios.get(SERVER_BASE_NAME + "/api/rulesets/")).data; + this.setState({availableRulesets: rulesetsSlug.rulesets as Ruleset[]}); + } + + async loadAllPlayers(): Promise { + const response = (await axios.get(SERVER_BASE_NAME + "/api/players")).data; + this.addNewPlayers([...response.guests, response.mainPlayer]) + } + + selectedRuleset(): Ruleset { + return this.state.availableRulesets.find( + ruleset => ruleset.id === this.state.currentSettings.ruleset) as Ruleset; + } + render(): ReactNode { return ( <> - {!this.state.loading && (this.state.settingUp ? + {this.state.settingUp || this.state.loading || this.props.loading ? ( this.onSetupComplete(s)} settings={this.state.currentSettings} availablePlayers={this.state.availablePlayers} + availableRulesets={this.state.availableRulesets} /> ) : ( this.returnToSetup()} /> ) - )} + } ); } diff --git a/src/Components/GameSetup.tsx b/src/Components/GameSetup.tsx index 163c66f..acb67c7 100755 --- a/src/Components/GameSetup.tsx +++ b/src/Components/GameSetup.tsx @@ -1,13 +1,16 @@ import React, {ChangeEvent, FocusEvent, KeyboardEvent, ReactNode} from "react"; -import {getSchemaListings, SchemaListing} from "../static/rulesets"; +import {Ruleset} from "../static/rulesets"; import LocaleContext from "../LocaleContext"; import {Button} from "semantic-ui-react"; import {Player} from "./Game"; interface GameSetupProps { + loading: boolean; onSetupComplete: (settings: GameSettings) => void; settings: GameSettings; availablePlayers: Player[]; + availableRulesets: Ruleset[]; + majorFailure: boolean; } interface GameSetupState { @@ -22,13 +25,9 @@ export interface GameSettings { } class GameSetup extends React.Component { - private readonly availableRulesets: SchemaListing[]; private changeLang: (lang: string) => void; - state: GameSetupState; constructor(props: GameSetupProps) { super(props); - - this.availableRulesets = getSchemaListings(); this.changeLang = () => {}; this.state = { selectedRuleset: this.props.settings.ruleset, @@ -66,7 +65,7 @@ class GameSetup extends React.Component { return this.props.availablePlayers.find(player => player.nick === playerName)?.id; } - playerIsNew(player: Player) { + playerIsNew(player: Player): boolean { return player.id === player.nick; } @@ -81,7 +80,7 @@ class GameSetup extends React.Component { const Locale = this.context.strings; const rulesetOptions: ReactNode[] = []; - for (const rulesetListing of this.availableRulesets) { + for (const rulesetListing of this.props.availableRulesets) { let className = "option"; if (this.state.selectedRuleset === rulesetListing.id) { className += " selected"; @@ -122,36 +121,61 @@ class GameSetup extends React.Component {
-
-
- - {Locale.setupScreen.players} - + {this.props.majorFailure && ( +
+
+ + An Error Occurred + +
+
+ The necessary data couldn't be loaded to play. Try reloading the page. +
-
- {playerListing} + )} + {this.props.loading && ( +
+
+ + Loading... + +
-
-
-
- - {Locale.setupScreen.selectRuleset} - -
-
- {rulesetOptions} -
-
-
- -
+ )} + {!this.props.loading && !this.props.majorFailure && ( + <> +
+
+ + {Locale.setupScreen.players} + +
+
+ {playerListing} +
+
+
+
+ + {Locale.setupScreen.selectRuleset} + +
+
+ {rulesetOptions} +
+
+
+ +
+ + )}
@@ -233,24 +257,22 @@ const ActivePlayerListItem: React.FunctionComponent = const {removePlayer, playerName, playerIsNew} = props; const Locale = React.useContext(LocaleContext).strings; return ( - <> -
-
- {playerName} - {playerIsNew && - - {Locale.setupScreen.playerNew} - - } -
-
+
+
+ {playerName} + {playerIsNew && ( + + {Locale.setupScreen.playerNew} + + )}
- +
+
); }; diff --git a/src/Components/KadiBoard.tsx b/src/Components/KadiBoard.tsx index 38dc18a..049444e 100755 --- a/src/Components/KadiBoard.tsx +++ b/src/Components/KadiBoard.tsx @@ -38,6 +38,7 @@ export interface KadiBoardProps { settings: GameSettings; returnToSetup: () => void; debug: boolean; + gameSchema: Ruleset; } interface KadiBoardState { @@ -57,12 +58,11 @@ interface ScoreSheet { class KadiBoard extends React.Component { private readonly gameSchema: Ruleset; private readonly caretaker: CaretakerSet; - state: KadiBoardState; constructor(props: KadiBoardProps) { super(props); - this.gameSchema = getGameSchemaById(this.props.settings.ruleset); + this.gameSchema = this.props.gameSchema; this.state = { scoreSheet: this.generateNewScoreSheet(this.props.settings.players), @@ -166,25 +166,22 @@ class KadiBoard extends React.Component { } private saveGame: () => void = async () => { - this.setState({savingGame: true}, () => { - axios.post(SERVER_BASE_NAME + "/api/games", - this.getJSONRepresentationForBoard(), - {headers: {"Content-Type": "application/json"}} - ) - .then(response => this.onGameSave(response.data)) - .catch(error => this.onSaveError(error)) - .finally(() => this.setState({ savingGame: false })); + console.log(this.getJSONRepresentationForBoard()); + this.setState({savingGame: true}, async () => { + try { + const response = await axios.post(SERVER_BASE_NAME + "/api/games", + this.getJSONRepresentationForBoard(), {headers: {"Content-Type": "application/json"}}); + this.setState({locked: true, saved: true}); + } + catch (e) { + console.log("Error saving:", e); + } + finally { + this.setState({ savingGame: false }); + } }); }; - private onGameSave = (serverResponse: string) => { - this.setState({locked: true, saved: true}); - }; - - private onSaveError = (error: any) => { - console.log("Error saving:", error); - }; - private fillOutRandomly(): void { for (const player of this.state.players) { for (const blockId in this.gameSchema.blocks) { diff --git a/src/static/rulesets.ts b/src/static/rulesets.ts index 1547ddc..5cf6b32 100755 --- a/src/static/rulesets.ts +++ b/src/static/rulesets.ts @@ -192,13 +192,4 @@ export function getGameSchemaById(schemaId: string): Ruleset { } } throw new RangeError("No such GameSchema with id '" + schemaId + "'!"); -} - -export interface SchemaListing { - id: string; - label: string; -} - -export function getSchemaListings(): SchemaListing[] { - return gameSchemas.map((s) => ({ id: s.id, label: s.label })); -} +} \ No newline at end of file