Profile page shows guests and lets you delete them. History page shows times in the appropriate format. IntlDatetime set up for each locale.
This commit is contained in:
11
src/App.tsx
11
src/App.tsx
@@ -1,8 +1,8 @@
|
||||
import React, {ReactNode} from "react";
|
||||
import {BrowserRouter as Router, Link, Route} from "react-router-dom";
|
||||
import {Redirect, Switch} from "react-router";
|
||||
import {BrowserRouter as Router, Route} from "react-router-dom";
|
||||
import {Redirect} from "react-router";
|
||||
import {IntlStrings} from "./static/strings";
|
||||
import {PageId, SupportedLang} from "./enums";
|
||||
import {PageId, SupportedLang, supportedLangToIntlDTF} from "./enums";
|
||||
import {pageComponentFromId} from "./pageListings";
|
||||
import KadiPage from "./Components/KadiPage";
|
||||
import HomePage from "./Components/HomePage";
|
||||
@@ -27,6 +27,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
username: username,
|
||||
loggedIn: loggedIn,
|
||||
updateUserContext: this.updateUserContext,
|
||||
dateTimeFormatter: this.state.userContext.dateTimeFormatter,
|
||||
currentLang: this.state.userContext.currentLang,
|
||||
strings: this.state.userContext.strings,
|
||||
changeLang: this.state.userContext.changeLang,
|
||||
@@ -35,6 +36,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
|
||||
this.changeLang = (lang: SupportedLang, submit=true) => {
|
||||
this.setState({userContext: {
|
||||
dateTimeFormatter: supportedLangToIntlDTF[lang],
|
||||
strings: IntlStrings[lang],
|
||||
currentLang: lang,
|
||||
changeLang: this.changeLang,
|
||||
@@ -52,6 +54,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
username: "",
|
||||
loggedIn: false,
|
||||
updateUserContext: this.updateUserContext,
|
||||
dateTimeFormatter: supportedLangToIntlDTF[SupportedLang.gb],
|
||||
currentLang: SupportedLang.gb,
|
||||
strings: IntlStrings[SupportedLang.gb],
|
||||
changeLang: this.changeLang,
|
||||
@@ -76,7 +79,7 @@ class App extends React.Component<AppProps, AppState> {
|
||||
}
|
||||
|
||||
submitLanguagePreference(lang: SupportedLang) {
|
||||
axios.post(SERVER_BASE_NAME + "/api/changeLang",
|
||||
axios.put(SERVER_BASE_NAME + "/api/lang",
|
||||
{lang: lang},
|
||||
{headers: {"Content-Type": "application/json"}}
|
||||
);
|
||||
|
||||
31
src/Components/GamesList.tsx
Normal file
31
src/Components/GamesList.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import {List, ListItem} from "semantic-ui-react";
|
||||
import React from "react";
|
||||
import UserContext from "../Contexts/UserContext";
|
||||
|
||||
interface GamesListProps {
|
||||
loading: boolean;
|
||||
gamesList: any[];
|
||||
}
|
||||
|
||||
const GamesList: React.FunctionComponent<GamesListProps> = (props) => {
|
||||
const {loading, gamesList} = props;
|
||||
const Uctx = React.useContext(UserContext);
|
||||
const listItems = gamesList.map(listing =>
|
||||
<ListItem key={listing.createdAt}>
|
||||
Game played on: {Uctx.dateTimeFormatter.format(new Date(listing.createdAt))}
|
||||
</ListItem>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
{loading ? (
|
||||
<p>{Uctx.strings.historyPage.loading}</p>
|
||||
) : (
|
||||
<List bulleted={true}>
|
||||
{listItems}
|
||||
</List>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GamesList;
|
||||
39
src/Components/GuestList.tsx
Normal file
39
src/Components/GuestList.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import {Header, List, ListItem} from "semantic-ui-react";
|
||||
import React from "react";
|
||||
import UserContext from "../Contexts/UserContext";
|
||||
import {Guest} from "./ProfilePage";
|
||||
import HeaderSubHeader from "semantic-ui-react/dist/commonjs/elements/Header/HeaderSubheader";
|
||||
import {SERVER_BASE_NAME} from "../index";
|
||||
|
||||
|
||||
interface GuestListProps {
|
||||
loading: boolean;
|
||||
guestList: Guest[];
|
||||
deleteGuest: (id: string) => any;
|
||||
}
|
||||
|
||||
const GuestList: React.FunctionComponent<GuestListProps> = (props) => {
|
||||
const {loading, guestList, deleteGuest} = props;
|
||||
const Uctx = React.useContext(UserContext);
|
||||
const listItems = guestList.map(guest =>
|
||||
<ListItem key={guest.id}>
|
||||
{guest.nick} - <a onClick={() => deleteGuest(guest.id)}>{Uctx.strings.general.deleteCommand}</a>
|
||||
</ListItem>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<Header size={"medium"}>
|
||||
{Uctx.strings.profilePage.guestsHeader}
|
||||
</Header>
|
||||
{loading ? (
|
||||
<p>{Uctx.strings.profilePage.loadingGuests}</p>
|
||||
) : (
|
||||
<List bulleted={true}>
|
||||
{listItems}
|
||||
</List>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GuestList;
|
||||
@@ -3,6 +3,7 @@ import {Header, List, ListItem} from "semantic-ui-react";
|
||||
import axios from "axios";
|
||||
import {SERVER_BASE_NAME} from "../index";
|
||||
import UserContext from "../Contexts/UserContext";
|
||||
import GamesList from "./GamesList";
|
||||
|
||||
interface HistoryPageProps {
|
||||
}
|
||||
@@ -27,11 +28,9 @@ class HistoryPage extends React.Component<HistoryPageProps, HistoryPageState> {
|
||||
.then(response => this.setState({gameListings: response.data.games}))
|
||||
.catch(error => this.handleError(error))
|
||||
.finally(() => this.setState({ loadingGames: false }));
|
||||
console.log(this.state.gameListings);
|
||||
}
|
||||
|
||||
handleError = (error: any) => void {
|
||||
|
||||
};
|
||||
|
||||
render(): ReactElement {
|
||||
@@ -41,22 +40,10 @@ class HistoryPage extends React.Component<HistoryPageProps, HistoryPageState> {
|
||||
<Header size={"huge"}>
|
||||
{Locale.historyPage.title}
|
||||
</Header>
|
||||
{
|
||||
this.state.loadingGames ? (
|
||||
<p>
|
||||
Loading games...
|
||||
</p>
|
||||
) :
|
||||
(
|
||||
<List bulleted={true}>
|
||||
{
|
||||
this.state.gameListings.map(listing => {
|
||||
return <ListItem key={listing.createdAt}>Game played on: {listing.createdAt}</ListItem>;
|
||||
})
|
||||
}
|
||||
</List>
|
||||
)
|
||||
}
|
||||
<GamesList
|
||||
loading={this.state.loadingGames}
|
||||
gamesList={this.state.gameListings}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
import React, {ReactElement} from "react";
|
||||
import {Header} from "semantic-ui-react";
|
||||
import UserContext from "../Contexts/UserContext";
|
||||
import axios from "axios";
|
||||
import {SERVER_BASE_NAME} from "../index";
|
||||
import GuestList from "./GuestList";
|
||||
|
||||
interface ProfilePageProps {}
|
||||
|
||||
interface ProfilePageState {
|
||||
loadingGuests: boolean;
|
||||
guests: Guest[];
|
||||
}
|
||||
|
||||
export interface Guest {
|
||||
id: string;
|
||||
nick: string;
|
||||
}
|
||||
|
||||
class ProfilePage extends React.Component<ProfilePageProps, ProfilePageState> {
|
||||
@@ -12,15 +22,48 @@ class ProfilePage extends React.Component<ProfilePageProps, ProfilePageState> {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
loadingGuests: false,
|
||||
guests: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
this.loadGuests();
|
||||
}
|
||||
|
||||
loadGuests(): void {
|
||||
this.setState({loadingGuests: true}, () => {
|
||||
axios.get(SERVER_BASE_NAME + "/api/guests")
|
||||
.then(response => this.setState({guests: response.data.guests}))
|
||||
.catch(error => this.handleError(error))
|
||||
.finally(() => this.setState({ loadingGuests: false }));
|
||||
});
|
||||
}
|
||||
|
||||
deleteGuest(id: string): void {
|
||||
console.log("delete with url", SERVER_BASE_NAME + "/api/guest/" + id);
|
||||
axios.delete(SERVER_BASE_NAME + "/api/guest/" + id)
|
||||
.then(response => this.loadGuests())
|
||||
.catch(error => this.handleError(error))
|
||||
}
|
||||
|
||||
handleError(error: any): void {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
render(): ReactElement {
|
||||
const Locale = this.context.strings;
|
||||
return (
|
||||
<Header size={"huge"}>
|
||||
{Locale.profilePage.title}
|
||||
</Header>
|
||||
<>
|
||||
<Header size={"huge"}>
|
||||
{Locale.profilePage.title}
|
||||
</Header>
|
||||
<GuestList
|
||||
deleteGuest={(id) => this.deleteGuest(id)}
|
||||
loading={this.state.loadingGuests}
|
||||
guestList={this.state.guests}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import React from "react";
|
||||
import {SupportedLang} from "../enums";
|
||||
import {supportedLangToIntlDTF, SupportedLang} from "../enums";
|
||||
import {IntlStrings} from "../static/strings";
|
||||
|
||||
export interface IUserContext {
|
||||
username: string;
|
||||
loggedIn: boolean;
|
||||
updateUserContext: (username: string, loggedIn: boolean) => void;
|
||||
dateTimeFormatter: Intl.DateTimeFormat;
|
||||
currentLang: SupportedLang;
|
||||
strings: any;
|
||||
changeLang: (lang: SupportedLang, submit?: boolean) => void;
|
||||
@@ -15,6 +16,7 @@ const userDefaultVal = {
|
||||
loggedIn: false,
|
||||
username: "",
|
||||
updateUserContext: () => {},
|
||||
dateTimeFormatter: supportedLangToIntlDTF[SupportedLang.gb],
|
||||
currentLang: SupportedLang.gb,
|
||||
strings: IntlStrings[SupportedLang.gb as SupportedLang],
|
||||
changeLang: () => {},
|
||||
|
||||
@@ -11,4 +11,10 @@ export enum PageId {
|
||||
stats = "stats",
|
||||
home = "home",
|
||||
history = "history",
|
||||
}
|
||||
}
|
||||
|
||||
export const supportedLangToIntlDTF: Record<SupportedLang, Intl.DateTimeFormat> = {
|
||||
gb: Intl.DateTimeFormat('en-AU'),
|
||||
de: Intl.DateTimeFormat('de-DE'),
|
||||
it: Intl.DateTimeFormat('it-IT'),
|
||||
};
|
||||
0
src/filetypes.d.ts
vendored
Executable file → Normal file
0
src/filetypes.d.ts
vendored
Executable file → Normal file
@@ -3,8 +3,7 @@ import ReactDOM from "react-dom";
|
||||
import "semantic-ui-css/semantic.min.css";
|
||||
import App from "./App";
|
||||
import * as serviceWorker from "./serviceWorker";
|
||||
|
||||
export const SERVER_BASE_NAME = "/kadi";
|
||||
export {homepage as SERVER_BASE_NAME} from "../package.json";
|
||||
|
||||
ReactDOM.render((
|
||||
<React.StrictMode>
|
||||
|
||||
@@ -28,6 +28,9 @@ export const LanguageNames: Record<SupportedLang, string> = {
|
||||
|
||||
export const IntlStrings = {
|
||||
gb: {
|
||||
general: {
|
||||
deleteCommand: "Delete",
|
||||
},
|
||||
menu: {
|
||||
profileTab: "Profile",
|
||||
statsTab: "Stats",
|
||||
@@ -44,6 +47,8 @@ export const IntlStrings = {
|
||||
},
|
||||
profilePage: {
|
||||
title: "Profile",
|
||||
guestsHeader: "Guests",
|
||||
loadingGuests: "Loading guests..."
|
||||
},
|
||||
statsPage: {
|
||||
title: "Stats",
|
||||
@@ -56,9 +61,13 @@ export const IntlStrings = {
|
||||
},
|
||||
historyPage: {
|
||||
title: "History",
|
||||
loading: "Loading games...",
|
||||
},
|
||||
},
|
||||
de: {
|
||||
general: {
|
||||
deleteCommand: "Löschen",
|
||||
},
|
||||
menu: {
|
||||
profileTab: "Profil",
|
||||
statsTab: "Statistiken",
|
||||
@@ -75,6 +84,8 @@ export const IntlStrings = {
|
||||
},
|
||||
profilePage: {
|
||||
title: "Profil",
|
||||
guestsHeader: "Gäste",
|
||||
loadingGuests: "Gäste werden geladen...",
|
||||
},
|
||||
statsPage: {
|
||||
title: "Statistiken",
|
||||
@@ -87,9 +98,13 @@ export const IntlStrings = {
|
||||
},
|
||||
historyPage: {
|
||||
title: "Spielverlauf",
|
||||
loading: "Spielverlauf wird geladen...",
|
||||
},
|
||||
},
|
||||
it: {
|
||||
general: {
|
||||
deleteCommand: "Cancella",
|
||||
},
|
||||
menu: {
|
||||
profileTab: "Profilo",
|
||||
statsTab: "Statistiche",
|
||||
@@ -106,6 +121,8 @@ export const IntlStrings = {
|
||||
},
|
||||
profilePage: {
|
||||
title: "Profilo",
|
||||
guestsHeader: "===TRANSLATE ME===",
|
||||
loadingGuests: "===TRANSLATE ME===",
|
||||
},
|
||||
statsPage: {
|
||||
title: "Statistiche",
|
||||
@@ -118,6 +135,7 @@ export const IntlStrings = {
|
||||
},
|
||||
historyPage: {
|
||||
title: "Storia",
|
||||
loading: "Caricando storia giochi..."
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
Reference in New Issue
Block a user