aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/components')
-rw-r--r--frontend/src/components/ConfirmDialog.tsx32
-rw-r--r--frontend/src/components/Discussions.tsx16
-rw-r--r--frontend/src/components/GameCategory.tsx22
-rw-r--r--frontend/src/components/GameEntry.tsx6
-rw-r--r--frontend/src/components/Leaderboards.tsx144
-rw-r--r--frontend/src/components/Login.tsx10
-rw-r--r--frontend/src/components/MapEntry.tsx10
-rw-r--r--frontend/src/components/MessageDialog.tsx30
-rw-r--r--frontend/src/components/MessageDialogLoad.tsx30
-rw-r--r--frontend/src/components/ModMenu.tsx18
-rw-r--r--frontend/src/components/RankingEntry.tsx58
-rw-r--r--frontend/src/components/Sidebar.tsx42
-rw-r--r--frontend/src/components/Summary.tsx12
-rw-r--r--frontend/src/components/UploadRunDialog.tsx22
14 files changed, 226 insertions, 226 deletions
diff --git a/frontend/src/components/ConfirmDialog.tsx b/frontend/src/components/ConfirmDialog.tsx
index 44a653b..d8784d2 100644
--- a/frontend/src/components/ConfirmDialog.tsx
+++ b/frontend/src/components/ConfirmDialog.tsx
@@ -1,4 +1,4 @@
1import React from 'react'; 1import React from "react";
2 2
3import "@css/Dialog.css" 3import "@css/Dialog.css"
4 4
@@ -10,22 +10,22 @@ interface ConfirmDialogProps {
10}; 10};
11 11
12const ConfirmDialog: React.FC<ConfirmDialogProps> = ({ title, subtitle, onConfirm, onCancel }) => { 12const ConfirmDialog: React.FC<ConfirmDialogProps> = ({ title, subtitle, onConfirm, onCancel }) => {
13 return ( 13 return (
14 <div className='dimmer'> 14 <div className='dimmer'>
15 <div className='dialog'> 15 <div className='dialog'>
16 <div className='dialog-element dialog-header'> 16 <div className='dialog-element dialog-header'>
17 <span>{title}</span> 17 <span>{title}</span>
18 </div>
19 <div className='dialog-element dialog-description'>
20 <span>{subtitle}</span>
21 </div>
22 <div className='dialog-element dialog-btns-container'>
23 <button onClick={onCancel}>Cancel</button>
24 <button onClick={onConfirm}>Confirm</button>
25 </div>
26 </div>
27 </div> 18 </div>
28 ) 19 <div className='dialog-element dialog-description'>
20 <span>{subtitle}</span>
21 </div>
22 <div className='dialog-element dialog-btns-container'>
23 <button onClick={onCancel}>Cancel</button>
24 <button onClick={onConfirm}>Confirm</button>
25 </div>
26 </div>
27 </div>
28 )
29}; 29};
30 30
31export default ConfirmDialog; 31export default ConfirmDialog;
diff --git a/frontend/src/components/Discussions.tsx b/frontend/src/components/Discussions.tsx
index 17ae586..0c37355 100644
--- a/frontend/src/components/Discussions.tsx
+++ b/frontend/src/components/Discussions.tsx
@@ -1,12 +1,12 @@
1import React from 'react'; 1import React from "react";
2 2
3import { MapDiscussion, MapDiscussions, MapDiscussionsDetail } from '@customTypes/Map'; 3import { MapDiscussion, MapDiscussions, MapDiscussionsDetail } from "@customTypes/Map";
4import { MapDiscussionCommentContent, MapDiscussionContent } from '@customTypes/Content'; 4import { MapDiscussionContent } from "@customTypes/Content";
5import { time_ago } from '@utils/Time'; 5import { time_ago } from "@utils/Time";
6import { API } from '@api/Api'; 6import { API } from "@api/Api";
7import "@css/Maps.css" 7import "@css/Maps.css"
8import { Link } from 'react-router-dom'; 8import { Link } from "react-router-dom";
9import useConfirm from '@hooks/UseConfirm'; 9import useConfirm from "@hooks/UseConfirm";
10 10
11interface DiscussionsProps { 11interface DiscussionsProps {
12 token?: string 12 token?: string
@@ -141,7 +141,7 @@ const Discussions: React.FC<DiscussionsProps> = ({ token, data, isModerator, map
141 data ? 141 data ?
142 (<> 142 (<>
143 {data.discussions.filter(f => f.title.includes(discussionSearch)).sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()) 143 {data.discussions.filter(f => f.title.includes(discussionSearch)).sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime())
144 .map((e, i) => ( 144 .map((e) => (
145 <div id='discussion-post'> 145 <div id='discussion-post'>
146 <button key={e.id} onClick={() => _open_map_discussion(e.id)}> 146 <button key={e.id} onClick={() => _open_map_discussion(e.id)}>
147 <span>{e.title}</span> 147 <span>{e.title}</span>
diff --git a/frontend/src/components/GameCategory.tsx b/frontend/src/components/GameCategory.tsx
index d8879ef..0d76d3e 100644
--- a/frontend/src/components/GameCategory.tsx
+++ b/frontend/src/components/GameCategory.tsx
@@ -1,7 +1,7 @@
1import React from 'react'; 1import React from "react";
2import { Link } from "react-router-dom"; 2import { Link } from "react-router-dom";
3 3
4import { Game, GameCategoryPortals } from '@customTypes/Game'; 4import { Game, GameCategoryPortals } from "@customTypes/Game";
5import "@css/Games.css" 5import "@css/Games.css"
6 6
7interface GameCategoryProps { 7interface GameCategoryProps {
@@ -10,15 +10,15 @@ interface GameCategoryProps {
10} 10}
11 11
12const GameCategory: React.FC<GameCategoryProps> = ({cat, game}) => { 12const GameCategory: React.FC<GameCategoryProps> = ({cat, game}) => {
13 return ( 13 return (
14 <Link className="games-page-item-body-item" to={"/games/" + game.id + "?cat=" + cat.category.id}> 14 <Link className="games-page-item-body-item" to={"/games/" + game.id + "?cat=" + cat.category.id}>
15 <div> 15 <div>
16 <span className='games-page-item-body-item-title'>{cat.category.name}</span> 16 <span className='games-page-item-body-item-title'>{cat.category.name}</span>
17 <br /> 17 <br />
18 <span className='games-page-item-body-item-num'>{cat.portal_count}</span> 18 <span className='games-page-item-body-item-num'>{cat.portal_count}</span>
19 </div> 19 </div>
20 </Link> 20 </Link>
21 ) 21 )
22} 22}
23 23
24export default GameCategory; 24export default GameCategory;
diff --git a/frontend/src/components/GameEntry.tsx b/frontend/src/components/GameEntry.tsx
index 3bd2842..454efb1 100644
--- a/frontend/src/components/GameEntry.tsx
+++ b/frontend/src/components/GameEntry.tsx
@@ -1,10 +1,10 @@
1import React from 'react'; 1import React from "react";
2import { Link } from "react-router-dom"; 2import { Link } from "react-router-dom";
3 3
4import { Game, GameCategoryPortals } from '@customTypes/Game'; 4import { Game, GameCategoryPortals } from "@customTypes/Game";
5import "@css/Games.css" 5import "@css/Games.css"
6 6
7import GameCategory from '@components/GameCategory'; 7import GameCategory from "@components/GameCategory";
8 8
9interface GameEntryProps { 9interface GameEntryProps {
10 game: Game; 10 game: Game;
diff --git a/frontend/src/components/Leaderboards.tsx b/frontend/src/components/Leaderboards.tsx
index fb614fa..5d4045a 100644
--- a/frontend/src/components/Leaderboards.tsx
+++ b/frontend/src/components/Leaderboards.tsx
@@ -1,9 +1,9 @@
1import React from 'react'; 1import React from "react";
2import { Link, useNavigate } from 'react-router-dom'; 2import { Link, useNavigate } from "react-router-dom";
3 3
4import { DownloadIcon, ThreedotIcon } from '@images/Images'; 4import { DownloadIcon, ThreedotIcon } from "@images/Images";
5import { MapLeaderboard } from '@customTypes/Map'; 5import { MapLeaderboard } from "@customTypes/Map";
6import { ticks_to_time, time_ago } from '@utils/Time'; 6import { ticks_to_time, time_ago } from "@utils/Time";
7import { API } from "@api/Api"; 7import { API } from "@api/Api";
8import useMessage from "@hooks/UseMessage"; 8import useMessage from "@hooks/UseMessage";
9import "@css/Maps.css" 9import "@css/Maps.css"
@@ -46,80 +46,80 @@ const Leaderboards: React.FC<LeaderboardsProps> = ({ mapID }) => {
46 }; 46 };
47 47
48 return ( 48 return (
49 <div> 49 <div>
50 {MessageDialogComponent} 50 {MessageDialogComponent}
51 <section id='section6' className='summary2'> 51 <section id='section6' className='summary2'>
52
53 <div id='leaderboard-top'
54 style={data.map.is_coop ? { gridTemplateColumns: "7.5% 40% 7.5% 15% 15% 15%" } : { gridTemplateColumns: "7.5% 30% 10% 20% 17.5% 15%" }}
55 >
56 <span>Place</span>
57 52
58 {data.map.is_coop ? ( 53 <div id='leaderboard-top'
59 <div id='runner'> 54 style={data.map.is_coop ? { gridTemplateColumns: "7.5% 40% 7.5% 15% 15% 15%" } : { gridTemplateColumns: "7.5% 30% 10% 20% 17.5% 15%" }}
60 <span>Blue</span> 55 >
61 <span>Orange</span> 56 <span>Place</span>
62 </div> 57
63 ) : ( 58 {data.map.is_coop ? (
64 <span>Runner</span> 59 <div id='runner'>
65 )} 60 <span>Blue</span>
66 61 <span>Orange</span>
67 <span>Portals</span> 62 </div>
68 <span>Time</span> 63 ) : (
69 <span>Date</span> 64 <span>Runner</span>
70 <div id='page-number'> 65 )}
71 <div> 66
72 67 <span>Portals</span>
73 <button onClick={() => pageNumber === 1 ? null : setPageNumber(prevPageNumber => prevPageNumber - 1)} 68 <span>Time</span>
74 ><i className='triangle' style={{ position: 'relative', left: '-5px', }}></i> </button> 69 <span>Date</span>
75 <span>{data.pagination.current_page}/{data.pagination.total_pages}</span> 70 <div id='page-number'>
76 <button onClick={() => pageNumber === data.pagination.total_pages ? null : setPageNumber(prevPageNumber => prevPageNumber + 1)} 71 <div>
77 ><i className='triangle' style={{ position: 'relative', left: '5px', transform: 'rotate(180deg)' }}></i> </button> 72
73 <button onClick={() => pageNumber === 1 ? null : setPageNumber(prevPageNumber => prevPageNumber - 1)}
74 ><i className='triangle' style={{ position: "relative", left: "-5px", }}></i> </button>
75 <span>{data.pagination.current_page}/{data.pagination.total_pages}</span>
76 <button onClick={() => pageNumber === data.pagination.total_pages ? null : setPageNumber(prevPageNumber => prevPageNumber + 1)}
77 ><i className='triangle' style={{ position: "relative", left: "5px", transform: "rotate(180deg)" }}></i> </button>
78 </div>
78 </div> 79 </div>
79 </div> 80 </div>
80 </div> 81 <hr />
81 <hr /> 82 <div id='leaderboard-records'>
82 <div id='leaderboard-records'> 83 {data.records.map((r, index) => (
83 {data.records.map((r, index) => ( 84 <span className='leaderboard-record' key={index}
84 <span className='leaderboard-record' key={index} 85 style={data.map.is_coop ? { gridTemplateColumns: "3% 4.5% 40% 4% 3.5% 15% 15% 14.5%" } : { gridTemplateColumns: "3% 4.5% 30% 4% 6% 20% 17% 15%" }}
85 style={data.map.is_coop ? { gridTemplateColumns: "3% 4.5% 40% 4% 3.5% 15% 15% 14.5%" } : { gridTemplateColumns: "3% 4.5% 30% 4% 6% 20% 17% 15%" }} 86 >
86 > 87 <span>{r.placement}</span>
87 <span>{r.placement}</span> 88 <span> </span>
88 <span> </span> 89 {r.kind === "multiplayer" ? (
89 {r.kind === "multiplayer" ? ( 90 <div>
90 <div>
91 <Link to={`/users/${r.host.steam_id}`}><span><img src={r.host.avatar_link} alt='' /> &nbsp; {r.host.user_name}</span></Link> 91 <Link to={`/users/${r.host.steam_id}`}><span><img src={r.host.avatar_link} alt='' /> &nbsp; {r.host.user_name}</span></Link>
92 <Link to={`/users/${r.partner.steam_id}`}><span><img src={r.partner.avatar_link} alt='' /> &nbsp; {r.partner.user_name}</span></Link> 92 <Link to={`/users/${r.partner.steam_id}`}><span><img src={r.partner.avatar_link} alt='' /> &nbsp; {r.partner.user_name}</span></Link>
93 </div> 93 </div>
94 ) : r.kind === "singleplayer" && ( 94 ) : r.kind === "singleplayer" && (
95 <div> 95 <div>
96 <Link to={`/users/${r.user.steam_id}`}><span><img src={r.user.avatar_link} alt='' /> &nbsp; {r.user.user_name}</span></Link> 96 <Link to={`/users/${r.user.steam_id}`}><span><img src={r.user.avatar_link} alt='' /> &nbsp; {r.user.user_name}</span></Link>
97 </div> 97 </div>
98 )} 98 )}
99 99
100 <span>{r.score_count}</span> 100 <span>{r.score_count}</span>
101 <span> </span> 101 <span> </span>
102 <span className='hover-popup' popup-text={(r.score_time) + " ticks"}>{ticks_to_time(r.score_time)}</span> 102 <span className='hover-popup' popup-text={(r.score_time) + " ticks"}>{ticks_to_time(r.score_time)}</span>
103 <span className='hover-popup' popup-text={r.record_date.replace("T", ' ').split(".")[0]}>{time_ago(new Date(r.record_date.replace("T", " ").replace("Z", "")))}</span> 103 <span className='hover-popup' popup-text={r.record_date.replace("T", " ").split(".")[0]}>{time_ago(new Date(r.record_date.replace("T", " ").replace("Z", "")))}</span>
104 104
105 {r.kind === "multiplayer" ? ( 105 {r.kind === "multiplayer" ? (
106 <span> 106 <span>
107 <button onClick={() => { message("Demo Information", `Host Demo ID: ${r.host_demo_id} \nParnter Demo ID: ${r.partner_demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button> 107 <button onClick={() => { message("Demo Information", `Host Demo ID: ${r.host_demo_id} \nParnter Demo ID: ${r.partner_demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button>
108 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${r.partner_demo_id}`}><img src={DownloadIcon} alt="download" style={{ filter: "hue-rotate(160deg) contrast(60%) saturate(1000%)" }} /></button> 108 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${r.partner_demo_id}`}><img src={DownloadIcon} alt="download" style={{ filter: "hue-rotate(160deg) contrast(60%) saturate(1000%)" }} /></button>
109 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${r.host_demo_id}`}><img src={DownloadIcon} alt="download" style={{ filter: "hue-rotate(300deg) contrast(60%) saturate(1000%)" }} /></button> 109 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${r.host_demo_id}`}><img src={DownloadIcon} alt="download" style={{ filter: "hue-rotate(300deg) contrast(60%) saturate(1000%)" }} /></button>
110 </span> 110 </span>
111 ) : r.kind === "singleplayer" && ( 111 ) : r.kind === "singleplayer" && (
112 112
113 <span> 113 <span>
114 <button onClick={() => { message("Demo Information", `Demo ID: ${r.demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button> 114 <button onClick={() => { message("Demo Information", `Demo ID: ${r.demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button>
115 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${r.demo_id}`}><img src={DownloadIcon} alt="download" /></button> 115 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${r.demo_id}`}><img src={DownloadIcon} alt="download" /></button>
116 </span> 116 </span>
117 )} 117 )}
118 </span> 118 </span>
119 ))} 119 ))}
120 </div> 120 </div>
121 </section> 121 </section>
122 </div> 122 </div>
123 ); 123 );
124}; 124};
125 125
diff --git a/frontend/src/components/Login.tsx b/frontend/src/components/Login.tsx
index f1628b2..89a37e1 100644
--- a/frontend/src/components/Login.tsx
+++ b/frontend/src/components/Login.tsx
@@ -1,9 +1,9 @@
1import React from 'react'; 1import React from "react";
2import { Link, useNavigate } from 'react-router-dom'; 2import { Link, useNavigate } from "react-router-dom";
3 3
4import { ExitIcon, UserIcon, LoginIcon } from '@images/Images'; 4import { ExitIcon, UserIcon, LoginIcon } from "@images/Images";
5import { UserProfile } from '@customTypes/Profile'; 5import { UserProfile } from "@customTypes/Profile";
6import { API } from '@api/Api'; 6import { API } from "@api/Api";
7import "@css/Login.css"; 7import "@css/Login.css";
8 8
9interface LoginProps { 9interface LoginProps {
diff --git a/frontend/src/components/MapEntry.tsx b/frontend/src/components/MapEntry.tsx
index 0f494ad..88137d8 100644
--- a/frontend/src/components/MapEntry.tsx
+++ b/frontend/src/components/MapEntry.tsx
@@ -1,12 +1,12 @@
1import React from 'react'; 1import React from "react";
2import { Link } from "react-router-dom"; 2import { Link } from "react-router-dom";
3 3
4const MapEntry: React.FC = () => { 4const MapEntry: React.FC = () => {
5 return ( 5 return (
6 <div> 6 <div>
7 7
8 </div> 8 </div>
9 ) 9 )
10} 10}
11 11
12export default MapEntry; 12export default MapEntry;
diff --git a/frontend/src/components/MessageDialog.tsx b/frontend/src/components/MessageDialog.tsx
index 5c85189..ae95f8d 100644
--- a/frontend/src/components/MessageDialog.tsx
+++ b/frontend/src/components/MessageDialog.tsx
@@ -1,4 +1,4 @@
1import React from 'react'; 1import React from "react";
2 2
3import "@css/Dialog.css" 3import "@css/Dialog.css"
4 4
@@ -9,21 +9,21 @@ interface MessageDialogProps {
9}; 9};
10 10
11const MessageDialog: React.FC<MessageDialogProps> = ({ title, subtitle, onClose }) => { 11const MessageDialog: React.FC<MessageDialogProps> = ({ title, subtitle, onClose }) => {
12 return ( 12 return (
13 <div className='dimmer'> 13 <div className='dimmer'>
14 <div className='dialog'> 14 <div className='dialog'>
15 <div className='dialog-element dialog-header'> 15 <div className='dialog-element dialog-header'>
16 <span>{title}</span> 16 <span>{title}</span>
17 </div>
18 <div className='dialog-element dialog-description'>
19 <span>{subtitle}</span>
20 </div>
21 <div className='dialog-element dialog-btns-container'>
22 <button onClick={onClose}>Close</button>
23 </div>
24 </div>
25 </div> 17 </div>
26 ) 18 <div className='dialog-element dialog-description'>
19 <span>{subtitle}</span>
20 </div>
21 <div className='dialog-element dialog-btns-container'>
22 <button onClick={onClose}>Close</button>
23 </div>
24 </div>
25 </div>
26 )
27} 27}
28 28
29export default MessageDialog; 29export default MessageDialog;
diff --git a/frontend/src/components/MessageDialogLoad.tsx b/frontend/src/components/MessageDialogLoad.tsx
index 966e064..000a2ab 100644
--- a/frontend/src/components/MessageDialogLoad.tsx
+++ b/frontend/src/components/MessageDialogLoad.tsx
@@ -1,4 +1,4 @@
1import React from 'react'; 1import React from "react";
2 2
3import "@css/Dialog.css" 3import "@css/Dialog.css"
4 4
@@ -8,22 +8,22 @@ interface MessageDialogLoadProps {
8}; 8};
9 9
10const MessageDialogLoad: React.FC<MessageDialogLoadProps> = ({ title, onClose }) => { 10const MessageDialogLoad: React.FC<MessageDialogLoadProps> = ({ title, onClose }) => {
11 return ( 11 return (
12 <div className='dimmer'> 12 <div className='dimmer'>
13 <div className='dialog'> 13 <div className='dialog'>
14 <div className='dialog-element dialog-header'> 14 <div className='dialog-element dialog-header'>
15 <span>{title}</span> 15 <span>{title}</span>
16 </div> 16 </div>
17 <div className='dialog-element dialog-description'> 17 <div className='dialog-element dialog-description'>
18 <div style={{display: "flex", justifyContent: "center"}}> 18 <div style={{display: "flex", justifyContent: "center"}}>
19 <span className="loader"></span> 19 <span className="loader"></span>
20 </div> 20 </div>
21 </div> 21 </div>
22 <div className='dialog-element dialog-btns-container'> 22 <div className='dialog-element dialog-btns-container'>
23 </div>
24 </div>
25 </div> 23 </div>
26 ) 24 </div>
25 </div>
26 )
27} 27}
28 28
29export default MessageDialogLoad; 29export default MessageDialogLoad;
diff --git a/frontend/src/components/ModMenu.tsx b/frontend/src/components/ModMenu.tsx
index 925b8a8..19ce0ce 100644
--- a/frontend/src/components/ModMenu.tsx
+++ b/frontend/src/components/ModMenu.tsx
@@ -1,12 +1,12 @@
1import React from 'react'; 1import React from "react";
2import ReactMarkdown from 'react-markdown'; 2import ReactMarkdown from "react-markdown";
3import { useNavigate } from 'react-router-dom'; 3import { useNavigate } from "react-router-dom";
4 4
5import { MapSummary } from '@customTypes/Map'; 5import { MapSummary } from "@customTypes/Map";
6import { ModMenuContent } from '@customTypes/Content'; 6import { ModMenuContent } from "@customTypes/Content";
7import { API } from '@api/Api'; 7import { API } from "@api/Api";
8import "@css/ModMenu.css" 8import "@css/ModMenu.css"
9import useConfirm from '@hooks/UseConfirm'; 9import useConfirm from "@hooks/UseConfirm";
10 10
11interface ModMenuProps { 11interface ModMenuProps {
12 token?: string; 12 token?: string;
@@ -55,10 +55,10 @@ const ModMenu: React.FC<ModMenuProps> = ({ token, data, selectedRun, mapID }) =>
55 width *= 320 / height; 55 width *= 320 / height;
56 height = 320; 56 height = 320;
57 } 57 }
58 const canvas = document.createElement('canvas'); 58 const canvas = document.createElement("canvas");
59 canvas.width = width; 59 canvas.width = width;
60 canvas.height = height; 60 canvas.height = height;
61 canvas.getContext('2d')!.drawImage(img, 0, 0, width, height); 61 canvas.getContext("2d")!.drawImage(img, 0, 0, width, height);
62 resolve(canvas.toDataURL(file.type, 0.6)); 62 resolve(canvas.toDataURL(file.type, 0.6));
63 }; 63 };
64 } 64 }
diff --git a/frontend/src/components/RankingEntry.tsx b/frontend/src/components/RankingEntry.tsx
index b899965..9ad9e1c 100644
--- a/frontend/src/components/RankingEntry.tsx
+++ b/frontend/src/components/RankingEntry.tsx
@@ -1,6 +1,6 @@
1import React from 'react'; 1import React from "react";
2import { Link } from "react-router-dom"; 2import { Link } from "react-router-dom";
3import { RankingType, SteamRanking, SteamRankingType } from '@customTypes/Ranking'; 3import { RankingType, SteamRankingType } from "@customTypes/Ranking";
4 4
5enum RankingCategories { 5enum RankingCategories {
6 rankings_overall, 6 rankings_overall,
@@ -14,33 +14,33 @@ interface RankingEntryProps {
14}; 14};
15 15
16const RankingEntry: React.FC<RankingEntryProps> = (prop) => { 16const RankingEntry: React.FC<RankingEntryProps> = (prop) => {
17 if ("placement" in prop.curRankingData) { 17 if ("placement" in prop.curRankingData) {
18 return ( 18 return (
19 <div className='leaderboard-entry'> 19 <div className='leaderboard-entry'>
20 <span>{prop.curRankingData.placement}</span> 20 <span>{prop.curRankingData.placement}</span>
21 <div> 21 <div>
22 <Link to={`/users/${prop.curRankingData.user.steam_id}`}> 22 <Link to={`/users/${prop.curRankingData.user.steam_id}`}>
23 <img src={prop.curRankingData.user.avatar_link}></img> 23 <img src={prop.curRankingData.user.avatar_link}></img>
24 <span>{prop.curRankingData.user.user_name}</span> 24 <span>{prop.curRankingData.user.user_name}</span>
25 </Link> 25 </Link>
26 </div> 26 </div>
27 <span>{prop.curRankingData.total_score}</span> 27 <span>{prop.curRankingData.total_score}</span>
28 </div> 28 </div>
29 ) 29 )
30 } else { 30 } else {
31 return ( 31 return (
32 <div className='leaderboard-entry'> 32 <div className='leaderboard-entry'>
33 <span>{prop.currentLeaderboardType == RankingCategories.rankings_singleplayer ? prop.curRankingData.sp_rank : prop.currentLeaderboardType == RankingCategories.rankings_multiplayer ? prop.curRankingData.mp_rank : prop.curRankingData.overall_rank}</span> 33 <span>{prop.currentLeaderboardType == RankingCategories.rankings_singleplayer ? prop.curRankingData.sp_rank : prop.currentLeaderboardType == RankingCategories.rankings_multiplayer ? prop.curRankingData.mp_rank : prop.curRankingData.overall_rank}</span>
34 <div> 34 <div>
35 <Link to={`/users/${prop.curRankingData.steam_id}`}> 35 <Link to={`/users/${prop.curRankingData.steam_id}`}>
36 <img src={prop.curRankingData.avatar_link}></img> 36 <img src={prop.curRankingData.avatar_link}></img>
37 <span>{prop.curRankingData.user_name}</span> 37 <span>{prop.curRankingData.user_name}</span>
38 </Link> 38 </Link>
39 </div> 39 </div>
40 <span>{prop.currentLeaderboardType == RankingCategories.rankings_singleplayer ? prop.curRankingData.sp_score : prop.currentLeaderboardType == RankingCategories.rankings_multiplayer ? prop.curRankingData.mp_score : prop.curRankingData.overall_score}</span> 40 <span>{prop.currentLeaderboardType == RankingCategories.rankings_singleplayer ? prop.curRankingData.sp_score : prop.currentLeaderboardType == RankingCategories.rankings_multiplayer ? prop.curRankingData.mp_score : prop.curRankingData.overall_score}</span>
41 </div> 41 </div>
42 ) 42 )
43 } 43 }
44} 44}
45 45
46export default RankingEntry; 46export default RankingEntry;
diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx
index f972c6f..eef5bca 100644
--- a/frontend/src/components/Sidebar.tsx
+++ b/frontend/src/components/Sidebar.tsx
@@ -1,11 +1,11 @@
1import React from 'react'; 1import React from "react";
2import { Link, useLocation } from 'react-router-dom'; 2import { Link, useLocation } from "react-router-dom";
3 3
4import { BookIcon, FlagIcon, HelpIcon, HomeIcon, LogoIcon, PortalIcon, SearchIcon, UploadIcon } from '@images/Images'; 4import { BookIcon, FlagIcon, HelpIcon, HomeIcon, LogoIcon, PortalIcon, SearchIcon, UploadIcon } from "@images/Images";
5import Login from '@components/Login'; 5import Login from "@components/Login";
6import { UserProfile } from '@customTypes/Profile'; 6import { UserProfile } from "@customTypes/Profile";
7import { Search } from '@customTypes/Search'; 7import { Search } from "@customTypes/Search";
8import { API } from '@api/Api'; 8import { API } from "@api/Api";
9import "@css/Sidebar.css"; 9import "@css/Sidebar.css";
10 10
11interface SidebarProps { 11interface SidebarProps {
@@ -39,7 +39,7 @@ const Sidebar: React.FC<SidebarProps> = ({ setToken, profile, setProfile, onUplo
39 }; 39 };
40 40
41 const _handle_sidebar_hide = () => { 41 const _handle_sidebar_hide = () => {
42 var btn = document.querySelectorAll("button.sidebar-button") as NodeListOf<HTMLElement> 42 const btn = document.querySelectorAll("button.sidebar-button") as NodeListOf<HTMLElement>
43 const span = document.querySelectorAll("button.sidebar-button>span") as NodeListOf<HTMLElement> 43 const span = document.querySelectorAll("button.sidebar-button>span") as NodeListOf<HTMLElement>
44 const side = document.querySelector("#sidebar-list") as HTMLElement; 44 const side = document.querySelector("#sidebar-list") as HTMLElement;
45 const searchbar = document.querySelector("#searchbar") as HTMLInputElement; 45 const searchbar = document.querySelector("#searchbar") as HTMLInputElement;
@@ -140,13 +140,13 @@ const Sidebar: React.FC<SidebarProps> = ({ setToken, profile, setProfile, onUplo
140 </div> 140 </div>
141 </div> 141 </div>
142 </Link> 142 </Link>
143 <button id='hamburger-menu' onClick={_toggle_mobile_menu} className={isMobileMenuOpen ? 'open' : ''}> 143 <button id='hamburger-menu' onClick={_toggle_mobile_menu} className={isMobileMenuOpen ? "open" : ""}>
144 <span></span> 144 <span></span>
145 <span></span> 145 <span></span>
146 <span></span> 146 <span></span>
147 </button> 147 </button>
148 </div> 148 </div>
149 <div id='sidebar' className={isMobileMenuOpen ? 'mobile-open' : ''}> 149 <div id='sidebar' className={isMobileMenuOpen ? "mobile-open" : ""}>
150 <Link to="/" tabIndex={-1}> 150 <Link to="/" tabIndex={-1}>
151 <div id='logo'> {/* logo */} 151 <div id='logo'> {/* logo */}
152 <img src={LogoIcon} alt="" height={"80px"} /> 152 <img src={LogoIcon} alt="" height={"80px"} />
@@ -204,7 +204,7 @@ const Sidebar: React.FC<SidebarProps> = ({ setToken, profile, setProfile, onUplo
204 </Link> 204 </Link>
205 </div> 205 </div>
206 </div> 206 </div>
207 <div id='search-panel' className={isMobileSearchOpen ? 'mobile-search-open' : ''}> 207 <div id='search-panel' className={isMobileSearchOpen ? "mobile-search-open" : ""}>
208 <input type="text" id='searchbar' placeholder='Search for map or a player...' onChange={(e) => _handle_search_change(e.target.value)} /> 208 <input type="text" id='searchbar' placeholder='Search for map or a player...' onChange={(e) => _handle_search_change(e.target.value)} />
209 <div className='mobile-search-header'> 209 <div className='mobile-search-header'>
210 <button className='mobile-search-close' onClick={_close_mobile_search}>✕</button> 210 <button className='mobile-search-close' onClick={_close_mobile_search}>✕</button>
@@ -220,15 +220,15 @@ const Sidebar: React.FC<SidebarProps> = ({ setToken, profile, setProfile, onUplo
220 </Link> 220 </Link>
221 ))} 221 ))}
222 {searchData?.players.map((q, index) => 222 {searchData?.players.map((q, index) =>
223 ( 223 (
224 <Link to={ 224 <Link to={
225 profile && q.steam_id === profile.steam_id ? `/profile` : 225 profile && q.steam_id === profile.steam_id ? "/profile" :
226 `/users/${q.steam_id}` 226 `/users/${q.steam_id}`
227 } className='search-player' key={index} onClick={_close_mobile_search}> 227 } className='search-player' key={index} onClick={_close_mobile_search}>
228 <img src={q.avatar_link} alt='pfp'></img> 228 <img src={q.avatar_link} alt='pfp'></img>
229 <span style={{ fontSize: `${36 - q.user_name.length * 0.8}px` }}>{q.user_name}</span> 229 <span style={{ fontSize: `${36 - q.user_name.length * 0.8}px` }}>{q.user_name}</span>
230 </Link> 230 </Link>
231 ))} 231 ))}
232 232
233 </div> 233 </div>
234 </div> 234 </div>
diff --git a/frontend/src/components/Summary.tsx b/frontend/src/components/Summary.tsx
index 7da2f1e..72b5bf0 100644
--- a/frontend/src/components/Summary.tsx
+++ b/frontend/src/components/Summary.tsx
@@ -1,7 +1,7 @@
1import React from 'react'; 1import React from "react";
2import ReactMarkdown from 'react-markdown'; 2import ReactMarkdown from "react-markdown";
3 3
4import { MapSummary } from '@customTypes/Map'; 4import { MapSummary } from "@customTypes/Map";
5import "@css/Maps.css" 5import "@css/Maps.css"
6 6
7interface SummaryProps { 7interface SummaryProps {
@@ -16,7 +16,7 @@ const Summary: React.FC<SummaryProps> = ({ selectedRun, setSelectedRun, data })
16 const [historySelected, setHistorySelected] = React.useState<boolean>(false); 16 const [historySelected, setHistorySelected] = React.useState<boolean>(false);
17 17
18 function _select_run(idx: number, category_id: number) { 18 function _select_run(idx: number, category_id: number) {
19 let r = document.querySelectorAll("button.record"); 19 const r = document.querySelectorAll("button.record");
20 r.forEach(e => (e as HTMLElement).style.backgroundColor = "#2b2e46"); 20 r.forEach(e => (e as HTMLElement).style.backgroundColor = "#2b2e46");
21 (r[idx] as HTMLElement).style.backgroundColor = "#161723" 21 (r[idx] as HTMLElement).style.backgroundColor = "#161723"
22 22
@@ -66,7 +66,7 @@ const Summary: React.FC<SummaryProps> = ({ selectedRun, setSelectedRun, data })
66 style={data.map.image === "" ? { backgroundColor: "#202232" } : {}}> 66 style={data.map.image === "" ? { backgroundColor: "#202232" } : {}}>
67 <img src={data.map.image} alt="" id='category-image'></img> 67 <img src={data.map.image} alt="" id='category-image'></img>
68 <p><span className='portal-count'>{data.summary.routes[selectedRun].history.score_count}</span> 68 <p><span className='portal-count'>{data.summary.routes[selectedRun].history.score_count}</span>
69 {data.summary.routes[selectedRun].history.score_count === 1 ? ` portal` : ` portals`}</p> 69 {data.summary.routes[selectedRun].history.score_count === 1 ? " portal" : " portals"}</p>
70 {data.map.is_coop ? // TODO: make this part dynamic 70 {data.map.is_coop ? // TODO: make this part dynamic
71 ( 71 (
72 <span style={{ gridTemplateColumns: "1fr 1fr 1fr" }}> 72 <span style={{ gridTemplateColumns: "1fr 1fr 1fr" }}>
@@ -109,7 +109,7 @@ const Summary: React.FC<SummaryProps> = ({ selectedRun, setSelectedRun, data })
109 _select_run(index, r.category.id); 109 _select_run(index, r.category.id);
110 }}> 110 }}>
111 <span>{new Date(r.history.date).toLocaleDateString( 111 <span>{new Date(r.history.date).toLocaleDateString(
112 "en-US", { month: 'long', day: 'numeric', year: 'numeric' } 112 "en-US", { month: "long", day: "numeric", year: "numeric" }
113 )}</span> 113 )}</span>
114 <span>{r.history.score_count}</span> 114 <span>{r.history.score_count}</span>
115 <span>{r.history.runner_name}</span> 115 <span>{r.history.runner_name}</span>
diff --git a/frontend/src/components/UploadRunDialog.tsx b/frontend/src/components/UploadRunDialog.tsx
index c02fdb8..dd609a1 100644
--- a/frontend/src/components/UploadRunDialog.tsx
+++ b/frontend/src/components/UploadRunDialog.tsx
@@ -1,15 +1,15 @@
1import React from 'react'; 1import React from "react";
2import { UploadRunContent } from '@customTypes/Content'; 2import { UploadRunContent } from "@customTypes/Content";
3import { ScoreboardTempUpdate, SourceDemoParser, NetMessages } from '@nekz/sdp'; 3import { ScoreboardTempUpdate, SourceDemoParser, NetMessages } from "@nekz/sdp";
4 4
5import '@css/UploadRunDialog.css'; 5import "@css/UploadRunDialog.css";
6import { Game } from '@customTypes/Game'; 6import { Game } from "@customTypes/Game";
7import { API } from '@api/Api'; 7import { API } from "@api/Api";
8import { useNavigate } from 'react-router-dom'; 8import { useNavigate } from "react-router-dom";
9import useMessage from '@hooks/UseMessage'; 9import useMessage from "@hooks/UseMessage";
10import useConfirm from '@hooks/UseConfirm'; 10import useConfirm from "@hooks/UseConfirm";
11import useMessageLoad from "@hooks/UseMessageLoad"; 11import useMessageLoad from "@hooks/UseMessageLoad";
12import { MapNames } from '@customTypes/MapNames'; 12import { MapNames } from "@customTypes/MapNames";
13 13
14interface UploadRunDialogProps { 14interface UploadRunDialogProps {
15 token?: string; 15 token?: string;