diff options
| author | Nidboj132 <28981031+Nidboj132@users.noreply.github.com> | 2023-09-22 15:58:48 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-22 15:58:48 +0200 |
| commit | 57856b4222b790b3bfaff6b4ed129a99818ab88b (patch) | |
| tree | 5ba99942430dc59803fbc8086d5adf7594da0460 /frontend | |
| parent | fix: page number error on empty records (#62) (diff) | |
| download | lphub-57856b4222b790b3bfaff6b4ed129a99818ab88b.tar.gz lphub-57856b4222b790b3bfaff6b4ed129a99818ab88b.tar.bz2 lphub-57856b4222b790b3bfaff6b4ed129a99818ab88b.zip | |
added leaderboard (#53)
Former-commit-id: cca018d7af153dbeab6689f48293ee58a8c871fe
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/src/components/pages/summary.css | 138 | ||||
| -rw-r--r-- | frontend/src/components/pages/summary.js | 104 | ||||
| -rw-r--r-- | frontend/src/imgs/12.png | bin | 0 -> 1545 bytes | |||
| -rw-r--r-- | frontend/src/imgs/13.png | bin | 0 -> 1251 bytes |
4 files changed, 224 insertions, 18 deletions
diff --git a/frontend/src/components/pages/summary.css b/frontend/src/components/pages/summary.css index a0f2f5d..6ac56eb 100644 --- a/frontend/src/components/pages/summary.css +++ b/frontend/src/components/pages/summary.css | |||
| @@ -65,7 +65,7 @@ | |||
| 65 | #section3{ | 65 | #section3{ |
| 66 | margin: 40px 0 0 0; | 66 | margin: 40px 0 0 0; |
| 67 | 67 | ||
| 68 | display: grid; | 68 | display: none; |
| 69 | grid-template-columns: 1fr 1fr; | 69 | grid-template-columns: 1fr 1fr; |
| 70 | gap: 20px; | 70 | gap: 20px; |
| 71 | } | 71 | } |
| @@ -73,7 +73,7 @@ | |||
| 73 | #category{ | 73 | #category{ |
| 74 | display: grid; | 74 | display: grid; |
| 75 | height: 350px; | 75 | height: 350px; |
| 76 | border-radius: 30px; | 76 | border-radius: 24px; |
| 77 | overflow: hidden; | 77 | overflow: hidden; |
| 78 | 78 | ||
| 79 | } | 79 | } |
| @@ -121,7 +121,7 @@ p>span.portal-count{font-weight: bold;font-size: 100px;vertical-align: -15%;} | |||
| 121 | #history{ | 121 | #history{ |
| 122 | min-width: 560px; | 122 | min-width: 560px; |
| 123 | background-color: #202232; | 123 | background-color: #202232; |
| 124 | border-radius: 30px; | 124 | border-radius: 24px; |
| 125 | 125 | ||
| 126 | } | 126 | } |
| 127 | 127 | ||
| @@ -162,8 +162,8 @@ p>span.portal-count{font-weight: bold;font-size: 100px;vertical-align: -15%;} | |||
| 162 | cursor: pointer; | 162 | cursor: pointer; |
| 163 | transition: background-color .1s; | 163 | transition: background-color .1s; |
| 164 | } | 164 | } |
| 165 | #history>span>button:nth-child(1){border-radius: 0 0 0 30px;} | 165 | #history>span>button:nth-child(1){border-radius: 0 0 0 24px;} |
| 166 | #history>span>button:nth-child(2){border-radius: 0 0 30px 0;} | 166 | #history>span>button:nth-child(2){border-radius: 0 0 24px 0;} |
| 167 | 167 | ||
| 168 | #graph{ | 168 | #graph{ |
| 169 | display: grid; | 169 | display: grid; |
| @@ -239,7 +239,7 @@ p>span.portal-count{font-weight: bold;font-size: 100px;vertical-align: -15%;} | |||
| 239 | /* Section 4: Difficulty + count */ | 239 | /* Section 4: Difficulty + count */ |
| 240 | 240 | ||
| 241 | #section4{ | 241 | #section4{ |
| 242 | display: grid; | 242 | display: none; |
| 243 | grid-template-columns: 1fr 1fr; | 243 | grid-template-columns: 1fr 1fr; |
| 244 | gap: 20px; | 244 | gap: 20px; |
| 245 | margin: 40px 0 0 0; | 245 | margin: 40px 0 0 0; |
| @@ -252,7 +252,7 @@ p>span.portal-count{font-weight: bold;font-size: 100px;vertical-align: -15%;} | |||
| 252 | text-align: center; | 252 | text-align: center; |
| 253 | cursor: default; | 253 | cursor: default; |
| 254 | 254 | ||
| 255 | border-radius: 20px; | 255 | border-radius: 24px; |
| 256 | display: grid; | 256 | display: grid; |
| 257 | grid-template-rows: 20px 40px 40px; | 257 | grid-template-rows: 20px 40px 40px; |
| 258 | } | 258 | } |
| @@ -273,7 +273,7 @@ p>span.portal-count{font-weight: bold;font-size: 100px;vertical-align: -15%;} | |||
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | .difficulty-rating{ | 275 | .difficulty-rating{ |
| 276 | border-radius: 20px; | 276 | border-radius: 24px; |
| 277 | width: 40px; height: 3px; | 277 | width: 40px; height: 3px; |
| 278 | background-color: #2b2e46; | 278 | background-color: #2b2e46; |
| 279 | } | 279 | } |
| @@ -302,7 +302,7 @@ p>span.portal-count{font-weight: bold;font-size: 100px;vertical-align: -15%;} | |||
| 302 | margin: 4px; | 302 | margin: 4px; |
| 303 | float:right; | 303 | float:right; |
| 304 | border: 0; | 304 | border: 0; |
| 305 | border-radius: 20px; | 305 | border-radius: 24px; |
| 306 | width: 608px; height: 342px; | 306 | width: 608px; height: 342px; |
| 307 | } | 307 | } |
| 308 | 308 | ||
| @@ -315,6 +315,126 @@ p>span.portal-count{font-weight: bold;font-size: 100px;vertical-align: -15%;} | |||
| 315 | #description-text>b{font-size: inherit;} | 315 | #description-text>b{font-size: inherit;} |
| 316 | #description-text>a{font-size: inherit;color: #3c91e6;} | 316 | #description-text>a{font-size: inherit;color: #3c91e6;} |
| 317 | 317 | ||
| 318 | |||
| 319 | /* Section 6: leaderboards */ | ||
| 320 | #section6{ | ||
| 321 | margin: 40px 0 20px 0; | ||
| 322 | min-height: 600px; | ||
| 323 | background-color: #202232; | ||
| 324 | |||
| 325 | border-radius: 24px; | ||
| 326 | padding: 10px 10px 0 10px; | ||
| 327 | |||
| 328 | } | ||
| 329 | #leaderboard-top>span{ | ||
| 330 | display: flex; | ||
| 331 | place-items: flex-end; | ||
| 332 | } | ||
| 333 | |||
| 334 | |||
| 335 | #section6>hr{border: 1px solid #2b2e46;margin: 8px 20px 0px 20px;} | ||
| 336 | #leaderboard-top{ | ||
| 337 | display: grid; | ||
| 338 | grid-template-columns: 7.5% 25% 7.5% 25% 20% 15%; | ||
| 339 | font-size: 20px; | ||
| 340 | height: 34px; | ||
| 341 | padding-left: 60px; | ||
| 342 | margin: 0 20px 0 20px; | ||
| 343 | } | ||
| 344 | #page-number{ | ||
| 345 | display: flex; | ||
| 346 | width: auto; | ||
| 347 | flex-direction: row-reverse; | ||
| 348 | } | ||
| 349 | #page-number>div{ | ||
| 350 | width: 100px; | ||
| 351 | place-items: center; | ||
| 352 | display: grid; | ||
| 353 | grid-template-columns: 1fr 1fr 1fr; | ||
| 354 | text-align: center; | ||
| 355 | } | ||
| 356 | #page-number>div>button{ | ||
| 357 | width: 30px; | ||
| 358 | height: 30px; | ||
| 359 | background-color: #202232; | ||
| 360 | border: 0; | ||
| 361 | padding: 0; | ||
| 362 | cursor: pointer; | ||
| 363 | } | ||
| 364 | |||
| 365 | .leaderboard-record{ | ||
| 366 | margin: 10px 20px 0px 20px; | ||
| 367 | height: 44px; width: calc(100% - 40px); | ||
| 368 | width: auto; | ||
| 369 | |||
| 370 | color: inherit; | ||
| 371 | border-radius: 40px; | ||
| 372 | text-align: left; | ||
| 373 | padding: 0 0 0 60px; | ||
| 374 | font-size: 20px; | ||
| 375 | font-family: inherit; | ||
| 376 | |||
| 377 | |||
| 378 | grid-template-columns: 3% 4.5% 25% 4% 3.5% 25% 20% 15%; | ||
| 379 | display: grid; | ||
| 380 | |||
| 381 | border: 0; | ||
| 382 | transition: background-color .1s; | ||
| 383 | background-color: #2b2e46; | ||
| 384 | } | ||
| 385 | |||
| 386 | .leaderboard-record>span:nth-child(1){display: grid;} | ||
| 387 | .leaderboard-record>span:nth-child(4){display: grid;} | ||
| 388 | .leaderboard-record>span:last-child{flex-direction: row-reverse;} | ||
| 389 | .leaderboard-record>span{ | ||
| 390 | display: flex; | ||
| 391 | place-items: center; | ||
| 392 | height: 44px; | ||
| 393 | } | ||
| 394 | .leaderboard-record>span>img{ | ||
| 395 | height: 36px; | ||
| 396 | border-radius: 50px; | ||
| 397 | padding: 0; | ||
| 398 | scale: .95; | ||
| 399 | } | ||
| 400 | .leaderboard-record>span>button{ | ||
| 401 | background-color: #0000; | ||
| 402 | border: 0; | ||
| 403 | cursor: pointer; | ||
| 404 | transition: opacity 0.1s; | ||
| 405 | } | ||
| 406 | |||
| 407 | .hover-popup { | ||
| 408 | position: relative; | ||
| 409 | } | ||
| 410 | |||
| 411 | .hover-popup::after { | ||
| 412 | content: attr(popup-text); | ||
| 413 | position: absolute; | ||
| 414 | /* top: 0%; */ | ||
| 415 | /* left: 80%; */ | ||
| 416 | /* transform: translateX(-100%); */ | ||
| 417 | /* padding: 5px; */ | ||
| 418 | background-color: #2b2e46; | ||
| 419 | /* border: 1px solid #161723; */ | ||
| 420 | border-radius: 8px; | ||
| 421 | visibility: hidden; | ||
| 422 | opacity: 0; | ||
| 423 | /* transition: visibility 0s, opacity 0.3s ease; */ | ||
| 424 | } | ||
| 425 | |||
| 426 | .hover-popup:hover::after { | ||
| 427 | visibility: visible; | ||
| 428 | opacity: 1; | ||
| 429 | } | ||
| 430 | |||
| 431 | .leaderboard-record:last-child{margin: 10px 20px 10px 20px;} | ||
| 432 | |||
| 433 | |||
| 434 | |||
| 435 | |||
| 436 | |||
| 437 | |||
| 318 | .triangle{ | 438 | .triangle{ |
| 319 | display: inline-block; | 439 | display: inline-block; |
| 320 | width: 8px; height: 0; | 440 | width: 8px; height: 0; |
diff --git a/frontend/src/components/pages/summary.js b/frontend/src/components/pages/summary.js index 276389f..deb5fd2 100644 --- a/frontend/src/components/pages/summary.js +++ b/frontend/src/components/pages/summary.js | |||
| @@ -7,6 +7,8 @@ import "./summary.css"; | |||
| 7 | import img4 from "../../imgs/4.png" | 7 | import img4 from "../../imgs/4.png" |
| 8 | import img5 from "../../imgs/5.png" | 8 | import img5 from "../../imgs/5.png" |
| 9 | import img6 from "../../imgs/6.png" | 9 | import img6 from "../../imgs/6.png" |
| 10 | import img12 from "../../imgs/12.png" | ||
| 11 | import img13 from "../../imgs/13.png" | ||
| 10 | import Modview from "./summary_modview.js" | 12 | import Modview from "./summary_modview.js" |
| 11 | 13 | ||
| 12 | export default function Summary(prop) { | 14 | export default function Summary(prop) { |
| @@ -28,7 +30,15 @@ const fakedata={} //for debug | |||
| 28 | // eslint-disable-next-line | 30 | // eslint-disable-next-line |
| 29 | }, []); | 31 | }, []); |
| 30 | 32 | ||
| 31 | 33 | const [pageNumber, setPageNumber] = React.useState(1); | |
| 34 | const [lbData, setLbData] = React.useState(null); | ||
| 35 | React.useEffect(() => { | ||
| 36 | fetch(`https://lp.ardapektezol.com/api/v1/maps/${location.pathname.split('/')[2]}/leaderboards?page=${pageNumber}`) | ||
| 37 | .then(r => r.json()) | ||
| 38 | .then(d => setLbData(d)) | ||
| 39 | console.log(lbData) | ||
| 40 | // eslint-disable-next-line | ||
| 41 | }, [pageNumber]); | ||
| 32 | 42 | ||
| 33 | 43 | ||
| 34 | 44 | ||
| @@ -40,6 +50,11 @@ function NavClick() { | |||
| 40 | const btn = document.querySelectorAll("#section2 button.nav-button"); | 50 | const btn = document.querySelectorAll("#section2 button.nav-button"); |
| 41 | btn.forEach((e) => {e.style.backgroundColor = "#2b2e46"}); | 51 | btn.forEach((e) => {e.style.backgroundColor = "#2b2e46"}); |
| 42 | btn[navState].style.backgroundColor = "#202232"; | 52 | btn[navState].style.backgroundColor = "#202232"; |
| 53 | |||
| 54 | document.querySelectorAll("section").forEach((e,i)=>i>=2?e.style.display="none":"") | ||
| 55 | if(navState === 0){document.querySelectorAll(".summary1").forEach((e) => {e.style.display = "grid"});} | ||
| 56 | if(navState === 1){document.querySelectorAll(".summary2").forEach((e) => {e.style.display = "block"});} | ||
| 57 | if(navState === 2){document.querySelectorAll(".summary3").forEach((e) => {e.style.display = "block"});} | ||
| 43 | }} | 58 | }} |
| 44 | 59 | ||
| 45 | 60 | ||
| @@ -108,7 +123,6 @@ function graph(state) { | |||
| 108 | <span><br/></span> | 123 | <span><br/></span> |
| 109 | )) | 124 | )) |
| 110 | case 2: // graph | 125 | case 2: // graph |
| 111 | let i = 1 | ||
| 112 | let g = 0 | 126 | let g = 0 |
| 113 | let h = 0 | 127 | let h = 0 |
| 114 | return graph_numbers.map((e,j)=>( | 128 | return graph_numbers.map((e,j)=>( |
| @@ -123,11 +137,11 @@ function graph(state) { | |||
| 123 | <td className='graph_ver' | 137 | <td className='graph_ver' |
| 124 | data-graph={ h++ } | 138 | data-graph={ h++ } |
| 125 | style={{outline: | 139 | style={{outline: |
| 126 | g==h-1 ? | 140 | g===h-1 ? |
| 127 | "1px solid #2b2e46" : g>=h ? "1px dashed white" : "0" }} | 141 | "1px solid #2b2e46" : g>=h ? "1px dashed white" : "0" }} |
| 128 | ></td> | 142 | ></td> |
| 129 | 143 | ||
| 130 | {g==h && graph_score.includes(graph_max-j) ? | 144 | {g===h && graph_score.includes(graph_max-j) ? |
| 131 | <button className='graph-button' | 145 | <button className='graph-button' |
| 132 | onClick={()=>{ | 146 | onClick={()=>{ |
| 133 | selectRun(graph_dates.length-(i-1),catState); | 147 | selectRun(graph_dates.length-(i-1),catState); |
| @@ -189,6 +203,29 @@ function YouTubeGetID(url){ | |||
| 189 | return (url[2] !== undefined) ? url[2].split(/[^0-9a-z_]/i)[0] : url[0]; | 203 | return (url[2] !== undefined) ? url[2].split(/[^0-9a-z_]/i)[0] : url[0]; |
| 190 | } | 204 | } |
| 191 | 205 | ||
| 206 | function TimeAgo(date) { | ||
| 207 | const seconds = Math.floor((new Date() - date) / 1000); | ||
| 208 | |||
| 209 | let interval = Math.floor(seconds / 31536000); | ||
| 210 | if (interval > 1) {return interval + ' years ago';} | ||
| 211 | |||
| 212 | interval = Math.floor(seconds / 2592000); | ||
| 213 | if (interval > 1) {return interval + ' months ago';} | ||
| 214 | |||
| 215 | interval = Math.floor(seconds / 86400); | ||
| 216 | if (interval > 1) {return interval + ' days ago';} | ||
| 217 | |||
| 218 | interval = Math.floor(seconds / 3600); | ||
| 219 | if (interval > 1) {return interval + ' hours ago';} | ||
| 220 | |||
| 221 | interval = Math.floor(seconds / 60); | ||
| 222 | if (interval > 1) {return interval + ' minutes ago';} | ||
| 223 | |||
| 224 | if(seconds < 10) return 'just now'; | ||
| 225 | |||
| 226 | return Math.floor(seconds) + ' seconds ago'; | ||
| 227 | }; | ||
| 228 | |||
| 192 | if(data!==null){ | 229 | if(data!==null){ |
| 193 | return ( | 230 | return ( |
| 194 | <> | 231 | <> |
| @@ -213,8 +250,7 @@ return ( | |||
| 213 | <button className='nav-button' onClick={()=>setNavState(1)}><img src={img5} alt="" /><span>Leaderboards</span></button> | 250 | <button className='nav-button' onClick={()=>setNavState(1)}><img src={img5} alt="" /><span>Leaderboards</span></button> |
| 214 | <button className='nav-button' onClick={()=>setNavState(2)}><img src={img6} alt="" /><span>Discussions</span></button> | 251 | <button className='nav-button' onClick={()=>setNavState(2)}><img src={img6} alt="" /><span>Discussions</span></button> |
| 215 | </section> | 252 | </section> |
| 216 | 253 | <section id='section3' className='summary1'> | |
| 217 | <section id='section3'> | ||
| 218 | <div id='category' | 254 | <div id='category' |
| 219 | style={data.map.image===""?{backgroundColor:"#202232"}:{}}> | 255 | style={data.map.image===""?{backgroundColor:"#202232"}:{}}> |
| 220 | <img src={data.map.image} alt="" id='category-image'></img> | 256 | <img src={data.map.image} alt="" id='category-image'></img> |
| @@ -279,7 +315,7 @@ return ( | |||
| 279 | 315 | ||
| 280 | 316 | ||
| 281 | </section> | 317 | </section> |
| 282 | <section id='section4'> | 318 | <section id='section4' className='summary1'> |
| 283 | <div id='difficulty'> | 319 | <div id='difficulty'> |
| 284 | <span>Difficulty</span> | 320 | <span>Difficulty</span> |
| 285 | {data.summary.routes.sort((a,b)=>a.category.id - b.category.id)[selectedRun].rating === 0 ? (<span style={{color:"lime"}}>Very easy</span>):null} | 321 | {data.summary.routes.sort((a,b)=>a.category.id - b.category.id)[selectedRun].rating === 0 ? (<span style={{color:"lime"}}>Very easy</span>):null} |
| @@ -301,7 +337,7 @@ return ( | |||
| 301 | </div> | 337 | </div> |
| 302 | </section> | 338 | </section> |
| 303 | 339 | ||
| 304 | <section id='section5'> | 340 | <section id='section5' className='summary1'> |
| 305 | <div id='description'> | 341 | <div id='description'> |
| 306 | {data.summary.routes.sort((a,b)=>a.category.id - b.category.id)[selectedRun].showcase!=="" ? | 342 | {data.summary.routes.sort((a,b)=>a.category.id - b.category.id)[selectedRun].showcase!=="" ? |
| 307 | <iframe title='Showcase video' src={vid}> </iframe> | 343 | <iframe title='Showcase video' src={vid}> </iframe> |
| @@ -312,9 +348,59 @@ return ( | |||
| 312 | {data.summary.routes.sort((a,b)=>a.category.id - b.category.id)[selectedRun].description} | 348 | {data.summary.routes.sort((a,b)=>a.category.id - b.category.id)[selectedRun].description} |
| 313 | </ReactMarkdown> | 349 | </ReactMarkdown> |
| 314 | </span> | 350 | </span> |
| 315 | </div> | 351 | </div> |
| 352 | </section> | ||
| 353 | |||
| 354 | {lbData===null?( | ||
| 355 | <section id='section6' className='summary2'> | ||
| 356 | <h1 style={{textAlign:"center"}}>Map is not available for competitive boards.</h1> | ||
| 357 | </section> | ||
| 358 | ):lbData.data.records.length===0?( | ||
| 359 | <section id='section6' className='summary2'> | ||
| 360 | <h1 style={{textAlign:"center"}}>No records found.</h1> | ||
| 361 | </section> | ||
| 362 | ):( | ||
| 363 | <section id='section6' className='summary2'> | ||
| 316 | 364 | ||
| 365 | <div id='leaderboard-top'> | ||
| 366 | <span>Place</span> | ||
| 367 | <span>Runner</span> | ||
| 368 | <span>Portals</span> | ||
| 369 | <span>Time</span> | ||
| 370 | <span>Date</span> | ||
| 371 | <div id='page-number'> | ||
| 372 | <div> | ||
| 373 | |||
| 374 | <button onClick={() => pageNumber === 1 ? null : setPageNumber(prevPageNumber => prevPageNumber - 1)} | ||
| 375 | ><i className='triangle' style={{position:'relative',left:'-5px',}}></i> </button> | ||
| 376 | <span>{lbData.data.pagination.current_page}/{lbData.data.pagination.total_pages}</span> | ||
| 377 | <button onClick={() => pageNumber === lbData.data.pagination.total_pages ? null : setPageNumber(prevPageNumber => prevPageNumber + 1)} | ||
| 378 | ><i className='triangle' style={{position:'relative',left:'5px',transform:'rotate(180deg)'}}></i> </button> | ||
| 379 | </div> | ||
| 380 | </div> | ||
| 381 | </div> | ||
| 382 | <hr/> | ||
| 383 | <div id='leaderboard-records'> | ||
| 384 | {lbData.data.records.map((r, index) => ( | ||
| 385 | <span className='leaderboard-record' key={index} > | ||
| 386 | <span>{r.placement}</span> | ||
| 387 | <span> </span> | ||
| 388 | <span><img src={r.user.avatar_link} alt='' /> {r.user.user_name}</span> | ||
| 389 | <span>{r.score_count}</span> | ||
| 390 | <span> </span> | ||
| 391 | <span>{r.score_time}</span> | ||
| 392 | <span className='hover-popup' popup-text={r.record_date.replace("T",' ').split(".")[0]}>{ TimeAgo(new Date(r.record_date.replace("T"," ").replace("Z",""))) }</span> | ||
| 393 | <span> | ||
| 394 | <button onClick={()=>{window.alert(r.demo_id)}}><img src={img13} alt="demo_id" /></button> | ||
| 395 | <button onClick={()=>window.location.href=`https://lp.ardapektezol.com/api/v1/demos?uuid=${r.demo_id}`}><img src={img12} alt="download" /></button> | ||
| 396 | </span> | ||
| 397 | </span> | ||
| 398 | ))} | ||
| 399 | {console.log(lbData.data.records.length)} | ||
| 400 | </div> | ||
| 317 | </section> | 401 | </section> |
| 402 | )} | ||
| 403 | |||
| 318 | </main> | 404 | </main> |
| 319 | </> | 405 | </> |
| 320 | ) | 406 | ) |
diff --git a/frontend/src/imgs/12.png b/frontend/src/imgs/12.png new file mode 100644 index 0000000..abb7717 --- /dev/null +++ b/frontend/src/imgs/12.png | |||
| Binary files differ | |||
diff --git a/frontend/src/imgs/13.png b/frontend/src/imgs/13.png new file mode 100644 index 0000000..28a67c5 --- /dev/null +++ b/frontend/src/imgs/13.png | |||
| Binary files differ | |||