diff --git a/common/utilities.js b/common/utilities.js index 1d2b474..ce0aa97 100644 --- a/common/utilities.js +++ b/common/utilities.js @@ -12,7 +12,8 @@ let excluded = [ //messages that should not be logged 'Not enough scientists', 'Not enough time has passed', - 'Profile sent' + 'Profile sent', + 'Ladder sent' ]; const log = (msg, ...args) => { diff --git a/public/styles/shared.css b/public/styles/shared.css index abf93bf..d280e90 100644 --- a/public/styles/shared.css +++ b/public/styles/shared.css @@ -198,7 +198,7 @@ footer { } } -/* profile page */ +/* flexbox tables */ .table { flex: 1; display: flex; diff --git a/server/index.js b/server/index.js index efdf9d8..c00d9e5 100644 --- a/server/index.js +++ b/server/index.js @@ -37,6 +37,7 @@ app.post('/profilerequest', profiles.profileRequest(connection)); app.post('/recruit', profiles.recruit(connection)); app.post('/train', profiles.train(connection)); app.post('/untrain', profiles.untrain(connection)); +app.post('/ladderrequest', profiles.ladderRequest(connection)); profiles.runGoldTick(connection); //static directories diff --git a/server/profiles.js b/server/profiles.js index ba8f6bc..ff483e4 100644 --- a/server/profiles.js +++ b/server/profiles.js @@ -356,6 +356,16 @@ const untrain = (connection) => (req, res) => { }); } +const ladderRequest = (connection) => (req, res) => { + let query = 'SELECT username, soldiers, recruits, gold FROM accounts JOIN profiles ON accounts.id = profiles.accountId ORDER BY soldiers DESC, recruits DESC, gold DESC LIMIT ?, ?;'; + connection.query(query, [req.body.start, req.body.length], (err, results) => { + if (err) throw err; + + res.status(200).json(results); + log('Ladder sent', req.body.start, req.body.length, results); + }); +} + const runGoldTick = (connection) => { let goldTickJob = new CronJob('0 */30 * * * *', () => { let query = 'UPDATE profiles SET gold = gold + recruits;'; @@ -375,5 +385,6 @@ module.exports = { recruit: recruit, train: train, untrain: untrain, - runGoldTick: runGoldTick + runGoldTick: runGoldTick, + ladderRequest: ladderRequest } \ No newline at end of file diff --git a/src/components/app.jsx b/src/components/app.jsx index f6abbd6..efe2e1b 100644 --- a/src/components/app.jsx +++ b/src/components/app.jsx @@ -4,6 +4,7 @@ import { BrowserRouter, Switch, Route } from 'react-router-dom'; //include pages import Home from './pages/home.jsx'; import Profile from './pages/profile.jsx'; +import Ladder from './pages/ladder.jsx'; import PasswordReset from './pages/password_reset.jsx' import PageNotFound from './pages/page_not_found.jsx'; @@ -23,6 +24,7 @@ export default class App extends React.Component { + diff --git a/src/components/pages/ladder.jsx b/src/components/pages/ladder.jsx new file mode 100644 index 0000000..047a549 --- /dev/null +++ b/src/components/pages/ladder.jsx @@ -0,0 +1,79 @@ +import React from 'react'; + +import CommonLinks from '../panels/common_links.jsx'; +import PagedLadder from '../panels/paged_ladder.jsx'; + +class Ladder extends React.Component { + constructor(props) { + super(props); + this.state = { + start: 0, + length: 50, + fetch: null + }; + } + + componentDidUpdate() { + this.state.fetch(); + } + + render() { + let ButtonHeader = this.buttonHeader.bind(this); + + return ( +
+

KINGDOM BATTLES!

+ +
+
+ +
+ +
+ + + +
+
+
+ ); + } + + buttonHeader() { + return ( +
+
+ +
+
+ +
+
+ ); + } + + increment() { + this.setState({ + start: this.state.start + this.state.length + }); + } + + decrement() { + this.setState({ + start: Math.max(0, this.state.start - this.state.length) + }); + } + + //bound callbacks + getFetch(fn) { + this.setState({ fetch: fn }); + } + + onReceived(data) { + if (data.length === 0) { + this.decrement(); + } + } +} + +export default Ladder; \ No newline at end of file diff --git a/src/components/panels/paged_ladder.jsx b/src/components/panels/paged_ladder.jsx new file mode 100644 index 0000000..98cdb3c --- /dev/null +++ b/src/components/panels/paged_ladder.jsx @@ -0,0 +1,66 @@ +import React from 'react'; +import { withRouter, Link } from 'react-router-dom'; +import PropTypes from 'prop-types'; + +class PagedLadder extends React.Component { + constructor(props) { + super(props); + this.state = { + data: {} + } + + if (props.getFetch) { + props.getFetch(this.fetchLadder.bind(this)); + } + + this.fetchLadder(); + } + + render() { + return ( +
+
+

Username

+

Soldiers

+

Recruits

+

Gold

+
+ {Object.keys(this.state.data).map((key) =>
{this.state.data[key].username}

{this.state.data[key].soldiers}

{this.state.data[key].recruits}

{this.state.data[key].gold}


)} +
+ ); + } + + fetchLadder(start = this.props.start, length = this.props.length) { + //build the XHR + let xhr = new XMLHttpRequest(); + + xhr.onreadystatechange = () => { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + let data = JSON.parse(xhr.responseText); + this.setState({data: data}); + + if (this.props.onReceived) { + this.props.onReceived(data); + } + } + } + } + + xhr.open('POST', '/ladderrequest', true); + xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); + xhr.send(JSON.stringify({ + start: start, + length: length + })); + } +} + +PagedLadder.propTypes = { + start: PropTypes.number.isRequired, + length: PropTypes.number.isRequired, + getFetch: PropTypes.func, + onReceived: PropTypes.func +}; + +export default withRouter(PagedLadder); \ No newline at end of file