feature(database-connection): Fix routing and refactor style sheets

This commit is contained in:
2021-01-12 11:49:08 +01:00
parent 29b6974714
commit 816d5df943
15 changed files with 251 additions and 119 deletions

View File

@@ -7,7 +7,8 @@
text-align: center;
height: 100vh;
color: whitesmoke;
background-color: #282c34; }
background-color: #282c34;
}
.first-place {
font-size: xx-large;

View File

@@ -1,4 +1,4 @@
.App {
@mixin background() {
width: auto;
display: flex;
flex-direction: column;
@@ -10,7 +10,7 @@
background-color: #282c34;
}
.blurred {
@mixin blurred() {
-webkit-filter: blur(5px);
-moz-filter: blur(5px);
-o-filter: blur(5px);

View File

@@ -1,4 +1,4 @@
import React from 'react';
import React, {FunctionComponent} from 'react';
import './App.scss';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';
@@ -8,7 +8,20 @@ import MainPage, {IMainPageProps} from "./pages/MainPage/MainPage";
library.add(faArrowCircleLeft, faArrowCircleRight)
export default class App extends React.Component {
const App: FunctionComponent = () => (
<Router>
<Switch>
{/*<Route exact path={'/'} component={(props: IMainPageProps) => (<MainPage {...props}/>)} />*/}
<Route exact path={'/'} to={'/season/1'} />
<Route path={'/season/:id'} component={(props: IMainPageProps) => (<MainPage {...props}/>)} />
</Switch>
</Router>
);
export default App;
// export default class App extends React.Component {
// componentDidMount() {
// this.setState({loading: false, mock: this.mockService.getStatsWithoutPromise()});
@@ -25,15 +38,3 @@ export default class App extends React.Component {
// }))
// });
// }
render() {
return (
<Router>
<Switch>
<Route exact path={'/'} component={(props: IMainPageProps) => (<MainPage {...props}/>)} />
<Route path={'/season/:id'} component={(props: IMainPageProps) => (<MainPage {...props}/>)} />
</Switch>
</Router>
);
}
}

View File

@@ -1,3 +1,4 @@
.Header {
.title {
font-size: 4vw;

View File

@@ -1 +1,4 @@
.SeasonDetail {}
.SeasonDetail {
vertical-align: middle;
justify-content: center;
}

View File

@@ -1,5 +1,6 @@
import React from 'react';
import './SeasonDetail.scss';
import {IUserListProperties} from "../UserList/UserList";
export interface SeasonDetailProperties {
seasonId: string,
@@ -9,10 +10,10 @@ export interface SeasonDetailProperties {
}
}
class SeasonDetail extends React.Component<SeasonDetailProperties> {
class SeasonDetail extends React.Component<IUserListProperties> {
render() {
const { seasonId, dates } = this.props
const { seasonId, dates } = this.props.userStats
return (
<span className="SeasonDetail" data-testid="SeasonDetail">
Season {seasonId} - Duration: {dates.start.toDateString()} - {dates.end.toDateString()}

View File

@@ -1 +1,13 @@
.SeasonSwitch {}
.SeasonSwitch {
a {
font-size: 3vw;
max-font-size: 4vw;
padding-left: 1em;
padding-right: 1em;
vertical-align: middle;
justify-content: center;
}
}

View File

@@ -2,22 +2,25 @@ import React from 'react';
import { Link } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import './SeasonSwitch.scss';
import SeasonDetail, { SeasonDetailProperties } from '../SeasonDetail/SeasonDetail';
import {withRouter} from "react-router";
import SeasonDetail from '../SeasonDetail/SeasonDetail';
import {IUserListProperties} from "../UserList/UserList";
class SeasonSwitch extends React.Component<SeasonDetailProperties> {
class SeasonSwitch extends React.Component<IUserListProperties> {
render() {
let seasonId = Number(this.props.seasonId)
let seasonId = Number(this.props.userStats.seasonId)
return(
<div className="SeasonSwitch" data-testid="SeasonSwitch">
<Link to={"/season/" + (seasonId - 1)}>
{
seasonId > 1
&& <Link to={"/season/" + (seasonId - 1)} onClick={() => this.props.onSeasonIdChange('' + (seasonId - 1))}>
<FontAwesomeIcon icon="arrow-circle-left" />
</Link>
}
<SeasonDetail {...this.props} />
<Link to={"/season/" + (seasonId + 1)}>
<Link to={"/season/" + (seasonId + 1)} onClick={() => this.props.onSeasonIdChange('' + (seasonId + 1))}>
<FontAwesomeIcon icon="arrow-circle-right" />
</Link>
</div>

View File

@@ -15,5 +15,9 @@
font-size: larger;
color: saddlebrown;
}
.SeasonSwitch {
padding-bottom: 1rem;
}
}

View File

@@ -15,7 +15,7 @@ export default class UserList extends React.Component<IUserListProperties, IUser
constructor(props: Readonly<IUserListProperties> | IUserListProperties) {
super(props);
this.state = { mocked: this.props.mocked }
// this.state = { mocked: this.props.mocked }
}
private createTableEntries(entries: TableEntry[]) {
@@ -51,7 +51,7 @@ export default class UserList extends React.Component<IUserListProperties, IUser
render() {
return (
<div className="UserList" data-testid="UserList">
<SeasonSwitch seasonId={this.props.userStats.seasonId} dates={this.props.userStats.dates} />
<SeasonSwitch onSeasonIdChange={this.props.onSeasonIdChange} userStats={this.props.userStats} />
<table>
<thead>
<tr>
@@ -70,9 +70,10 @@ export default class UserList extends React.Component<IUserListProperties, IUser
}
}
interface IUserListProperties {
export interface IUserListProperties {
userStats: UserStatsResponse
mocked: boolean
mocked?: boolean
onSeasonIdChange: any
}
interface IUserListState {

View File

@@ -1,8 +1,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import App from "./App";
ReactDOM.render(
<React.StrictMode>

View File

@@ -2,8 +2,8 @@ import TableEntry from "../models/TableEntry";
import UserStatsService from "../services/UserStatsService";
import UserStatsResponse from "../models/UserStatsResponse";
export default class UserStatsMockService extends UserStatsService {
private readonly mocks: UserStatsResponse[] = [
export default class UserStatsMockService {
private static readonly mocks: UserStatsResponse[] = [
{
seasonId: "1",
dates: {
@@ -36,11 +36,12 @@ export default class UserStatsMockService extends UserStatsService {
}
]
async getStats(seasonId: string): Promise<UserStatsResponse> {
static async getStats(seasonId: string): Promise<UserStatsResponse> {
return Promise.resolve(this.mocks[Number(seasonId) - 1])
}
getStatsWithoutPromise(seasonId: string): UserStatsResponse {
static getStatsWithoutPromise(seasonId: string): UserStatsResponse {
return this.mocks[Number(seasonId) - 1]
}
}

View File

@@ -1,3 +1,5 @@
.MainPage {
@import "src/App.scss";
.MainPage {
@include background();
}

View File

@@ -1,7 +1,5 @@
import React, {useEffect} from "react";
import UserStatsService from "../../services/UserStatsService";
import React, {FC, FunctionComponent, useCallback, useEffect, useState} from "react";
import UserStatsMockService from "../../mock/UserStatsMockService";
import {findDOMNode} from "react-dom";
import Header from "../../components/Header/Header";
import UserList from "../../components/UserList/UserList";
import ErrorContainer from "../../components/ErrorContainer/ErrorContainer";
@@ -9,77 +7,115 @@ import Footer from "../../components/Footer/Footer";
import {RouteComponentProps} from "react-router/index";
import UserStatsResponse from "../../models/UserStatsResponse";
import {withRouter} from "react-router";
import RequestError from "../../models/RequestError";
import './MainPage.scss';
class MainPage extends React.Component<IMainPageProps, IMainPageState> {
// class MainPage extends React.Component<IMainPageProps, IMainPageState> {
//
// private apiService: UserStatsService = new UserStatsService();
// private mockService = new UserStatsMockService();
//
// constructor(props: IMainPageProps) {
// super(props)
//
// console.log("this.props.match.params.id = " + this.props.match.params.id)
//
//
//
// let seasonId = !this.props.match.params.id ? "1" : this.props.match.params.id
//
// console.log("seasonId = " + seasonId)
//
// this.state = {
// id: seasonId,
// error: undefined,
// loading: false,
// users: this.mockService.getStatsWithoutPromise("1")
// }
// }
//
// componentWillMount() {
// this.fetchData();
// }
//
// componentDidUpdate(prevProps: Readonly<IMainPageProps>) {
// const element = findDOMNode(this);
// if (element != null) {
// window.scrollTo(0, 0);
// }
//
// if(prevProps.match.params.id !== this.props.match.params.id) {
// this.setState({ id: this.props.match.params.id })
// this.fetchData()
// }
// }
//
// private fetchData() {
// this.setState({ loading: true })
// // this.apiService.getStats(this.state.id)
// // .then(data => this.setState({
// // loading: false,
// // users: data
// // }))
// this.mockService.getStats(this.state.id)
// .then(data => this.setState({
// loading: false,
// users: data
// }))
// }
//
// render() {
// console.log("this.state.id = " + this.state.id)
// console.log("this.state.users.seasonId = " + this.state.users.seasonId)
//
// return (
// <div className="MainPage">
// <Header />
// {
// this.state.error && <ErrorContainer message={this.state.error} />
// }
// {
// (this.state.loading)
// ? <UserList userStats={this.state.users} mocked={true} />
// : <UserList userStats={this.state.users} mocked={!(!this.state.error)} />
// }
// {/* { this.state.error != null ? <p className="error-message"> { this.state.error } Please try again later!</p> : null} */}
// <Footer />
// </div>
// )
// }
// }
private apiService: UserStatsService = new UserStatsService();
private mockService = new UserStatsMockService();
const MainPage: FC<IMainPageProps> = (props: IMainPageProps) => {
const [seasonId, setSeasonId] = useState(props.match.params.id)
const [error, setError] = useState<RequestError | undefined>(undefined)
const [loading, setLoadingState] = useState(true)
const [seasonStats, setSeasonStats] = useState<UserStatsResponse>(UserStatsMockService.getStatsWithoutPromise(seasonId))
constructor(props: IMainPageProps) {
super(props)
const toggleLoading = useCallback(() => setLoadingState(!loading), [setLoadingState, loading])
console.log("this.props.match.params.id = " + this.props.match.params.id)
useEffect(() => {
UserStatsMockService.getStats(seasonId)
.then(res => setSeasonStats(res))
.catch(err => setError(err))
.finally(() => toggleLoading())
}, [seasonId, toggleLoading])
let seasonId = !this.props.match.params.id ? "1" : this.props.match.params.id
console.log("seasonId = " + seasonId)
this.state = {
id: seasonId,
error: undefined,
loading: false,
users: this.mockService.getStatsWithoutPromise("1")
}
}
componentWillMount() {
this.fetchData();
}
componentDidUpdate(prevProps: Readonly<IMainPageProps>) {
const element = findDOMNode(this);
if (element != null) {
window.scrollTo(0, 0);
}
// if(prevProps.match.params.id !== this.props.match.params.id) {
// this.setState({ id: this.props.match.params.id })
// }
}
private fetchData() {
this.setState({ loading: true })
// this.apiService.getStats(this.state.id)
// .then(data => this.setState({
// loading: false,
// users: data
// }))
this.mockService.getStats(this.state.id)
.then(data => this.setState({
loading: false,
users: data
}))
}
render() {
return (
<div className="MainPage">
<Header />
{
this.state.error && <ErrorContainer message={this.state.error} />
error && <ErrorContainer message={error.message} />
}
{
(this.state.loading)
? <UserList userStats={this.state.users} mocked={true} />
: <UserList userStats={this.state.users} mocked={!(!this.state.error)} />
(loading)
? <UserList onSeasonIdChange={setSeasonId} userStats={seasonStats} mocked={true} />
: <UserList onSeasonIdChange={setSeasonId} userStats={seasonStats} mocked={!(!error)} />
}
{/* { this.state.error != null ? <p className="error-message"> { this.state.error } Please try again later!</p> : null} */}
<Footer />
</div>
)
}
}
export interface IMainPageProps extends RouteComponentProps<{ id: string }> {

View File

@@ -1,19 +1,19 @@
import RequestError from "../models/RequestError";
import UserStatsResponse from "../models/UserStatsResponse";
import {useEffect, useState} from "react";
export default class UserStatsService {
private apiURL = 'https://api.tsotr.humenius.me/stats'
private static apiURL = 'https://api.tsotr.humenius.me/stats'
private requestInit: RequestInit = {
private static requestInit: RequestInit = {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
async getStats(seasonId: string): Promise<UserStatsResponse> {
public static async getStats(seasonId: string): Promise<UserStatsResponse> {
return fetch(this.apiURL, this.requestInit)
.then(res => UserStatsService.checkResponse(res))
.then(data => data.json());
@@ -29,3 +29,69 @@ export default class UserStatsService {
return response;
}
}
// const checkResponse = <T extends Response>(response: T): T => {
// if (!response.ok) {
// console.log(response);
// let error = new RequestError(response.statusText);
// error.response = response;
// throw error;
// }
// return response;
// }
//
// const useApiService = <T>(url: string, method: string = 'GET'): { response: T | null; error: RequestError | null } => {
// const baseUrl = "https://api.tsotr.humenius.me"
// const [response, setResponse] = useState<T | null>(null)
// const [error, setError] = useState<RequestError | null>(null)
// const requestInit = {
// method: method,
// headers: {
// 'Content-Type': 'application/json'
// }
// }
//
// useEffect(() => {
// const fetchData = async (): Promise<void> => {
// const result = await fetch(`${baseUrl}${url}`, requestInit)
// .then(res => checkResponse(res))
// .then(data => data.json())
// .catch(err => setError(err))
// setResponse(result)
// }
//
// fetchData()
// }, [url])
//
// return { response, error }
// }
//
// // const seasonStatsQuery = (seasonId: number): { response: UserStatsResponse | null; error: RequestError | null } => {
// // const baseUrl = "https://api.tsotr.humenius.me/stats/season/"
// // const [response, setResponse] = useState<UserStatsResponse | null>(null)
// // const [error, setError] = useState<RequestError | null>(null)
// // const requestInit = {
// // method: 'GET',
// // headers: {
// // 'Content-Type': 'application/json'
// // }
// // }
// //
// // useEffect(() => {
// // const fetchData = async (): Promise<void> => {
// // const result = await fetch(baseUrl, requestInit)
// // .then(res => checkResponse(res))
// // .then(data => data.json())
// // .catch(err => setError(err))
// // setResponse(result)
// // }
// //
// // fetchData()
// // }, [seasonId])
// //
// // return { response, error }
// // }
//
// const currentSeasonStatsQuery = useApiService<UserStatsResponse>('/stats')
//
// export default useApiService;