From 83d2243c65bf5fce5c75ef3753595d38f4d545d5 Mon Sep 17 00:00:00 2001 From: Wolfboy248 <121288977+Wolfboy248@users.noreply.github.com> Date: Sat, 13 Jul 2024 00:15:58 +0200 Subject: feat: fixes, styles, partial homepage implementation and maplist header loader (#188) --- frontend/src/App.css | 10 + frontend/src/App.js | 2 +- frontend/src/components/pages/home.css | 12 +- frontend/src/components/pages/home.js | 125 ++++++++--- frontend/src/components/pages/maplist.css | 12 +- frontend/src/components/pages/maplist.js | 341 +++++++++++++++++------------- frontend/src/components/sidebar.js | 1 - 7 files changed, 313 insertions(+), 190 deletions(-) diff --git a/frontend/src/App.css b/frontend/src/App.css index c43738b..65e35de 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -8,6 +8,16 @@ body { animation: loader 1.2s ease infinite; background-size: 400% 300%; background-image: linear-gradient(-90deg, #202232 0%, #202232 25%, #2a2c41 50%, #202232 75%, #202232 100%); + user-select: none; +} + +.loader-text { + animation: loader 1.2s ease infinite; + background-size: 400% 300%; + background-image: linear-gradient(-90deg, #202232 0%, #202232 25%, #2a2c41 50%, #202232 75%, #202232 100%); + user-select: none; + color: #00000000; + border-radius: 1000px; } @keyframes loader { diff --git a/frontend/src/App.js b/frontend/src/App.js index 5b68ae5..d96fa88 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -28,7 +28,7 @@ export default function App() { - }> + }> }> }> }> diff --git a/frontend/src/components/pages/home.css b/frontend/src/components/pages/home.css index 072b12b..e5a8eab 100644 --- a/frontend/src/components/pages/home.css +++ b/frontend/src/components/pages/home.css @@ -68,9 +68,11 @@ .recommended-map-img { width: 250px; - border-radius: 24px; + border-radius: 19px; margin-bottom: 0; - border: 7px solid #2B2E46; + /* border: 7px solid #2B2E46; */ + background-size: cover; + background-position-x: 50%; } .difficulty-bar-home { @@ -78,13 +80,13 @@ display: grid; grid-template-columns: 20% 20% 20% 20% 20%; align-items: center; - margin: 5px; - margin-top: 16px; + margin: 0px; + margin-top: 7px; } .difficulty-point { background: #2B2E46; - height: 3px; + height: 4px; margin: 5px; border-radius: 10px; } diff --git a/frontend/src/components/pages/home.js b/frontend/src/components/pages/home.js index c1477ab..55e58a8 100644 --- a/frontend/src/components/pages/home.js +++ b/frontend/src/components/pages/home.js @@ -4,14 +4,45 @@ import { useLocation, Link } from "react-router-dom"; import "./home.css" import News from '../news'; import Record from '../record'; +import Login from '../login'; export default function Homepage(prop) { - const {token, setToken} = prop + const { token, setToken } = prop const [home, setHome] = React.useState(null); + const [profile, setProfile] = React.useState(null); + const [loading, setLoading] = React.useState(true) const location = useLocation(); + const [isLoggedIn, setIsLoggedIn] = React.useState(false); + React.useEffect(() => { + try { + fetch(`https://lp.ardapektezol.com/api/v1/profile`, { + headers: { + 'Content-Type': 'application/json', + Authorization: token + } + }) + .then(r => r.json()) + .then(d => setProfile(d.data)) + .then(d => { + if (profile != null) { + setIsLoggedIn(true) + } + }) + .then(d => { + setLoading(false) + }) + } catch (error) { + console.log(error) + } + + }, [token, profile]); + useEffect(() => { async function fetchMapImg() { + if (!isLoggedIn) { + return; + } try { const response = await fetch("https://lp.ardapektezol.com/api/v1/games", { headers: { @@ -23,11 +54,11 @@ export default function Homepage(prop) { const recommendedMapImg = document.querySelector("#recommendedMapImg"); - recommendedMapImg.src = `${data.data[0].image}` + recommendedMapImg.style.backgroundImage = `url(${data.data[0].image})` const column1 = document.querySelector("#column1"); const column2 = document.querySelector("#column2"); - + column2.style.height = column1.clientHeight + "px"; } catch (error) { console.log(error) @@ -115,41 +146,57 @@ export default function Homepage(prop) { }, ] + if (loading) { + return ( +
+
+ ) + } + return (
-
- Welcome back,
- Krzyhau +
+

Home

+ {isLoggedIn ? +
+ Welcome back,
+ + Wolfboy248 +
+ : null}
-
+
{/* Column 1 */} + {isLoggedIn ?
-
+
- Overall rank
- #69 + Overall rank
+ {profile.rankings.overall.rank > 0 ? "#" + profile.rankings.overall.rank : "No rank"}
- Singleplayer
- #10 (60/62) + Singleplayer
+ {profile.rankings.singleplayer.rank > 0 ? "#" + profile.rankings.singleplayer.rank : "No rank"} {profile.rankings.singleplayer.rank > 0 ? "(" + profile.rankings.singleplayer.completion_count + "/" + profile.rankings.singleplayer.completion_total + ")" : ""}
- Overall rank
- #69 (13/37) + Cooperative rank
+ {profile.rankings.cooperative.rank > 0 ? "#" + profile.rankings.cooperative.rank : "No rank"} {profile.rankings.cooperative.rank > 0 ? "(" + profile.rankings.cooperative.completion_count + "/" + profile.rankings.cooperative.completion_total + ")" : ""}
+ : null} + {isLoggedIn ?
-
- -
- Container Ride - Your Record: 4 portals - World Record: 2 portals +
+
+
+ Container Ride + Your Record: 4 portals + World Record: 2 portals
-
+
@@ -158,17 +205,39 @@ export default function Homepage(prop) {
-
+ : null} +
Place - Runner + Runner Portals Time Date
-
+
+ + + + + + + + + + + + + + + + + + + + + @@ -180,9 +249,9 @@ export default function Homepage(prop) {
{/* Column 2 */} -
+
-
+
{newsList.map((newsList, index) => ( ))} @@ -190,9 +259,9 @@ export default function Homepage(prop) {
- - + +
) } \ No newline at end of file diff --git a/frontend/src/components/pages/maplist.css b/frontend/src/components/pages/maplist.css index 2f279c3..b56aacc 100644 --- a/frontend/src/components/pages/maplist.css +++ b/frontend/src/components/pages/maplist.css @@ -52,7 +52,7 @@ a { .game { width: 100%; height: 192px; - background: #202232; + /* background: #202232; */ border-radius: 24px; overflow: hidden; } @@ -112,18 +112,22 @@ a { align-items: center; } -.game-nav-btn:hover, .selected { - background-color: #202232; +.game-nav-btn:hover { cursor: pointer; } +.selected { + background-color: #202232; +} + .gameview-nav { margin-top: 20px; display: flex; height: 56px; border-radius: 24px; overflow: hidden; - background-color: #202232; + gap: 0.06em; + /* background-color: #202232; */ } .maplist { diff --git a/frontend/src/components/pages/maplist.js b/frontend/src/components/pages/maplist.js index a7464e9..a5c6c19 100644 --- a/frontend/src/components/pages/maplist.js +++ b/frontend/src/components/pages/maplist.js @@ -1,5 +1,5 @@ import React, { useEffect, useRef, useState } from 'react'; -import { useLocation, Link } from "react-router-dom"; +import { useLocation, Link } from "react-router-dom"; import { BrowserRouter as Router, Route, Routes, useNavigate } from 'react-router-dom'; import "./maplist.css" @@ -7,12 +7,16 @@ import img5 from "../../imgs/5.png" import img6 from "../../imgs/6.png" export default function Maplist(prop) { - const {token,setToken} = prop + const { token, setToken } = prop const scrollRef = useRef(null) const [games, setGames] = React.useState(null); + const [hasOpenedStatistics, setHasOpenedStatistics] = React.useState(false); + const [totalPortals, setTotalPortals] = React.useState(0); + const [loading, setLoading] = React.useState(true) const location = useLocation(); - - let gameTitle; + + const [gameTitle, setGameTitle] = React.useState(""); + const [catPortalCount, setCatPortalCount] = React.useState(0); let minPage; let maxPage; let currentPage; @@ -33,23 +37,21 @@ export default function Maplist(prop) { const params = new URLSearchParams(url.search) gameState = parseFloat(location.pathname.split("/")[2]) - document.querySelector("#catPortalCount").innerText = data.data[gameState - 1].category_portals[0].portal_count; - - if (gameState == 1){ - gameTitle = data.data[0].name; + if (gameState == 1) { + setGameTitle(data.data[0].name); maxPage = 9; minPage = 1; createCategories(1); - } else if (gameState == 2){ - gameTitle = data.data[1].name; + } else if (gameState == 2) { + setGameTitle(data.data[1].name); maxPage = 16; minPage = 10; add = 10 createCategories(2); } - + let chapterParam = params.get("chapter") currentPage = minPage; @@ -60,14 +62,22 @@ export default function Maplist(prop) { changePage(currentPage); + // if (!loading) { + + // document.querySelector("#catPortalCount").innerText = data.data[gameState - 1].category_portals[0].portal_count; + + // } + + setCatPortalCount(data.data[gameState - 1].category_portals[0].portal_count); + // 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) => { + const maplistBtns = document.querySelectorAll("#maplistBtn"); + maplistBtns.forEach((btn, i) => { if (i == index) { btn.className = "game-nav-btn selected" @@ -78,9 +88,10 @@ export default function Maplist(prop) { } 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"); + setHasOpenedStatistics(true); } } else { btn.className = "game-nav-btn"; @@ -106,6 +117,8 @@ export default function Maplist(prop) { categoriesArr.forEach((category) => { createCategory(category); }); + + setLoading(false); } let categoryNum = 0; @@ -131,6 +144,12 @@ export default function Maplist(prop) { } async function changeCategory(category, btn) { + const navBtns = document.querySelectorAll("#catBtn"); + navBtns.forEach((btns) => { + btns.classList.remove("selected"); + }); + + btn.srcElement.classList.add("selected"); const response = await fetch("https://lp.ardapektezol.com/api/v1/games", { headers: { 'Authorization': token @@ -139,19 +158,13 @@ export default function Maplist(prop) { 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"); + // console.log(catState) 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"); @@ -165,7 +178,7 @@ export default function Maplist(prop) { 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]; @@ -195,13 +208,10 @@ export default function Maplist(prop) { 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 { @@ -263,10 +273,10 @@ export default function Maplist(prop) { difficultyPoint3.className = "difficulty-point"; difficultyPoint4.className = "difficulty-point"; difficultyPoint5.className = "difficulty-point"; - + maplistTitle.innerText = mapName; - difficultyLabel.innerText = "Difficulty: " + difficultyLabel.innerText = "Difficulty: " maplistPortalcountPortals.innerText = "portals" b.innerText = mapPortalCount; maplistImg.style.backgroundImage = `url(${mapImage})`; @@ -301,7 +311,7 @@ export default function Maplist(prop) { } async function fetchMaps(chapterID) { - try{ + try { const response = await fetch(`https://lp.ardapektezol.com/api/v1/chapters/${chapterID}`, { headers: { 'Authorization': token @@ -349,92 +359,108 @@ export default function Maplist(prop) { React.useEffect(() => { const lineChart = document.querySelector(".line-chart") - function createGraph() { + let tempTotalPortals = 0 + fetch("https://lp.ardapektezol.com/api/v1/games/1/maps", { + headers: { + 'Authorization': token + } + }) + .then(r => r.json()) + .then(d => { + d.data.maps.forEach((map, i) => { + tempTotalPortals += map.portal_count + }) + }) + .then(() => { + setTotalPortals(tempTotalPortals) + }) + async function createGraph() { + console.log(totalPortals) // max let items = [ { - record: "100", - date: new Date(2011, 4, 4), - map: "Container Ride", - first: "tiny zach" + 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: "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: "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: "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: "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: "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: "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: "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: "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: "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: "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: "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: "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" + record: "74", + date: new Date(2024, 4, 4), + map: "Container Ride", + first: "tiny zach" }, ] @@ -449,7 +475,7 @@ export default function Maplist(prop) { 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; @@ -474,7 +500,7 @@ export default function Maplist(prop) { 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") @@ -493,7 +519,7 @@ export default function Maplist(prop) { yearSpan.style.fontSize = "22px" yearSpan.style.opacity = "0.8" lineChart.appendChild(yearSpan) - + } let maxPortals; @@ -529,19 +555,19 @@ export default function Maplist(prop) { 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; + 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; + 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; @@ -587,11 +613,11 @@ export default function Maplist(prop) { 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.width = "100%" + placeholderDiv.style.height = "2px" placeholderDiv.style.backgroundColor = "#2B2E46" placeholderDiv.style.zIndex = "0" - + if (index == 0) { lineChart.appendChild(numPortalsTextBottom) } @@ -627,11 +653,11 @@ export default function Maplist(prop) { lineSeg.style.animationDelay = delay + "s" } dataPoint.style.animationDelay = delay + "s" - + let isHoveringOverData = true; let isDataActive = false; document.querySelector("#dataPointInfo").style.left = item.x + "px"; - document.querySelector("#dataPointInfo").style.bottom = (point_height * item.record -3) + "px"; + document.querySelector("#dataPointInfo").style.bottom = (point_height * item.record - 3) + "px"; dataPoint.addEventListener("mouseenter", (e) => { isDataActive = true; isHoveringOverData = true; @@ -645,14 +671,14 @@ export default function Maplist(prop) { 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"; + document.querySelector("#dataPointInfo").style.left = item.x - 400 + "px"; } else { - document.querySelector("#dataPointInfo").style.left = item.x + "px"; + 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"; + 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.bottom = (point_height * (item.record - minPortals) - 3) + "px"; } document.querySelector("#dataPointInfo").style.opacity = "1"; document.querySelector("#dataPointInfo").style.zIndex = "10"; @@ -689,8 +715,6 @@ export default function Maplist(prop) { } } - createGraph() - async function fetchGames() { try { const response = await fetch("https://lp.ardapektezol.com/api/v1/games", { @@ -726,40 +750,42 @@ export default function Maplist(prop) { const handleResize = (entries) => { for (let entry of entries) { - lineChart.innerHTML = "" - createGraph() + if (hasOpenedStatistics) { + 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) { + }; + + 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 () => { + } + + return () => { if (divRef.current) { resizeObserver.unobserve(divRef.current); } resizeObserver.disconnect(); - }; + }; + - }) return (
@@ -769,36 +795,49 @@ export default function Maplist(prop) { Games list -   + {!loading ? + {gameTitle} + : + LOADINGLOADING}
-
-
-
- 0 - portals + {!loading ? +
+
+
+ {catPortalCount} + portals +
-
- -
-
+ :
+
+
+ 00 + portals +
+
} + {!loading ? +
+
+ :
+
}
-
- undefined
+ undefined
undefined
@@ -810,19 +849,19 @@ export default function Maplist(prop) {
- +
-
+
- Portal count over time
+ Portal count over time
-
+
Date @@ -839,7 +878,7 @@ export default function Maplist(prop) {
    - +
diff --git a/frontend/src/components/sidebar.js b/frontend/src/components/sidebar.js index 08e9c6e..1ca17e6 100644 --- a/frontend/src/components/sidebar.js +++ b/frontend/src/components/sidebar.js @@ -46,7 +46,6 @@ const [sidebar, setSidebar] = React.useState(); // Clicked buttons function SidebarClick(x){ const btn = document.querySelectorAll("button.sidebar-button"); -console.log(x) if(sidebar===1){setSidebar(0);SidebarHide()} -- cgit v1.2.3