From cfac59282da55f4791d6352f15887a15e9ff6ec5 Mon Sep 17 00:00:00 2001
From: Wolfboy248 <121288977+Wolfboy248@users.noreply.github.com>
Date: Wed, 10 Jul 2024 21:51:25 +0200
Subject: Games page, maplist page (#153)
Co-authored-by: Wolfboy248 <105884620+Wolfboy248@users.noreply.github.com>
---
frontend/src/components/pages/game.js | 46 ++
frontend/src/components/pages/games.css | 99 ++++
frontend/src/components/pages/games.js | 58 ++
frontend/src/components/pages/home.css | 90 ++++
frontend/src/components/pages/home.js | 198 +++++++
frontend/src/components/pages/maplist.css | 399 ++++++++++++++
frontend/src/components/pages/maplist.js | 844 ++++++++++++++++++++++++++++++
frontend/src/components/pages/summary.css | 4 +-
frontend/src/components/pages/summary.js | 20 +-
9 files changed, 1751 insertions(+), 7 deletions(-)
create mode 100644 frontend/src/components/pages/game.js
create mode 100644 frontend/src/components/pages/games.css
create mode 100644 frontend/src/components/pages/games.js
create mode 100644 frontend/src/components/pages/home.css
create mode 100644 frontend/src/components/pages/home.js
create mode 100644 frontend/src/components/pages/maplist.css
create mode 100644 frontend/src/components/pages/maplist.js
(limited to 'frontend/src/components/pages')
diff --git a/frontend/src/components/pages/game.js b/frontend/src/components/pages/game.js
new file mode 100644
index 0000000..017760b
--- /dev/null
+++ b/frontend/src/components/pages/game.js
@@ -0,0 +1,46 @@
+import React, { useEffect, useRef, useState } from 'react';
+import { useLocation, Link } from "react-router-dom";
+
+import "./games.css"
+
+export default function GameEntry({ gameInfo }) {
+ const [gameEntry, setGameEntry] = React.useState(null);
+ const location = useLocation();
+
+ const gameInfoCats = gameInfo.category_portals;
+
+ useEffect(() => {
+ gameInfoCats.forEach(catInfo => {
+ const itemBody = document.createElement("div");
+ const itemTitle = document.createElement("span");
+ const spacing = document.createElement("br");
+ const itemNum = document.createElement("span");
+
+ itemTitle.innerText = catInfo.category.name;
+ itemNum.innerText = catInfo.portal_count;
+ itemTitle.classList.add("games-page-item-body-item-title");
+ itemNum.classList.add("games-page-item-body-item-num");
+ itemBody.appendChild(itemTitle);
+ itemBody.appendChild(spacing);
+ itemBody.appendChild(itemNum);
+ itemBody.className = "games-page-item-body-item";
+
+ // itemBody.innerHTML = `
+ // ${catInfo.category.name}
+ // ${catInfo.portal_count}`
+
+ document.getElementById(`${gameInfo.id}`).appendChild(itemBody);
+ });
+ })
+
+ return (
+
')) {
+ return
+ }
+ const title = e.getAttribute("title");
+
+ const titleDiv = document.createElement("div");
+ const titleSpan = document.createElement("span");
+
+ titleDiv.classList.add("homepage-panel-title-div")
+
+ titleSpan.innerText = title
+
+ titleDiv.appendChild(titleSpan)
+ e.insertBefore(titleDiv, e.firstChild)
+ });
+ })
+
+ const newsList = [
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ {
+ "title": "Portal Saved on Container Ride",
+ "short_description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus vehicula facilisis quam, non ultrices nisl aliquam at. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."
+ },
+ ]
+
+ return (
+
+
+ Welcome back,
+ Krzyhau
+
+
+
+
+ {/* Column 1 */}
+
+
+
+ Overall rank
+ #69
+
+
+ Singleplayer
+ #10 (60/62)
+
+
+ Overall rank
+ #69 (13/37)
+
+
+
+
+
+
![]()
+
+
Container Ride
+
Your Record: 4 portals
+
World Record: 2 portals
+
+
+
+
+
+
+
+ Place
+ Runner
+ Portals
+ Time
+ Date
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* Column 2 */}
+
+
+
+ {newsList.map((newsList, index) => (
+
+ ))}
+
+
+
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/frontend/src/components/pages/maplist.css b/frontend/src/components/pages/maplist.css
new file mode 100644
index 0000000..a63c4ec
--- /dev/null
+++ b/frontend/src/components/pages/maplist.css
@@ -0,0 +1,399 @@
+.maplist-page {
+ position: relative;
+ left: 350px;
+ height: 100vh;
+ color: #cdcfdf;
+ width: calc(100% - 380px);
+ font-family: BarlowSemiCondensed-Regular;
+ overflow-y: scroll;
+ overflow-x: hidden;
+ padding-right: 30px;
+}
+
+a {
+ color: inherit;
+ width: fit-content;
+}
+
+.maplist-page-content {
+ position: absolute;
+ left: 0px;
+ width: calc(100% - 50px);
+}
+
+.maplist-page-header {
+ margin-top: 20px;
+ display: grid;
+ margin-bottom: 10px;
+}
+
+.nav-btn {
+ height: 40px;
+ background-color: #2b2e46;
+ color: inherit;
+ font-size: 18px;
+ font-family: inherit;
+ border: none;
+ border-radius: 20px;
+ transition: background-color .1s;
+ cursor: default;
+ width: fit-content;
+}
+
+.nav-btn>span {
+ padding: 0 8px 0 8px;
+}
+
+.nav-btn:hover {
+ background-color: #202232;
+ cursor: pointer;
+}
+
+.game {
+ width: 100%;
+ height: 192px;
+ background: #202232;
+ border-radius: 24px;
+ overflow: hidden;
+}
+
+.game-header {
+ width: 100%;
+ height: 144px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ overflow: hidden;
+}
+
+.game-header-text {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ position: absolute;
+}
+
+.game-img {
+ width: 100%;
+ height: 100%;
+ background-size: cover;
+ filter: blur(4px);
+}
+
+.game-header-text>span {
+ font-size: 42px;
+ font-weight: 500;
+ margin: 5px;
+}
+
+.game-header-text span>b {
+ font-size: 96px;
+ font-weight: 600;
+}
+
+.game-nav {
+ display: flex;
+ height: 48px;
+}
+
+.game-nav-btn {
+ width: 100%;
+ height: 100%;
+ border: none;
+ border-radius: 0px;
+ color: inherit;
+ font-family: inherit;
+ font-size: 22px;
+ background: #2B2E46;
+ transition: background-color .1s;
+ margin: 0 1px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.game-nav-btn:hover, .selected {
+ background-color: #202232;
+ cursor: pointer;
+}
+
+.gameview-nav {
+ margin-top: 20px;
+ display: flex;
+ height: 56px;
+ border-radius: 24px;
+ overflow: hidden;
+ background-color: #202232;
+}
+
+.maplist {
+ width: 100%;
+ margin-top: 20px;
+ margin-bottom: 40px;
+}
+
+.chapter-name {
+ font-size: 30px;
+}
+
+.chapter-page-div {
+ display: flex;
+ justify-content: right;
+ transform: translateY(-30px);
+}
+
+.chapter-page-div button {
+ background-color: #00000000;
+ border: 0;
+ cursor: pointer;
+ height: 30px;
+ padding: 0;
+ width: 30px;
+}
+
+.chapter-page-div span {
+ color: #cdcfdf;
+ font-family: BarlowSemiCondensed-Regular;
+ font-size: 20px;
+}
+
+.maplist-maps {
+ display: grid;
+ grid-template-columns: 25% 25% 25% 25%;
+ margin-top: 10px;
+ transform: translateY(-30px);
+}
+
+.maplist-item {
+ background: #202232;
+ border-radius: 24px;
+ overflow: hidden;
+ margin: 10px 10px;
+ /* padding: 10px 15px; */
+ cursor: pointer;
+ user-select: none;
+}
+
+.loader-map {
+ border-radius: 24px;
+ overflow: hidden;
+ margin: 10px 10px;
+ /* padding: 10px 15px; */
+ user-select: none;
+ width: calc(100% - 20px);
+ height: calc(223px);
+}
+
+.maplist-img-div {
+ height: 150px;
+ overflow: hidden;
+}
+
+.maplist-img {
+ width: 100%;
+ height: 100%;
+ background-size: cover;
+ filter: blur(4px);
+ opacity: 0.7;
+}
+
+.maplist-portalcount-div {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ height: 100%;
+ transform: translateY(-100%);
+ overflow: hidden;
+}
+
+.maplist-title {
+ font-size: 22px;
+ text-align: center;
+ width: 100%;
+ display: inherit;
+ padding: 5px 0px;
+ color: #CDCFDF;
+}
+
+.maplist-portals {
+ margin-left: 5px;
+ font-size: 32px;
+}
+
+.difficulty-div {
+ display: flex;
+ padding: 7px 10px;
+}
+
+.difficulty-label {
+ font-size: 18px;
+}
+
+.difficulty-bar {
+ width: 100%;
+ display: grid;
+ grid-template-columns: 20% 20% 20% 20% 20%;
+ align-items: center;
+ margin: 5px;
+}
+
+.difficulty-point {
+ background: #2B2E46;
+ height: 3px;
+ margin: 5px;
+ border-radius: 10px;
+}
+
+.stats {
+ margin-top: 30px;
+}
+
+.portalcount-over-time-div {
+ width: 100%;
+ height: 450px;
+ position: relative;
+ background-color: #202232;
+ border-radius: 20px;
+}
+
+.graph-title {
+ width: 100%;
+ display: inherit;
+ font-size: 24px;
+ margin-top: 5px;
+ text-align: center;
+ font-family: BarlowSemiCondensed-SemiBold;
+ padding-top: 7px;
+}
+
+.portalcount-graph {
+ height: calc(100% - 30px);
+ width: calc(100% - 80px);
+}
+
+.chart {
+ height: calc(100% - 80px);
+ width: 100%;
+ position: relative;
+ padding: 0px 0px;
+ scrollbar-width: thin;
+}
+
+.line-chart {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ border-bottom: 2px solid #2B2E46;
+}
+
+.data-point {
+ background-color: #202232;
+ border: 4px solid #006FDE;
+ border-radius: 50%;
+ height: 6px;
+ position: absolute;
+ width: 6px;
+ bottom: calc(var(--y) - 4.5px);
+ left: calc(var(--x) - 6.5px);
+ transition: all 0.2s cubic-bezier(0.075, 0.82, 0.165, 1);
+ z-index: 1;
+ animation: point_intro 0.2s cubic-bezier(0.075, 0.82, 0.165, 1.8);
+ animation-fill-mode: backwards;
+}
+
+.data-point:hover, .data-point-active {
+ background-color: #006FDE;
+ box-shadow: 0px 0px 10px #006FDE;
+}
+
+.line-segment {
+ background-color: #006FDE;
+ bottom: var(--y);
+ height: 4px;
+ left: var(--x);
+ position: absolute;
+ transform: rotate(calc(var(--angle) * -1deg));
+ width: calc(var(--hypotenuse) * 1px);
+ transform-origin: left bottom;
+ border-radius: 20px;
+ z-index: 1;
+ animation: line_intro 0.05s cubic-bezier(0, 1, 0.31, 0.96);
+ animation-fill-mode: backwards;
+}
+
+#dataPointInfo {
+ position: absolute;
+ width: 400px;
+ height: 85px;
+ background: #202232;
+ box-shadow: 0px 4px 16px 0px #00000080;
+ transition: all 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
+ z-index: 1000;
+ opacity: 0;
+ left: auto;
+ border-radius: 20px;
+ padding: 15px 7px;
+}
+
+.section-header {
+ display: flex;
+ text-align: center;
+ font-family: BarlowSemiCondensed-SemiBold;
+ font-size: 18px;
+ height: 40%;
+ justify-content: space-evenly;
+ align-items: center;
+}
+
+.section-header span, .section-data span {
+ flex: 1;
+}
+
+.divider {
+ width: 100%;
+ height: 2px;
+ background-color: #2B2E46;
+ display: flex;
+ margin: 5px 0px 8px 0px;
+}
+
+.section-data {
+ display: flex;
+ grid-template-columns: 25% 25% 25% 25%;
+ text-align: center;
+ background-color: #2B2E46;
+ height: 52%;
+ border-radius: 200px;
+ align-items: center;
+ justify-content: space-evenly;
+ flex-grow: 1;
+ font-family: BarlowSemiCondensed-Regular;
+ font-size: 18px;
+ padding: 0px 5px;
+}
+
+@keyframes line_intro {
+ 0% {
+ width: 0;
+ }
+ 100% {
+ width: calc(var(--hypotenuse) * 1px);
+ }
+}
+
+@keyframes point_intro {
+ 0% {
+ opacity: 0;
+ width: 0;
+ height: 0;
+ transform: translate(3px, -3px);
+ }
+ 100% {
+ width: 6px;
+ height: 6px;
+ transform: translate(0px, 0px);
+ opacity: 1;
+ }
+}
diff --git a/frontend/src/components/pages/maplist.js b/frontend/src/components/pages/maplist.js
new file mode 100644
index 0000000..dca76d6
--- /dev/null
+++ b/frontend/src/components/pages/maplist.js
@@ -0,0 +1,844 @@
+import React, { useEffect, useRef, useState } from 'react';
+import { useLocation, Link } from "react-router-dom";
+import { BrowserRouter as Router, Route, Routes, useNavigate } from 'react-router-dom';
+
+import "./maplist.css"
+import img5 from "../../imgs/5.png"
+import img6 from "../../imgs/6.png"
+
+export default function Maplist(prop) {
+ const {token,setToken} = prop
+ const scrollRef = useRef(null)
+ const [games, setGames] = React.useState(null);
+ const location = useLocation();
+
+ let gameTitle;
+ let minPage;
+ let maxPage;
+ let currentPage;
+ let add = 0;
+ let gameState;
+ let catState = 0;
+ async function detectGame() {
+ const response = await fetch("https://lp.ardapektezol.com/api/v1/games", {
+ headers: {
+ 'Authorization': token
+ }
+ });
+
+ const data = await response.json();
+
+ const url = new URL(window.location.href)
+
+ const params = new URLSearchParams(url.search)
+ gameState = parseFloat(params.get("game"))
+
+ document.querySelector("#catPortalCount").innerText = data.data[gameState - 1].category_portals[0].portal_count;
+
+ if (gameState == 1){
+ gameTitle = data.data[0].name;
+
+ maxPage = 9;
+ minPage = 1;
+ createCategories(1);
+ } else if (gameState == 2){
+ gameTitle = data.data[1].name;
+
+ maxPage = 16;
+ minPage = 10;
+ add = 10
+ createCategories(2);
+ }
+
+ let chapterParam = params.get("chapter")
+
+ currentPage = minPage;
+
+ if (chapterParam) {
+ currentPage = +chapterParam + add
+ }
+
+ changePage(currentPage);
+
+ // if (chapterParam) {
+ // document.querySelector("#pageNumbers").innerText = `${chapterParam - minPage + 1}/${maxPage - minPage + 1}`
+ // }
+ }
+
+ function changeMaplistOrStatistics(index, name) {
+ const maplistBtns = document.querySelectorAll("#maplistBtn");
+ maplistBtns.forEach((btn, i) => {
+ if (i == index) {
+ btn.className = "game-nav-btn selected"
+
+ if (name == "maplist") {
+ document.querySelector(".stats").style.display = "none";
+ document.querySelector(".maplist").style.display = "block";
+ document.querySelector(".maplist").setAttribute("currentTab", "maplist");
+ } else {
+ document.querySelector(".stats").style.display = "block";
+ document.querySelector(".maplist").style.display = "none";
+
+ document.querySelector(".maplist-page").scrollTo({ top: 372, behavior: "smooth" })
+ document.querySelector(".maplist").setAttribute("currentTab", "stats");
+ }
+ } else {
+ btn.className = "game-nav-btn";
+ }
+ });
+ }
+
+ async function createCategories(gameID) {
+ const response = await fetch("https://lp.ardapektezol.com/api/v1/games", {
+ headers: {
+ 'Authorization': token
+ }
+ });
+
+ const data = await response.json();
+ let categoriesArr = data.data[gameID - 1].category_portals;
+
+ const gameNav = document.querySelector(".game-nav");
+ gameNav.innerHTML = "";
+ categoriesArr.forEach((category) => {
+ createCategory(category);
+ });
+ }
+
+ let categoryNum = 0;
+ function createCategory(category) {
+ const gameNav = document.querySelector(".game-nav");
+
+ categoryNum++;
+ const gameNavBtn = document.createElement("button");
+ if (categoryNum == 1) {
+ gameNavBtn.className = "game-nav-btn selected";
+ } else {
+ gameNavBtn.className = "game-nav-btn";
+ }
+ gameNavBtn.id = "catBtn"
+ gameNavBtn.innerText = category.category.name;
+
+ gameNavBtn.addEventListener("click", (e) => {
+ changeCategory(category, e);
+ changePage(currentPage);
+ })
+
+ gameNav.appendChild(gameNavBtn);
+ }
+
+ async function changeCategory(category, btn) {
+ const response = await fetch("https://lp.ardapektezol.com/api/v1/games", {
+ headers: {
+ 'Authorization': token
+ }
+ });
+
+ const data = await response.json();
+ catState = category.category.id - 1;
+ console.log(catState)
+ const navBtns = document.querySelectorAll("#catBtn");
+ navBtns.forEach((btns) => {
+ btns.classList.remove("selected");
+ });
+
+ btn.srcElement.classList.add("selected");
+ document.querySelector("#catPortalCount").innerText = category.portal_count;
+ }
+
+ async function changePage(page) {
+
+ const pageNumbers = document.querySelector("#pageNumbers");
+
+ pageNumbers.innerText = `${currentPage - minPage + 1}/${maxPage - minPage + 1}`;
+
+ const maplistMaps = document.querySelector(".maplist-maps");
+ maplistMaps.innerHTML = "";
+ for (let index = 0; index < 8; index++) {
+ const loadingAnimation = document.createElement("div");
+ loadingAnimation.classList.add("loader");
+ loadingAnimation.classList.add("loader-map")
+ maplistMaps.appendChild(loadingAnimation);
+ }
+ const data = await fetchMaps(page);
+ const maps = data.data.maps;
+ const name = data.data.chapter.name;
+
+ let chapterName = "Chapter";
+ const chapterNumberOld = name.split(" - ")[0];
+ let chapterNumber1 = chapterNumberOld.split("Chapter ")[1];
+ if (chapterNumber1 == undefined) {
+ chapterName = "Course"
+ chapterNumber1 = chapterNumberOld.split("Course ")[1];
+ }
+ const chapterNumber = chapterNumber1.toString().padStart(2, "0");
+ const chapterTitle = name.split(" - ")[1];
+
+ const chapterNumberElement = document.querySelector(".chapter-num")
+ const chapterTitleElement = document.querySelector(".chapter-name")
+ chapterNumberElement.innerText = chapterName + " " + chapterNumber;
+ chapterTitleElement.innerText = chapterTitle;
+
+ maplistMaps.innerHTML = "";
+ maps.forEach(map => {
+ let portalCount;
+ if (map.category_portals[catState] != undefined) {
+ portalCount = map.category_portals[catState].portal_count;
+ } else {
+ portalCount = map.category_portals[0].portal_count;
+ }
+ addMap(map.name, portalCount, map.image, map.difficulty + 1, map.id);
+ });
+
+ const gameTitleElement = document.querySelector("#gameTitle");
+ gameTitleElement.innerText = gameTitle;
+
+ const url = new URL(window.location.href)
+
+ const params = new URLSearchParams(url.search)
+
+ let chapterParam = params.get("chapter")
+
+ try {
+ const response = await fetch("https://lp.ardapektezol.com/api/v1/games", {
+ headers: {
+ 'Authorization': token
+ }
+ });
+
+ const data = await response.json();
+
+ const gameImg = document.querySelector(".game-img");
+
+ gameImg.style.backgroundImage = `url(${data.data[0].image})`;
+
+ // const mapImg = document.querySelectorAll(".maplist-img");
+ // mapImg.forEach((map) => {
+ // map.style.backgroundImage = `url(${data.data[0].image})`;
+ // });
+
+ } catch (error) {
+ console.log("error fetching games:", error);
+ }
+
+ asignDifficulties();
+ }
+
+ async function addMap(mapName, mapPortalCount, mapImage, difficulty, mapID) {
+ // jesus christ
+ const maplistItem = document.createElement("div");
+ const maplistTitle = document.createElement("span");
+ const maplistImgDiv = document.createElement("div");
+ const maplistImg = document.createElement("div");
+ const maplistPortalcountDiv = document.createElement("div");
+ const maplistPortalcount = document.createElement("span");
+ const b = document.createElement("b");
+ const maplistPortalcountPortals = document.createElement("span");
+ const difficultyDiv = document.createElement("div");
+ const difficultyLabel = document.createElement("span");
+ const difficultyBar = document.createElement("div");
+ const difficultyPoint1 = document.createElement("div");
+ const difficultyPoint2 = document.createElement("div");
+ const difficultyPoint3 = document.createElement("div");
+ const difficultyPoint4 = document.createElement("div");
+ const difficultyPoint5 = document.createElement("div");
+
+ maplistItem.className = "maplist-item";
+ maplistTitle.className = "maplist-title";
+ maplistImgDiv.className = "maplist-img-div";
+ maplistImg.className = "maplist-img";
+ maplistPortalcountDiv.className = "maplist-portalcount-div";
+ maplistPortalcount.className = "maplist-portalcount";
+ maplistPortalcountPortals.className = "maplist-portals";
+ difficultyDiv.className = "difficulty-div";
+ difficultyLabel.className = "difficulty-label";
+ difficultyBar.className = "difficulty-bar";
+ difficultyPoint1.className = "difficulty-point";
+ difficultyPoint2.className = "difficulty-point";
+ difficultyPoint3.className = "difficulty-point";
+ difficultyPoint4.className = "difficulty-point";
+ difficultyPoint5.className = "difficulty-point";
+
+
+ maplistTitle.innerText = mapName;
+ difficultyLabel.innerText = "Difficulty: "
+ maplistPortalcountPortals.innerText = "portals"
+ b.innerText = mapPortalCount;
+ maplistImg.style.backgroundImage = `url(${mapImage})`;
+ difficultyBar.setAttribute("difficulty", difficulty)
+ maplistItem.setAttribute("id", mapID)
+ maplistItem.addEventListener("click", () => {
+ console.log(mapID)
+ window.location.href = "/maps/" + mapID
+ })
+
+ // appends
+ // maplist item
+ maplistItem.appendChild(maplistTitle);
+ maplistImgDiv.appendChild(maplistImg);
+ maplistImgDiv.appendChild(maplistPortalcountDiv);
+ maplistPortalcountDiv.appendChild(maplistPortalcount);
+ maplistPortalcount.appendChild(b);
+ maplistPortalcountDiv.appendChild(maplistPortalcountPortals);
+ maplistItem.appendChild(maplistImgDiv);
+ maplistItem.appendChild(difficultyDiv);
+ difficultyDiv.appendChild(difficultyLabel);
+ difficultyDiv.appendChild(difficultyBar);
+ difficultyBar.appendChild(difficultyPoint1);
+ difficultyBar.appendChild(difficultyPoint2);
+ difficultyBar.appendChild(difficultyPoint3);
+ difficultyBar.appendChild(difficultyPoint4);
+ difficultyBar.appendChild(difficultyPoint5);
+
+ // display in place
+ const maplistMaps = document.querySelector(".maplist-maps");
+ maplistMaps.appendChild(maplistItem);
+ }
+
+ async function fetchMaps(chapterID) {
+ try{
+ const response = await fetch(`https://lp.ardapektezol.com/api/v1/chapters/${chapterID}`, {
+ headers: {
+ 'Authorization': token
+ }
+ });
+
+ const data = await response.json();
+ return data;
+ } catch (err) {
+ console.log(err)
+ }
+ }
+
+ // difficulty stuff
+ function asignDifficulties() {
+ const difficulties = document.querySelectorAll(".difficulty-bar");
+ difficulties.forEach((difficultyElement) => {
+ let difficulty = difficultyElement.getAttribute("difficulty");
+ if (difficulty == "1") {
+ difficultyElement.childNodes[0].style.backgroundColor = "#51C355";
+ } else if (difficulty == "2") {
+ difficultyElement.childNodes[0].style.backgroundColor = "#8AC93A";
+ difficultyElement.childNodes[1].style.backgroundColor = "#8AC93A";
+ } else if (difficulty == "3") {
+ difficultyElement.childNodes[0].style.backgroundColor = "#8AC93A";
+ difficultyElement.childNodes[1].style.backgroundColor = "#8AC93A";
+ difficultyElement.childNodes[2].style.backgroundColor = "#8AC93A";
+ } else if (difficulty == "4") {
+ difficultyElement.childNodes[0].style.backgroundColor = "#C35F51";
+ difficultyElement.childNodes[1].style.backgroundColor = "#C35F51";
+ difficultyElement.childNodes[2].style.backgroundColor = "#C35F51";
+ difficultyElement.childNodes[3].style.backgroundColor = "#C35F51";
+ } else if (difficulty == "5") {
+ difficultyElement.childNodes[0].style.backgroundColor = "#C35F51";
+ difficultyElement.childNodes[1].style.backgroundColor = "#C35F51";
+ difficultyElement.childNodes[2].style.backgroundColor = "#C35F51";
+ difficultyElement.childNodes[3].style.backgroundColor = "#C35F51";
+ difficultyElement.childNodes[4].style.backgroundColor = "#C35F51";
+ }
+ });
+ }
+
+ const divRef = useRef(null);
+
+ React.useEffect(() => {
+
+ const lineChart = document.querySelector(".line-chart")
+ function createGraph() {
+ // max
+ let items = [
+ {
+ record: "100",
+ date: new Date(2011, 4, 4),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "98",
+ date: new Date(2012, 6, 4),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "94",
+ date: new Date(2013, 0, 1),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "90",
+ date: new Date(2014, 0, 1),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "88",
+ date: new Date(2015, 6, 14),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "84",
+ date: new Date(2016, 8, 19),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "82",
+ date: new Date(2017, 3, 20),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "81",
+ date: new Date(2018, 2, 25),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "80",
+ date: new Date(2019, 3, 4),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "78",
+ date: new Date(2020, 11, 21),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "77",
+ date: new Date(2021, 10, 25),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "76",
+ date: new Date(2022, 4, 17),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "75",
+ date: new Date(2023, 9, 31),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ {
+ record: "74",
+ date: new Date(2024, 4, 4),
+ map: "Container Ride",
+ first: "tiny zach"
+ },
+ ]
+
+ function calculatePosition(date, startDate, endDate, maxWidth) {
+ const totalMilliseconds = endDate - startDate + 10000000000;
+ const millisecondsFromStart = date - startDate + 5000000000;
+ return (millisecondsFromStart / totalMilliseconds) * maxWidth
+ }
+
+ const minDate = items.reduce((min, dp) => dp.date < min ? dp.date : min, items[0].date)
+ const maxDate = items.reduce((max, dp) => dp.date > max ? dp.date : max, items[0].date)
+
+ const graph_width = document.querySelector(".portalcount-over-time-div").clientWidth
+ // console.log(graph_width)
+
+ const uniqueYears = new Set()
+ items.forEach(dp => uniqueYears.add(dp.date.getFullYear()))
+ let minYear = Infinity;
+ let maxYear = -Infinity;
+
+ items.forEach(dp => {
+ const year = dp.date.getFullYear();
+ minYear = Math.min(minYear, year);
+ maxYear = Math.max(maxYear, year);
+ });
+
+ // Add missing years to the set
+ for (let year = minYear; year <= maxYear; year++) {
+ uniqueYears.add(year);
+ }
+ const uniqueYearsArr = Array.from(uniqueYears)
+
+ items = items.map(dp => ({
+ record: dp.record,
+ date: dp.date,
+ x: calculatePosition(dp.date, minDate, maxDate, lineChart.clientWidth),
+ map: dp.map,
+ first: dp.first
+ }))
+
+ const yearInterval = lineChart.clientWidth / uniqueYears.size
+ for (let index = 1; index < (uniqueYears.size); index++) {
+ const placeholderlmao = document.createElement("div")
+ const yearSpan = document.createElement("span")
+ yearSpan.style.position = "absolute"
+ placeholderlmao.style.height = "100%"
+ placeholderlmao.style.width = "2px"
+ placeholderlmao.style.backgroundColor = "#00000080"
+ placeholderlmao.style.position = `absolute`
+ const thing = calculatePosition(new Date(uniqueYearsArr[index], 0, 0), minDate, maxDate, lineChart.clientWidth)
+ placeholderlmao.style.left = `${thing}px`
+ yearSpan.style.left = `${thing}px`
+ yearSpan.style.bottom = "-34px"
+ yearSpan.innerText = uniqueYearsArr[index]
+ yearSpan.style.fontFamily = "BarlowSemiCondensed-Regular"
+ yearSpan.style.fontSize = "22px"
+ yearSpan.style.opacity = "0.8"
+ lineChart.appendChild(yearSpan)
+
+ }
+
+ let maxPortals;
+ let minPortals;
+ let precision;
+ let multiplier = 1;
+ for (let index = 0; index < items.length; index++) {
+ precision = Math.floor((items[0].record - items[items.length - 1].record))
+ if (precision > 20) {
+ precision = 20
+ }
+ minPortals = Math.floor((items[items.length - 1].record) / 10) * 10
+ if (index == 0) {
+ maxPortals = items[index].record - minPortals
+ }
+ }
+ function calculateMultiplier(value) {
+ while (value > precision) {
+ multiplier += 1;
+ value -= precision;
+ }
+ }
+ calculateMultiplier(items[0].record);
+ // if (items[0].record > 10) {
+ // multiplier = 2;
+ // }
+
+ // Original cubic bezier control points
+ const P0 = { x: 0, y: 0 };
+ const P1 = { x: 0.26, y: 1 };
+ const P2 = { x: 0.74, y: 1 };
+ const P3 = { x: 1, y: 0 };
+
+ function calculateIntermediateControlPoints(t, P0, P1, P2, P3) {
+ const x = (1 - t) ** 3 * P0.x +
+ 3 * (1 - t) ** 2 * t * P1.x +
+ 3 * (1 - t) * t ** 2 * P2.x +
+ t ** 3 * P3.x;
+
+ const y = (1 - t) ** 3 * P0.y +
+ 3 * (1 - t) ** 2 * t * P1.y +
+ 3 * (1 - t) * t ** 2 * P2.y +
+ t ** 3 * P3.y;
+
+ return { x, y };
+ }
+
+
+ let delay = 0;
+ for (let index = 0; index < items.length; index++) {
+ let chart_height = 340;
+ const item = items[index];
+ delay += 0.05;
+ // console.log(lineChart.clientWidth)
+
+ // maxPortals++;
+ // maxPortals++;
+
+ let point_height = (chart_height / maxPortals)
+
+ for (let index = 0; index < (maxPortals / multiplier); index++) {
+ // console.log((index + 1) * multiplier)
+ let current_portal_count = (index + 1);
+
+ const placeholderDiv = document.createElement("div")
+ const numPortalsText = document.createElement("span")
+ const numPortalsTextBottom = document.createElement("span")
+ numPortalsText.innerText = (current_portal_count * multiplier) + minPortals
+ numPortalsTextBottom.innerText = minPortals
+ placeholderDiv.style.position = "absolute"
+ numPortalsText.style.position = "absolute"
+ numPortalsTextBottom.style.position = "absolute"
+ numPortalsText.style.left = "-37px"
+ numPortalsText.style.opacity = "0.2"
+ numPortalsTextBottom.style.opacity = "0.2"
+ numPortalsText.style.fontFamily = "BarlowSemiCondensed-Regular"
+ numPortalsTextBottom.style.fontFamily = "BarlowSemiCondensed-Regular"
+ numPortalsText.style.fontSize = "22px"
+ numPortalsTextBottom.style.left = "-37px"
+ numPortalsTextBottom.style.fontSize = "22px"
+ numPortalsTextBottom.style.fontWeight = "400"
+ numPortalsText.style.color = "#CDCFDF"
+ numPortalsTextBottom.style.color = "#CDCFDF"
+ numPortalsText.style.fontFamily = "inherit"
+ numPortalsTextBottom.style.fontFamily = "inherit"
+ numPortalsText.style.textAlign = "right"
+ numPortalsTextBottom.style.textAlign = "right"
+ numPortalsText.style.width = "30px"
+ numPortalsTextBottom.style.width = "30px"
+ placeholderDiv.style.bottom = `${(point_height * current_portal_count * multiplier) - 2}px`
+ numPortalsText.style.bottom = `${(point_height * current_portal_count * multiplier) - 2 - 9}px`
+ numPortalsTextBottom.style.bottom = `${0 - 2 - 8}px`
+ placeholderDiv.id = placeholderDiv.style.bottom
+ placeholderDiv.style.width = "100%"
+ placeholderDiv.style.height = "2px"
+ placeholderDiv.style.backgroundColor = "#2B2E46"
+ placeholderDiv.style.zIndex = "0"
+
+ if (index == 0) {
+ lineChart.appendChild(numPortalsTextBottom)
+ }
+ lineChart.appendChild(numPortalsText)
+ lineChart.appendChild(placeholderDiv)
+ }
+
+ const li = document.createElement("li");
+ const lineSeg = document.createElement("div");
+ const dataPoint = document.createElement("div");
+
+ li.style = `--y: ${point_height * (item.record - minPortals) - 3}px; --x: ${item.x}px`;
+ lineSeg.className = "line-segment";
+ dataPoint.className = "data-point";
+
+ if (items[index + 1] !== undefined) {
+ const hypotenuse = Math.sqrt(
+ Math.pow(items[index + 1].x - items[index].x, 2) +
+ Math.pow((point_height * items[index + 1].record) - point_height * item.record, 2)
+ );
+ const angle = Math.asin(
+ ((point_height * item.record) - (point_height * items[index + 1].record)) / hypotenuse
+ );
+
+ lineSeg.style = `--hypotenuse: ${hypotenuse}; --angle: ${angle * (-180 / Math.PI)}`;
+ const t0 = index / items.length;
+ const t1 = (index + 1) / items.length
+
+ const P0t0 = calculateIntermediateControlPoints(t0, P0, P1, P2, P3);
+ const P1t1 = calculateIntermediateControlPoints(t1, P0, P1, P2, P3);
+ const bezierStyle = `cubic-bezier(${P0t0.x.toFixed(3)}, ${P0t0.y.toFixed(3)}, ${P1t1.x.toFixed(3)}, ${P1t1.y.toFixed(3)})`
+ lineSeg.style.animationTimingFunction = bezierStyle
+ lineSeg.style.animationDelay = delay + "s"
+ }
+ dataPoint.style.animationDelay = delay + "s"
+
+ let isHoveringOverData = false;
+ let isDataActive = false;
+ document.querySelector("#dataPointInfo").style.left = item.x + "px";
+ document.querySelector("#dataPointInfo").style.bottom = (point_height * item.record -3) + "px";
+ dataPoint.addEventListener("mouseenter", (e) => {
+ isDataActive = true;
+ isHoveringOverData = true;
+ const dataPoints = document.querySelectorAll(".data-point")
+ dataPoints.forEach(point => {
+ point.classList.remove("data-point-active")
+ });
+ dataPoint.classList.add("data-point-active")
+ document.querySelector("#dataPointRecord").innerText = item.record;
+ document.querySelector("#dataPointMap").innerText = item.map;
+ document.querySelector("#dataPointDate").innerText = item.date.toLocaleDateString("en-GB");
+ document.querySelector("#dataPointFirst").innerText = item.first;
+ if ((lineChart.clientWidth - 400) < item.x) {
+ document.querySelector("#dataPointInfo").style.left = item.x - 400 + "px";
+ } else {
+ document.querySelector("#dataPointInfo").style.left = item.x + "px";
+ }
+ if ((lineChart.clientHeight - 115) < (point_height * (item.record - minPortals) -3)) {
+ document.querySelector("#dataPointInfo").style.bottom = (point_height * (item.record - minPortals) -3) - 115 + "px";
+ } else {
+ document.querySelector("#dataPointInfo").style.bottom = (point_height * (item.record - minPortals) -3) + "px";
+ }
+ document.querySelector("#dataPointInfo").style.opacity = "1";
+ document.querySelector("#dataPointInfo").style.zIndex = "10";
+ });
+ document.querySelector("#dataPointInfo").addEventListener("mouseenter", (e) => {
+ isHoveringOverData = true;
+ })
+ document.querySelector("#dataPointInfo").addEventListener("mouseleave", (e) => {
+ isHoveringOverData = false;
+ })
+ document.addEventListener("mousedown", () => {
+ if (!isHoveringOverData) {
+ isDataActive = false
+ dataPoint.classList.remove("data-point-active")
+ document.querySelector("#dataPointInfo").style.opacity = "0";
+ document.querySelector("#dataPointInfo").style.zIndex = "0";
+ }
+ })
+ dataPoint.addEventListener("mouseenter", (e) => {
+ isHoveringOverData = false;
+ })
+ document.querySelector(".chart").addEventListener("mouseleave", () => {
+ isDataActive = false
+ dataPoint.classList.remove("data-point-active")
+ document.querySelector("#dataPointInfo").style.opacity = "0";
+ document.querySelector("#dataPointInfo").style.zIndex = "0";
+ })
+
+ li.appendChild(lineSeg);
+ li.appendChild(dataPoint);
+ lineChart.appendChild(li);
+ }
+ }
+
+ createGraph()
+
+ async function fetchGames() {
+ try {
+ const response = await fetch("https://lp.ardapektezol.com/api/v1/games", {
+ headers: {
+ 'Authorization': token
+ }
+ });
+
+ const data = await response.json();
+
+ const gameImg = document.querySelector(".game-img");
+
+ gameImg.style.backgroundImage = `url(${data.data[0].image})`;
+
+ // const mapImg = document.querySelectorAll(".maplist-img");
+ // mapImg.forEach((map) => {
+ // map.style.backgroundImage = `url(${data.data[0].image})`;
+ // });
+
+ } catch (error) {
+ console.log("error fetching games:", error);
+ }
+ }
+
+ detectGame();
+
+ const maplistImg = document.querySelector("#maplistImg");
+ maplistImg.src = img5;
+ const statisticsImg = document.querySelector("#statisticsImg");
+ statisticsImg.src = img6;
+
+ fetchGames();
+
+ const handleResize = (entries) => {
+ for (let entry of entries) {
+ lineChart.innerHTML = ""
+ createGraph()
+ if (document.querySelector(".maplist").getAttribute("currentTab") == "stats") {
+ document.querySelector(".stats").style.display = "block"
+ } else {
+ document.querySelector(".stats").style.display = "none"
+ }
+ }
+ };
+
+ const resizeObserver = new ResizeObserver(handleResize);
+
+ // if (scrollRef.current) {
+ // //hi
+ // if (new URLSearchParams(new URL(window.location.href).search).get("chapter")) {
+ // setTimeout(() => {
+ // scrollRef.current.scrollIntoView({ behavior: "smooth", block: "start" })
+ // }, 200);
+ // }
+
+ // }
+
+ if (divRef.current) {
+ resizeObserver.observe(divRef.current);
+ }
+
+ return () => {
+ if (divRef.current) {
+ resizeObserver.unobserve(divRef.current);
+ }
+ resizeObserver.disconnect();
+ };
+
+
+ })
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
undefined
+
undefined
+
+
+
+ 0/0
+
+
+
+
+
+
+
+
+
+
+
Portal count over time
+
+
+
+
+
+
+ Date
+ Map
+ Record
+ First completion
+
+
+
+
+
+
+ Hello
+
+
+
+
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/frontend/src/components/pages/summary.css b/frontend/src/components/pages/summary.css
index c99a0bf..8c6ec35 100644
--- a/frontend/src/components/pages/summary.css
+++ b/frontend/src/components/pages/summary.css
@@ -35,8 +35,8 @@
border: none;
transition: background-color .1s;
}
-#section1>div>.nav-button:nth-child(1){border-radius: 20px 0 0 20px;}
-#section1>div>.nav-button:nth-child(2){border-radius: 0 20px 20px 0;margin-left: 2px;}
+/* #section1>div>.nav-button:nth-child(1){border-radius: 0px;}:nth-child(1){border-radius: 20px 0 0 20px;}
+#section1>div>.nav-button:nth-child(2){border-radius: 0 20px 20px 0;margin-left: 2px;} */
.nav-button>span{padding: 0 8px 0 8px;}
.nav-button:hover{background-color: #202232;cursor: pointer;}
diff --git a/frontend/src/components/pages/summary.js b/frontend/src/components/pages/summary.js
index 0bd26af..9957c5d 100644
--- a/frontend/src/components/pages/summary.js
+++ b/frontend/src/components/pages/summary.js
@@ -1,5 +1,5 @@
-import React from 'react';
-import { useLocation } from "react-router-dom";
+import React, { useEffect } from 'react';
+import { useLocation, Link } from "react-router-dom";
import ReactMarkdown from 'react-markdown'
import "./summary.css";
@@ -317,8 +317,18 @@ if(window.confirm(`Are you sure you want to remove post: ${post.title}?`)){
}
-
if(data!==null){
+
+let current_chapter = data.map.chapter_name
+let isCoop = false;
+if (data.map.game_name == "Portal 2 - Cooperative") {
+ isCoop = true
+}
+
+current_chapter = data.map.chapter_name.split(" ")
+// current_chapter = current_chapter.split("-")
+current_chapter = current_chapter[1]
+
return (
<>
{token!==null?mod===true?
:"":""}
@@ -329,8 +339,8 @@ return (
-
-
+
+
{data.map.map_name}
--
cgit v1.2.3