diff --git a/webapp/src/App.js b/webapp/src/App.js index 3aa63ee..80f2778 100644 --- a/webapp/src/App.js +++ b/webapp/src/App.js @@ -1,31 +1,34 @@ import './App.css'; -import React, { useReducer } from 'react' -import { BrowserRouter, Routes, Route } from "react-router-dom" +import React from 'react'; +import { BrowserRouter, Routes, Route } from "react-router-dom"; import Header from "./container/Header" import Leaderboard from "./container/Leaderboard" import Game from "./components/Game" import About from "./components/About" -import Polling from './flux/polling'; -import User from './flux/user'; +import usePollingReducer from './reducer/polling'; +import useUserReducer from './reducer/user'; +import useLeaderboardReducer from './reducer/leaderboard'; + import useLeaderboardApi from './api/leaderboard'; import useUserApi from './api/user'; function App() { - const pollingFlux = useReducer(Polling.reducer, Polling.initialState); - const userFlux = useReducer(User.reducer, User.initialState); + const pollingReducer = usePollingReducer(); + const userReducer = useUserReducer(); + const leaderboardReducer = useLeaderboardReducer(); - const leaderboardApi = useLeaderboardApi(pollingFlux); - const userApi = useUserApi(userFlux); + const leaderboardApi = useLeaderboardApi(leaderboardReducer); + const userApi = useUserApi(userReducer); - const leaderboard = leaderboardApi.get(); + const leaderboard = leaderboardApi.get(pollingReducer); const user = userApi.get(); return (
-
+
{/* https://stackoverflow.com/questions/40541994/multiple-path-names-for-a-same-component-in-react-router */} } /> diff --git a/webapp/src/api/leaderboard.js b/webapp/src/api/leaderboard.js index d32b4b6..1b7ca18 100644 --- a/webapp/src/api/leaderboard.js +++ b/webapp/src/api/leaderboard.js @@ -2,19 +2,26 @@ import usePolling from "../util/Polling" const uri = '/api/leaderboard'; -export default function useLeaderboardApi([polling, dispatchPolling]) { +export default function useLeaderboardApi(leaderboardReducer) { + const [leaderboard, dispatchLeaderboaed] = leaderboardReducer; + + const useGet = (pollingReducer) => { + const [polling, dispatchPolling] = pollingReducer; - const useGet = () => { const mode = (polling.enabled === true) ? { interval_sec: 300 } // update leaderbord stats every 5 min : { interval_stop: true } // user has fliped OfflineToggel - const [leaderboard, isFetching] = usePolling(uri, mode); + const [table, isFetching] = usePolling(uri, mode); if (polling.leaderboard !== isFetching) { dispatchPolling({ type: 'next', leaderboard: isFetching }); } + if (leaderboard.table !== table) { + dispatchLeaderboaed({ type: 'next', table }); + } + return leaderboard; } diff --git a/webapp/src/container/Header.jsx b/webapp/src/container/Header.jsx index 72f52bf..dc4d2a0 100644 --- a/webapp/src/container/Header.jsx +++ b/webapp/src/container/Header.jsx @@ -4,8 +4,8 @@ import { NavLink } from "react-router-dom"; import OnlineToggle from '../components/OnlineToggle'; import Wobler from '../components/Wobler'; -export default function Header({ pollingFlux }) { - const [polling, dispatchPolling] = pollingFlux; +export default function Header({ pollingReducer }) { + const [polling, dispatchPolling] = pollingReducer; return (
@@ -33,4 +33,4 @@ export default function Header({ pollingFlux }) {
) -} +} \ No newline at end of file diff --git a/webapp/src/container/Leaderboard.jsx b/webapp/src/container/Leaderboard.jsx index 44e338b..54457c7 100644 --- a/webapp/src/container/Leaderboard.jsx +++ b/webapp/src/container/Leaderboard.jsx @@ -4,14 +4,15 @@ import Loading from '../components/Loading'; export default function Leaderboard({ leaderboard, user }) { - if (leaderboard == null) + const table = leaderboard?.table; + if (!table) return const isCurrentUser = (playerName) => - user.isCurrentUser(playerName) === true ? true : null; + user?.isCurrentUser(playerName) === true ? true : null; - const tableRows = Object.keys(leaderboard).map(playerName => { - var rank = leaderboard[playerName]; + const tableRows = Object.keys(table).map(playerName => { + var rank = table[playerName]; return {playerName} diff --git a/webapp/src/flux/user.js b/webapp/src/flux/user.js deleted file mode 100644 index 0d286cd..0000000 --- a/webapp/src/flux/user.js +++ /dev/null @@ -1,28 +0,0 @@ -import { localeCompare } from '../util/Locale' -import StateHelper from '../util/StateHelper'; - -export const userInitialState = { - username: '', - isCurrentUser: function (otherUsername) { - return localeCompare(this.username, otherUsername) - }, - -}; - -export function userReducer(state, action) { - switch (action.type) { - - case 'next': - return StateHelper.next(state, action); - - default: - throw Error('Unknown action.type: ' + action.type); - } -} - -const User = { - reducer: userReducer, - initialState: userInitialState -}; - -export default User; \ No newline at end of file diff --git a/webapp/src/reducer/leaderboard.js b/webapp/src/reducer/leaderboard.js new file mode 100644 index 0000000..06352a4 --- /dev/null +++ b/webapp/src/reducer/leaderboard.js @@ -0,0 +1,21 @@ +import { useReducer } from 'react'; +import { nextState } from '../util/StateHelper'; + +export const leaderboardInitialState = { + table: null, +}; + +export function leaderboardReducer(state, action) { + switch (action.type) { + + case 'next': + return nextState(state, action); + + default: + throw Error('LeaderboardReducer: Unknown action.type', action.type); + } +} + +export default function useLeaderboardReducer() { + return useReducer(leaderboardReducer, leaderboardInitialState); +} \ No newline at end of file diff --git a/webapp/src/flux/polling.js b/webapp/src/reducer/polling.js similarity index 77% rename from webapp/src/flux/polling.js rename to webapp/src/reducer/polling.js index c4ce599..521f5c7 100644 --- a/webapp/src/flux/polling.js +++ b/webapp/src/reducer/polling.js @@ -1,4 +1,5 @@ -import { useLocalStorage } from '../util/PersistentStorage' +import { useReducer } from 'react'; +import { useLocalStorage } from '../util/PersistentStorage'; import { nextState } from '../util/StateHelper'; const Persistent = (() => { @@ -33,9 +34,6 @@ export function pollingReducer(curntState, action) { } } -const Polling = { - reducer: pollingReducer, - initialState: pollingInitialState -}; - -export default Polling \ No newline at end of file +export default function usePollingReducer() { + return useReducer(pollingReducer, pollingInitialState); +} \ No newline at end of file diff --git a/webapp/src/reducer/user.js b/webapp/src/reducer/user.js new file mode 100644 index 0000000..4128100 --- /dev/null +++ b/webapp/src/reducer/user.js @@ -0,0 +1,26 @@ +import { useReducer } from 'react'; +import { localeCompare } from '../util/Locale'; +import { nextState } from '../util/StateHelper'; + +export const userInitialState = { + username: '', + + isCurrentUser: function (otherUsername) { + return localeCompare(this.username, otherUsername) + } +}; + +export function userReducer(state, action) { + switch (action.type) { + + case 'next': + return nextState(state, action); + + default: + throw Error('Unknown action.type', action.type); + } +} + +export default function useUserReducer() { + return useReducer(userReducer, userInitialState); +} \ No newline at end of file diff --git a/webapp/src/util/Polling.js b/webapp/src/util/Polling.js index ed3fac6..49a1f9a 100644 --- a/webapp/src/util/Polling.js +++ b/webapp/src/util/Polling.js @@ -47,7 +47,7 @@ export default function usePolling(url, mode) { }, [url, mode, isFetching, cache, fetchData, delayID]); return [ - cache, // API response + cache, // API responce isFetching // true / false ] }