diff --git a/frontend/src/App.css b/frontend/src/App.css index f706869..d1d6ef7 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -7,7 +7,8 @@ text-align: center; height: 100vh; color: whitesmoke; - background-color: #282c34; } + background-color: #282c34; +} .first-place { font-size: xx-large; diff --git a/frontend/src/App.scss b/frontend/src/App.scss index 2a8df4a..11bbc4e 100644 --- a/frontend/src/App.scss +++ b/frontend/src/App.scss @@ -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); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 8742bff..b96091e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -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 = () => ( + + + {/* ()} />*/} + + ()} /> + + +); + +export default App; + + +// export default class App extends React.Component { // componentDidMount() { // this.setState({loading: false, mock: this.mockService.getStatsWithoutPromise()}); @@ -24,16 +37,4 @@ export default class App extends React.Component { // error: err.error // })) // }); - // } - - render() { - return ( - - - ()} /> - ()} /> - - - ); - } -} + // } \ No newline at end of file diff --git a/frontend/src/components/Header/Header.scss b/frontend/src/components/Header/Header.scss index f7b7b90..cb98711 100644 --- a/frontend/src/components/Header/Header.scss +++ b/frontend/src/components/Header/Header.scss @@ -1,3 +1,4 @@ + .Header { .title { font-size: 4vw; diff --git a/frontend/src/components/SeasonDetail/SeasonDetail.scss b/frontend/src/components/SeasonDetail/SeasonDetail.scss index 4d13848..9617966 100644 --- a/frontend/src/components/SeasonDetail/SeasonDetail.scss +++ b/frontend/src/components/SeasonDetail/SeasonDetail.scss @@ -1 +1,4 @@ -.SeasonDetail {} \ No newline at end of file +.SeasonDetail { + vertical-align: middle; + justify-content: center; +} \ No newline at end of file diff --git a/frontend/src/components/SeasonDetail/SeasonDetail.tsx b/frontend/src/components/SeasonDetail/SeasonDetail.tsx index 8a1b0b8..555add0 100644 --- a/frontend/src/components/SeasonDetail/SeasonDetail.tsx +++ b/frontend/src/components/SeasonDetail/SeasonDetail.tsx @@ -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 { +class SeasonDetail extends React.Component { render() { - const { seasonId, dates } = this.props + const { seasonId, dates } = this.props.userStats return ( Season {seasonId} - Duration: {dates.start.toDateString()} - {dates.end.toDateString()} diff --git a/frontend/src/components/SeasonSwitch/SeasonSwitch.scss b/frontend/src/components/SeasonSwitch/SeasonSwitch.scss index 7c1ccd1..805e253 100644 --- a/frontend/src/components/SeasonSwitch/SeasonSwitch.scss +++ b/frontend/src/components/SeasonSwitch/SeasonSwitch.scss @@ -1 +1,13 @@ -.SeasonSwitch {} \ No newline at end of file +.SeasonSwitch { + + + a { + font-size: 3vw; + max-font-size: 4vw; + padding-left: 1em; + padding-right: 1em; + vertical-align: middle; + justify-content: center; + } + +} \ No newline at end of file diff --git a/frontend/src/components/SeasonSwitch/SeasonSwitch.tsx b/frontend/src/components/SeasonSwitch/SeasonSwitch.tsx index b529328..bfe1225 100644 --- a/frontend/src/components/SeasonSwitch/SeasonSwitch.tsx +++ b/frontend/src/components/SeasonSwitch/SeasonSwitch.tsx @@ -2,24 +2,27 @@ 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 { +class SeasonSwitch extends React.Component { render() { - let seasonId = Number(this.props.seasonId) + let seasonId = Number(this.props.userStats.seasonId) return( - - - + { + seasonId > 1 + && this.props.onSeasonIdChange('' + (seasonId - 1))}> + + + } - + - - - + this.props.onSeasonIdChange('' + (seasonId + 1))}> + + ) } diff --git a/frontend/src/components/UserList/UserList.scss b/frontend/src/components/UserList/UserList.scss index 3d2819a..c2a909c 100644 --- a/frontend/src/components/UserList/UserList.scss +++ b/frontend/src/components/UserList/UserList.scss @@ -15,5 +15,9 @@ font-size: larger; color: saddlebrown; } + + .SeasonSwitch { + padding-bottom: 1rem; + } } diff --git a/frontend/src/components/UserList/UserList.tsx b/frontend/src/components/UserList/UserList.tsx index 2351901..24333f1 100644 --- a/frontend/src/components/UserList/UserList.tsx +++ b/frontend/src/components/UserList/UserList.tsx @@ -15,7 +15,7 @@ export default class UserList extends React.Component | 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 - + @@ -65,14 +65,15 @@ export default class UserList extends React.Component - + ) } } -interface IUserListProperties { +export interface IUserListProperties { userStats: UserStatsResponse - mocked: boolean + mocked?: boolean + onSeasonIdChange: any } interface IUserListState { diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index f5185c1..394af67 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -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( diff --git a/frontend/src/mock/UserStatsMockService.ts b/frontend/src/mock/UserStatsMockService.ts index 6aef08e..531f1b0 100644 --- a/frontend/src/mock/UserStatsMockService.ts +++ b/frontend/src/mock/UserStatsMockService.ts @@ -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 { + static async getStats(seasonId: string): Promise { + return Promise.resolve(this.mocks[Number(seasonId) - 1]) } - getStatsWithoutPromise(seasonId: string): UserStatsResponse { + static getStatsWithoutPromise(seasonId: string): UserStatsResponse { return this.mocks[Number(seasonId) - 1] } } diff --git a/frontend/src/pages/MainPage/MainPage.scss b/frontend/src/pages/MainPage/MainPage.scss index c936413..5a0b98c 100644 --- a/frontend/src/pages/MainPage/MainPage.scss +++ b/frontend/src/pages/MainPage/MainPage.scss @@ -1,3 +1,5 @@ +@import "src/App.scss"; + .MainPage { - + @include background(); } \ No newline at end of file diff --git a/frontend/src/pages/MainPage/MainPage.tsx b/frontend/src/pages/MainPage/MainPage.tsx index f30dc72..feacadb 100644 --- a/frontend/src/pages/MainPage/MainPage.tsx +++ b/frontend/src/pages/MainPage/MainPage.tsx @@ -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 { +// class MainPage extends React.Component { +// +// 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) { +// 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 ( +// +// +// { +// this.state.error && +// } +// { +// (this.state.loading) +// ? +// : +// } +// {/* { this.state.error != null ? { this.state.error } Please try again later! : null} */} +// +// +// ) +// } +// } - private apiService: UserStatsService = new UserStatsService(); - private mockService = new UserStatsMockService(); +const MainPage: FC = (props: IMainPageProps) => { + const [seasonId, setSeasonId] = useState(props.match.params.id) + const [error, setError] = useState(undefined) + const [loading, setLoadingState] = useState(true) + const [seasonStats, setSeasonStats] = useState(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) { - 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 ( - - - { - this.state.error && - } - { - (this.state.loading) - ? - : - } - {/* { this.state.error != null ? { this.state.error } Please try again later! : null} */} - - - ) - } + return ( + + + { + error && + } + { + (loading) + ? + : + } + {/* { this.state.error != null ? { this.state.error } Please try again later! : null} */} + + + ) } export interface IMainPageProps extends RouteComponentProps<{ id: string }> { diff --git a/frontend/src/services/UserStatsService.ts b/frontend/src/services/UserStatsService.ts index 5b04f33..a70263c 100644 --- a/frontend/src/services/UserStatsService.ts +++ b/frontend/src/services/UserStatsService.ts @@ -1,22 +1,22 @@ 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 { + public static async getStats(seasonId: string): Promise { return fetch(this.apiURL, this.requestInit) - .then(res => UserStatsService.checkResponse(res)) - .then(data => data.json()); + .then(res => UserStatsService.checkResponse(res)) + .then(data => data.json()); } private static checkResponse(response: any): any { @@ -29,3 +29,69 @@ export default class UserStatsService { return response; } } + +// const checkResponse = (response: T): T => { +// if (!response.ok) { +// console.log(response); +// let error = new RequestError(response.statusText); +// error.response = response; +// throw error; +// } +// return response; +// } +// +// const useApiService = (url: string, method: string = 'GET'): { response: T | null; error: RequestError | null } => { +// const baseUrl = "https://api.tsotr.humenius.me" +// const [response, setResponse] = useState(null) +// const [error, setError] = useState(null) +// const requestInit = { +// method: method, +// headers: { +// 'Content-Type': 'application/json' +// } +// } +// +// useEffect(() => { +// const fetchData = async (): Promise => { +// 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(null) +// // const [error, setError] = useState(null) +// // const requestInit = { +// // method: 'GET', +// // headers: { +// // 'Content-Type': 'application/json' +// // } +// // } +// // +// // useEffect(() => { +// // const fetchData = async (): Promise => { +// // 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('/stats') +// +// export default useApiService; \ No newline at end of file
{ this.state.error } Please try again later!