diff --git a/frontend/static/css/gameHistory.css b/frontend/static/css/gameHistory.css new file mode 100644 index 0000000..465b115 --- /dev/null +++ b/frontend/static/css/gameHistory.css @@ -0,0 +1,15 @@ + +#game-list { + justify-content: flex-start; + display: flex; + flex-wrap: wrap; +} + +#game-list .game-item { + display: flex; + flex-direction: column; + height: 160px; + width: 160px; + margin: 10px; + border-radius: 5%; +} \ No newline at end of file diff --git a/frontend/static/js/api/Profile.js b/frontend/static/js/api/Profile.js index 75d0a68..b055423 100644 --- a/frontend/static/js/api/Profile.js +++ b/frontend/static/js/api/Profile.js @@ -1,4 +1,5 @@ import { Client } from "./Client.js"; +import { Game } from "./game/Game.js"; class Profile { @@ -59,6 +60,36 @@ class Profile } + /** + * @returns {[Game]} + */ + async getGameHistory() + { + let response = await this.client._get(`/api/games/history/${this.id}`); + let response_data = await response.json(); + + let games = []; + + response_data.forEach(game_data => { + games.push(new Game(this.client, + game_data.id, + null, + null, + null, + game_data.winner_id, + game_data.state, + game_data.started, + game_data.finished, + game_data.players, + game_data.start_timestamp, + game_data.stop_timestamp + ) + ); + }); + + return games; + } + async getBlock() { let block_response = await this.client._get("/api/profiles/block"); diff --git a/frontend/static/js/api/Profiles.js b/frontend/static/js/api/Profiles.js index ceddad6..7c0de7e 100644 --- a/frontend/static/js/api/Profiles.js +++ b/frontend/static/js/api/Profiles.js @@ -42,6 +42,11 @@ class Profiles return profile; } + /** + * + * @param {Number} id + * @returns {Profile} + */ async getProfileId(id) { let profile = new Profile(this.client, undefined, id); diff --git a/frontend/static/js/api/game/Game.js b/frontend/static/js/api/game/Game.js index 4c1b830..6f1a4d8 100644 --- a/frontend/static/js/api/game/Game.js +++ b/frontend/static/js/api/game/Game.js @@ -13,8 +13,16 @@ class Game * @param {CallableFunction} goal_handler * @param {CallableFunction} finish_handler * @param {CallableFunction} disconnect_handler + * @param {Boolean} finished + * @param {Number} id + * @param {[Object]} players_data + * @param {Number} start_timestamp + * @param {Number} stop_timestamp + * @param {Boolean} started + * @param {Number} winner_id + * @param {String} state */ - constructor(client, id, disconnect_handler, goal_handler, finish_handler) + constructor(client, id, disconnect_handler, goal_handler, finish_handler, winner_id, state, started, finished, players_data, start_timestamp, stop_timestamp) { /** * @type {Client} @@ -40,6 +48,50 @@ class Game * @type {CallableFunction} */ this.disconnect_handler = disconnect_handler; + + /** + * @type {String} + */ + this.state = state; + + /** + * @type {Boolean} + */ + this.started = started; + + /** + * @type {Boolean} + */ + this.finished = finished; + + /** + * @type {Number} + */ + this.winner_id = this.finished ? winner_id : undefined; + + /** + * @type {Number} + */ + this.start_timestamp = start_timestamp; + + /** + * @type {Number} + */ + this.stop_timestamp = stop_timestamp; + + /** + * @type {[Player]} + */ + this.players = []; + + players_data.forEach(player_data => { + this.players.push(new Player(this, + player_data.player_id, + player_data.username, + player_data.score + ) + ); + }); } /** @@ -55,9 +107,6 @@ class Game let response_data = await response.json(); - /** - * @type {[Player]} - */ this.players = []; response_data.players.forEach(player_data => { @@ -69,34 +118,14 @@ class Game ); }); - /** - * @type {String} - */ this.state = response_data.state; - /** - * @type {Boolean} - */ this.started = response_data.started; - - /** - * @type {Boolean} - */ this.finished = response_data.finished; - /** - * @type {Number} - */ this.winner_id = this.finished ? response_data.winner_id : undefined; - /** - * @type {Number} - */ this.start_timestamp = response_data.start_timestamp; - - /** - * @type {Number} - */ this.stop_timestamp = response_data.stop_timestamp; if (this.finished === true) diff --git a/frontend/static/js/index.js b/frontend/static/js/index.js index c6491a8..1bf21fe 100644 --- a/frontend/static/js/index.js +++ b/frontend/static/js/index.js @@ -19,6 +19,7 @@ import TournamentsView from "./views/tournament/TournamentsListView.js"; import TournamentCreateView from "./views/tournament/TournamentCreateView.js"; import AuthenticationView from "./views/accounts/AuthenticationView.js"; import TicTacToeView from "./views/TicTacToeView.js"; +import GameHistoryView from "./views/GameHistoryView.js"; let client = new Client(location.origin); let lang = client.lang; @@ -77,6 +78,7 @@ const router = async(uri) => { const routes = [ { path: "/", view: Dashboard }, + { path: "/profiles/:id/history", view: GameHistoryView }, { path: "/profiles/:username", view: ProfilePageView }, { path: "/tournaments/create", view: TournamentCreateView }, { path: "/tournaments/:id", view: TournamentPageView }, diff --git a/frontend/static/js/views/GameHistoryView.js b/frontend/static/js/views/GameHistoryView.js new file mode 100644 index 0000000..60e7850 --- /dev/null +++ b/frontend/static/js/views/GameHistoryView.js @@ -0,0 +1,66 @@ +import { client, lang } from "../index.js"; +import AbstractAuthenticatedView from "./abstracts/AbstractAuthenticatedView.js"; + +export default class extends AbstractAuthenticatedView +{ + constructor(params) + { + super(params, 'homeWindowTitle'); + this.id = params.id; + } + + async postInit() + { + this.profile = await client.profiles.getProfileId(this.id); + + if (this.profile === null) + return 404; + + await this.fillHistory(); + } + + async fillHistory() + { + let games = await this.profile.getGameHistory(); + + let game_list = document.getElementById("game-list"); + + games.forEach(game => { + + let a = document.createElement("a"); + a.href = `/games/${game.id}/0`; + a.setAttribute("data-link", true); + + let game_item = document.createElement("div"); + game_item.className = "game-item"; + game_item.style.backgroundColor = "grey"; + if (game.started) + game_item.style.backgroundColor = "yellow"; + if (game.finished) + game_item.style.backgroundColor = this.profile.id === game.winner_id ? "green" : "red"; + + game.players.forEach(player => { + let player_score = document.createElement("a"); + + player_score.href = `/profiles/${player.username}`; + player_score.innerText = `${player.username}: ${player.score.length}`; + player_score.setAttribute("data-link", true); + + game_item.appendChild(player_score); + }); + + a.appendChild(game_item); + game_list.appendChild(a); + }); + } + + async getHtml() + { + return /* HTML */ ` + +